Update fluid to 7c22cd49a7eb76ae1d9606672ee467fb52383de0 (#2407) (#2504)
authorArtemy Skrebkov <artemy.skrebkov@intel.com>
Fri, 2 Oct 2020 10:15:10 +0000 (13:15 +0300)
committerGitHub <noreply@github.com>
Fri, 2 Oct 2020 10:15:10 +0000 (13:15 +0300)
* Update fluid to 7c22cd49a7eb76ae1d9606672ee467fb52383de0

   OpenCV 4.5.0

* Fix windows build

187 files changed:
inference-engine/thirdparty/fluid/checksum.txt
inference-engine/thirdparty/fluid/modules/gapi/CMakeLists.txt
inference-engine/thirdparty/fluid/modules/gapi/cmake/standalone.cmake
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/core.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/core.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/video.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/core.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidbuffer.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garg.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garray.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcommon.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompiled.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompoundkernel.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcomputation.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gframe.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gkernel.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmat.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmetaarg.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gopaque.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gproto.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gscalar.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtype_traits.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtyped.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/imgproc.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/ie.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/parsers.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/ocl/core.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/opencv_includes.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/operators.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/assert.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/convert.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/cvdefs.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/exports.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/mat.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/plaidml/core.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render_types.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/rmat.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/type_traits.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/variant.hpp
inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/video.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/misc/python/pyopencv_gapi.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/misc/python/shadow_gapi.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/misc/python/test/test_gapi_core.py [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/misc/python/test/test_gapi_sample_pipelines.py [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests.hpp
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests_inl.hpp
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_render_perf_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_render_perf_tests.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_render_perf_tests_inl.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_video_perf_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_video_perf_tests.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_video_perf_tests_inl.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_core_perf_tests_cpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_core_perf_tests_fluid.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_video_perf_tests_cpu.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_core_perf_tests_gpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_imgproc_perf_tests_gpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/perf/perf_precomp.hpp
inference-engine/thirdparty/fluid/modules/gapi/perf/render/gapi_render_perf_tests_ocv.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/samples/dynamic_graph.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/samples/gaze_estimation.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/samples/privacy_masking_camera.cpp
inference-engine/thirdparty/fluid/modules/gapi/scripts/measure_privacy_masking.py [new file with mode: 0755]
inference-engine/thirdparty/fluid/modules/gapi/src/api/garray.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gbackend.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation_priv.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gframe.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/api/gmat.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gopaque.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gorigin.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gorigin.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto_priv.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/gscalar.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_core.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_imgproc.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_nnparsers.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_video.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/api/operators.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/api/s11n.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gbackend.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gcompoundkernel.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/serialization.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/serialization.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpucore.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuimgproc.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpukernel.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuvideo.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gnnparsers.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gnnparsers.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer_priv.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidcore.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/ie/giebackend.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/ie/giebackend.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/ie/giebackend/giewrapper.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/backends/ie/giebackend/giewrapper.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/src/backends/ocl/goclbackend.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/ocl/goclbackend.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/ocl/goclimgproc.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/plaidml/gplaidmlbackend.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/plaidml/gplaidmlcore.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/backends/render/grenderocvbackend.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled_priv.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodelbuilder.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gobjref.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/kernels.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/meta.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/transformations.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/executor/gstreamingexecutor.cpp
inference-engine/thirdparty/fluid/modules/gapi/src/executor/gstreamingexecutor.hpp
inference-engine/thirdparty/fluid/modules/gapi/src/logger.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_compoundkernel_tests.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests_inl.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests_inl.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_parsers_tests_common.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_tests_common.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests_common.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests_inl.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_cpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_fluid.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_fluid.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_test_utils.hpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_cpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_fluid.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_video_tests_cpu.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_array_tests.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_async_test.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_compile_args_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_desc_tests.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_frame_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_kernel_tests.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_opaque_tests.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_plaidml_pipelines.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_sample_pipelines.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_transform_tests.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gapi_typed_tests.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_core_tests_gpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_imgproc_tests_gpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_operators_tests_gpu.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/infer/gapi_infer_ie_test.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/infer/gapi_infer_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_dynamic_graph.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_garg_test.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_proto_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/opencl_kernels_test_gapi.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/own/mat_tests.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/rmat/rmat_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/rmat/rmat_view_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/s11n/gapi_s11n_tests.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp [new file with mode: 0644]
inference-engine/thirdparty/fluid/modules/gapi/test/streaming/gapi_streaming_tests.cpp
inference-engine/thirdparty/fluid/modules/gapi/test/test_precomp.hpp
inference-engine/thirdparty/fluid/modules/gapi/test/util/variant_tests.cpp
inference-engine/thirdparty/fluid/revision.txt

index 519ebba..76d4577 100644 (file)
@@ -13,14 +13,29 @@ if(NOT TARGET ade)
   return()
 endif()
 
+if(INF_ENGINE_TARGET)
+  ocv_option(OPENCV_GAPI_INF_ENGINE "Build GraphAPI module with Inference Engine support" ON)
+endif()
+
 set(the_description "OpenCV G-API Core Module")
 
-ocv_add_module(gapi opencv_imgproc)
+ocv_add_module(gapi
+    REQUIRED
+      opencv_imgproc
+    OPTIONAL
+      opencv_video
+    WRAP
+      python
+)
 
 if(MSVC)
   # Disable obsollete warning C4503 popping up on MSVC <<2017
   # https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4503?view=vs-2019
   ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4503)
+  if (OPENCV_GAPI_INF_ENGINE AND NOT INF_ENGINE_RELEASE VERSION_GREATER "2021000000")
+    # Disable IE deprecated code warning C4996 for releases < 2021.1
+    ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4996)
+  endif()
 endif()
 
 file(GLOB gapi_ext_hdrs
@@ -46,6 +61,7 @@ set(gapi_srcs
     src/api/garray.cpp
     src/api/gopaque.cpp
     src/api/gscalar.cpp
+    src/api/gframe.cpp
     src/api/gkernel.cpp
     src/api/gbackend.cpp
     src/api/gproto.cpp
@@ -55,6 +71,8 @@ set(gapi_srcs
     src/api/operators.cpp
     src/api/kernels_core.cpp
     src/api/kernels_imgproc.cpp
+    src/api/kernels_video.cpp
+    src/api/kernels_nnparsers.cpp
     src/api/render.cpp
     src/api/render_ocv.cpp
     src/api/ginfer.cpp
@@ -87,7 +105,9 @@ set(gapi_srcs
     src/backends/cpu/gcpubackend.cpp
     src/backends/cpu/gcpukernel.cpp
     src/backends/cpu/gcpuimgproc.cpp
+    src/backends/cpu/gcpuvideo.cpp
     src/backends/cpu/gcpucore.cpp
+    src/backends/cpu/gnnparsers.cpp
 
     # Fluid Backend (also built-in, FIXME:move away)
     src/backends/fluid/gfluidbuffer.cpp
@@ -105,6 +125,7 @@ set(gapi_srcs
     # IE Backend. FIXME: should be included by CMake
     # if and only if IE support is enabled
     src/backends/ie/giebackend.cpp
+    src/backends/ie/giebackend/giewrapper.cpp
 
     # Render Backend.
     src/backends/render/grenderocvbackend.cpp
@@ -117,6 +138,10 @@ set(gapi_srcs
     # Compound
     src/backends/common/gcompoundbackend.cpp
     src/backends/common/gcompoundkernel.cpp
+
+    # Serialization API and routines
+    src/api/s11n.cpp
+    src/backends/common/serialization.cpp
     )
 
 ocv_add_dispatched_file(backends/fluid/gfluidimgproc_func SSE4_1 AVX2)
@@ -132,12 +157,20 @@ ocv_module_include_directories("${CMAKE_CURRENT_LIST_DIR}/src")
 
 ocv_create_module()
 
-ocv_target_link_libraries(${the_module} PRIVATE ade ${INF_ENGINE_TARGET})
+ocv_target_link_libraries(${the_module} PRIVATE ade)
+if(OPENCV_GAPI_INF_ENGINE)
+  ocv_target_link_libraries(${the_module} PRIVATE ${INF_ENGINE_TARGET})
+endif()
 if(HAVE_TBB)
   ocv_target_link_libraries(${the_module} PRIVATE tbb)
 endif()
 
-ocv_add_accuracy_tests(${INF_ENGINE_TARGET})
+set(__test_extra_deps "")
+if(OPENCV_GAPI_INF_ENGINE)
+  list(APPEND __test_extra_deps ${INF_ENGINE_TARGET})
+endif()
+ocv_add_accuracy_tests(${__test_extra_deps})
+
 # FIXME: test binary is linked with ADE directly since ADE symbols
 # are not exported from libopencv_gapi.so in any form - thus
 # there're two copies of ADE code in memory when tests run (!)
@@ -165,5 +198,10 @@ if(HAVE_PLAIDML)
   ocv_target_include_directories(${the_module} SYSTEM PRIVATE ${PLAIDML_INCLUDE_DIRS})
 endif()
 
+if(WIN32)
+  # Required for htonl/ntohl on Windows
+  ocv_target_link_libraries(${the_module} PRIVATE wsock32 ws2_32)
+endif()
+
 ocv_add_perf_tests()
 ocv_add_samples()
index f448d97..ca54697 100644 (file)
@@ -45,3 +45,8 @@ if(MSVC)
 endif()
 
 target_link_libraries(${FLUID_TARGET} PRIVATE ade)
+
+if(WIN32)
+  # Required for htonl/ntohl on Windows
+  target_link_libraries(${FLUID_TARGET} PRIVATE wsock32 ws2_32)
+endif()
index 00400a8..8ecba2b 100644 (file)
@@ -31,7 +31,7 @@ namespace core {
     using GMat2 = std::tuple<GMat,GMat>;
     using GMat3 = std::tuple<GMat,GMat,GMat>; // FIXME: how to avoid this?
     using GMat4 = std::tuple<GMat,GMat,GMat,GMat>;
-    using GMatScalar = std::tuple<GMat, GScalar>;
+    using GMatScalar  = std::tuple<GMat, GScalar>;
 
     G_TYPED_KERNEL(GAdd, <GMat(GMat, GMat, int)>, "org.opencv.core.math.add") {
         static GMatDesc outMeta(GMatDesc a, GMatDesc b, int ddepth) {
@@ -392,10 +392,10 @@ namespace core {
             }
             else
             {
-                GAPI_Assert(fx != 0. && fy != 0.);
-                return in.withSize
-                    (Size(static_cast<int>(round(in.size.width  * fx)),
-                          static_cast<int>(round(in.size.height * fy))));
+                int outSz_w = static_cast<int>(round(in.size.width  * fx));
+                int outSz_h = static_cast<int>(round(in.size.height * fy));
+                GAPI_Assert(outSz_w > 0 && outSz_h > 0);
+                return in.withSize(Size(outSz_w, outSz_h));
             }
         }
     };
@@ -501,6 +501,18 @@ namespace core {
             return in.withType(in.depth, in.chan).withSize(dsize);
         }
     };
+
+    G_TYPED_KERNEL(GSize, <GOpaque<Size>(GMat)>, "org.opencv.core.size") {
+        static GOpaqueDesc outMeta(const GMatDesc&) {
+            return empty_gopaque_desc();
+        }
+    };
+
+    G_TYPED_KERNEL(GSizeR, <GOpaque<Size>(GOpaque<Rect>)>, "org.opencv.core.sizeR") {
+        static GOpaqueDesc outMeta(const GOpaqueDesc&) {
+            return empty_gopaque_desc();
+        }
+    };
 }
 
 //! @addtogroup gapi_math
@@ -528,7 +540,7 @@ Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref
 @param ddepth optional depth of the output matrix.
 @sa sub, addWeighted
 */
-GAPI_EXPORTS GMat add(const GMat& src1, const GMat& src2, int ddepth = -1);
+GAPI_EXPORTS_W GMat add(const GMat& src1, const GMat& src2, int ddepth = -1);
 
 /** @brief Calculates the per-element sum of matrix and given scalar.
 
@@ -744,7 +756,7 @@ Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref
 @note Function textual ID is "org.opencv.core.math.mean"
 @param src input matrix.
 */
-GAPI_EXPORTS GScalar mean(const GMat& src);
+GAPI_EXPORTS_W GScalar mean(const GMat& src);
 
 /** @brief Calculates x and y coordinates of 2D vectors from their magnitude and angle.
 
@@ -1434,7 +1446,7 @@ All output matrices must be in @ref CV_8UC1.
 @sa merge3, merge4
 */
 GAPI_EXPORTS std::tuple<GMat, GMat, GMat,GMat> split4(const GMat& src);
-GAPI_EXPORTS std::tuple<GMat, GMat, GMat> split3(const GMat& src);
+GAPI_EXPORTS_W std::tuple<GMat, GMat, GMat> split3(const GMat& src);
 
 /** @brief Applies a generic geometrical transformation to an image.
 
@@ -1720,6 +1732,24 @@ GAPI_EXPORTS GMat warpAffine(const GMat& src, const Mat& M, const Size& dsize, i
                              int borderMode = cv::BORDER_CONSTANT, const Scalar& borderValue = Scalar());
 //! @} gapi_transform
 
+/** @brief Gets dimensions from Mat.
+
+@note Function textual ID is "org.opencv.core.size"
+
+@param src Input tensor
+@return Size (tensor dimensions).
+*/
+GAPI_EXPORTS GOpaque<Size> size(const GMat& src);
+
+/** @overload
+Gets dimensions from rectangle.
+
+@note Function textual ID is "org.opencv.core.sizeR"
+
+@param r Input rectangle.
+@return Size (rectangle dimensions).
+*/
+GAPI_EXPORTS GOpaque<Size> size(const GOpaque<Rect>& r);
 } //namespace gapi
 } //namespace cv
 
index ffd3596..ac08f91 100644 (file)
@@ -16,7 +16,7 @@ namespace gapi {
 namespace core {
 namespace cpu {
 
-GAPI_EXPORTS GKernelPackage kernels();
+GAPI_EXPORTS_W cv::gapi::GKernelPackage kernels();
 
 } // namespace cpu
 } // namespace core
index 59090cc..86ceace 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018-2019 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GCPUKERNEL_HPP
@@ -17,7 +17,7 @@
 #include <opencv2/gapi/gcommon.hpp>
 #include <opencv2/gapi/gkernel.hpp>
 #include <opencv2/gapi/garg.hpp>
-#include <opencv2/gapi/own/convert.hpp> //to_ocv
+#include <opencv2/gapi/gmetaarg.hpp>
 #include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
 #include <opencv2/gapi/util/util.hpp>
 
@@ -96,8 +96,8 @@ public:
     const T& inArg(int input) { return m_args.at(input).get<T>(); }
 
     // Syntax sugar
-    const cv::gapi::own::Mat&   inMat(int input);
-    cv::gapi::own::Mat&         outMatR(int output); // FIXME: Avoid cv::gapi::own::Mat m = ctx.outMatR()
+    const cv::Mat&   inMat(int input);
+    cv::Mat&         outMatR(int output); // FIXME: Avoid cv::Mat m = ctx.outMatR()
 
     const cv::Scalar& inVal(int input);
     cv::Scalar& outValR(int output); // FIXME: Avoid cv::Scalar s = ctx.outValR()
@@ -110,11 +110,17 @@ public:
         return outOpaqueRef(output).wref<T>();
     }
 
+    GArg state()
+    {
+        return m_state;
+    }
+
 protected:
     detail::VectorRef& outVecRef(int output);
     detail::OpaqueRef& outOpaqueRef(int output);
 
     std::vector<GArg> m_args;
+    GArg m_state;
 
     //FIXME: avoid conversion of arguments from internal representation to OpenCV one on each call
     //to OCV kernel. (This can be achieved by a two single time conversions in GCPUExecutable::run,
@@ -128,16 +134,19 @@ protected:
 class GAPI_EXPORTS GCPUKernel
 {
 public:
-    // This function is kernel's execution entry point (does the processing work)
-    using F = std::function<void(GCPUContext &)>;
+    // This function is a kernel's execution entry point (does the processing work)
+    using RunF = std::function<void(GCPUContext &)>;
+    // This function is a stateful kernel's setup routine (configures state)
+    using SetupF = std::function<void(const GMetaArgs &, const GArgs &,
+                                      GArg &, const GCompileArgs &)>;
 
     GCPUKernel();
-    explicit GCPUKernel(const F& f);
+    GCPUKernel(const RunF& runF, const SetupF& setupF = nullptr);
 
-    void apply(GCPUContext &ctx);
+    RunF m_runF = nullptr;
+    SetupF m_setupF = nullptr;
 
-protected:
-    F m_f;
+    bool m_isStateful = false;
 };
 
 // FIXME: This is an ugly ad-hoc implementation. TODO: refactor
@@ -147,12 +156,16 @@ namespace detail
 template<class T> struct get_in;
 template<> struct get_in<cv::GMat>
 {
-    static cv::Mat    get(GCPUContext &ctx, int idx) { return to_ocv(ctx.inMat(idx)); }
+    static cv::Mat    get(GCPUContext &ctx, int idx) { return ctx.inMat(idx); }
 };
 template<> struct get_in<cv::GMatP>
 {
     static cv::Mat    get(GCPUContext &ctx, int idx) { return get_in<cv::GMat>::get(ctx, idx); }
 };
+template<> struct get_in<cv::GFrame>
+{
+    static cv::Mat    get(GCPUContext &ctx, int idx) { return get_in<cv::GMat>::get(ctx, idx); }
+};
 template<> struct get_in<cv::GScalar>
 {
     static cv::Scalar get(GCPUContext &ctx, int idx) { return ctx.inVal(idx); }
@@ -192,7 +205,7 @@ template<class T> struct get_in
 };
 
 struct tracked_cv_mat{
-    tracked_cv_mat(cv::gapi::own::Mat& m) : r{to_ocv(m)}, original_data{m.data} {}
+    tracked_cv_mat(cv::Mat& m) : r{m}, original_data{m.data} {}
     cv::Mat r;
     uchar* original_data;
 
@@ -252,6 +265,12 @@ template<typename U> struct get_out<cv::GArray<U>>
         return ctx.outVecR<U>(idx);
     }
 };
+
+//FIXME(dm): GArray<Mat>/GArray<GMat> conversion should be done more gracefully in the system
+template<> struct get_out<cv::GArray<cv::GMat> >: public get_out<cv::GArray<cv::Mat> >
+{
+};
+
 template<typename U> struct get_out<cv::GOpaque<U>>
 {
     static U& get(GCPUContext &ctx, int idx)
@@ -260,12 +279,73 @@ template<typename U> struct get_out<cv::GOpaque<U>>
     }
 };
 
+template<typename, typename>
+struct OCVSetupHelper;
+
+template<typename Impl, typename... Ins>
+struct OCVSetupHelper<Impl, std::tuple<Ins...>>
+{
+    // Using 'auto' return type and 'decltype' specifier in both 'setup_impl' versions
+    // to check existence of required 'Impl::setup' functions.
+    // While 'decltype' specifier accepts expression we pass expression with 'comma-operator'
+    // where first operand of comma-operator is call attempt to desired 'Impl::setup' and
+    // the second operand is 'void()' expression.
+    //
+    // SFINAE for 'Impl::setup' which accepts compile arguments.
+    template<int... IIs>
+    static auto setup_impl(const GMetaArgs &metaArgs, const GArgs &args,
+                           GArg &state, const GCompileArgs &compileArgs,
+                           detail::Seq<IIs...>) ->
+        decltype(Impl::setup(detail::get_in_meta<Ins>(metaArgs, args, IIs)...,
+                             std::declval<typename std::add_lvalue_reference<
+                                              std::shared_ptr<typename Impl::State>
+                                                                            >::type
+                                         >(),
+                            compileArgs)
+                 , void())
+    {
+        // TODO: unique_ptr <-> shared_ptr conversion ?
+        // To check: Conversion is possible only if the state which should be passed to
+        // 'setup' user callback isn't required to have previous value
+        std::shared_ptr<typename Impl::State> stPtr;
+        Impl::setup(detail::get_in_meta<Ins>(metaArgs, args, IIs)..., stPtr, compileArgs);
+        state = GArg(stPtr);
+    }
+
+    // SFINAE for 'Impl::setup' which doesn't accept compile arguments.
+    template<int... IIs>
+    static auto setup_impl(const GMetaArgs &metaArgs, const GArgs &args,
+                           GArg &state, const GCompileArgs &/* compileArgs */,
+                           detail::Seq<IIs...>) ->
+        decltype(Impl::setup(detail::get_in_meta<Ins>(metaArgs, args, IIs)...,
+                             std::declval<typename std::add_lvalue_reference<
+                                              std::shared_ptr<typename Impl::State>
+                                                                            >::type
+                                         >()
+                            )
+                 , void())
+    {
+        // The same comment as in 'setup' above.
+        std::shared_ptr<typename Impl::State> stPtr;
+        Impl::setup(detail::get_in_meta<Ins>(metaArgs, args, IIs)..., stPtr);
+        state = GArg(stPtr);
+    }
+
+    static void setup(const GMetaArgs &metaArgs, const GArgs &args,
+                      GArg& state, const GCompileArgs &compileArgs)
+    {
+        setup_impl(metaArgs, args, state, compileArgs,
+                   typename detail::MkSeq<sizeof...(Ins)>::type());
+    }
+};
+
+// OCVCallHelper is a helper class to call stateless OCV kernels and OCV kernel functors.
 template<typename, typename, typename>
 struct OCVCallHelper;
 
 // FIXME: probably can be simplified with std::apply or analogue.
 template<typename Impl, typename... Ins, typename... Outs>
-struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
+struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>>
 {
     template<typename... Inputs>
     struct call_and_postprocess
@@ -293,19 +373,16 @@ struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
         //by comparing it's state (data ptr) before and after the call.
         //This is done by converting each output Mat into tracked_cv_mat object, and binding
         //them to parameters of ad-hoc function
-        //Convert own::Scalar to cv::Scalar before call kernel and run kernel
-        //convert cv::Scalar to own::Scalar after call kernel and write back results
         call_and_postprocess<decltype(get_in<Ins>::get(ctx, IIs))...>
-                                      ::call(get_in<Ins>::get(ctx, IIs)...,
-                                             get_out<Outs>::get(ctx, OIs)...);
+            ::call(get_in<Ins>::get(ctx, IIs)..., get_out<Outs>::get(ctx, OIs)...);
     }
 
     template<int... IIs, int... OIs>
-    static void call_impl(cv::GCPUContext &ctx, Impl& impl, detail::Seq<IIs...>, detail::Seq<OIs...>)
+    static void call_impl(cv::GCPUContext &ctx, Impl& impl,
+                          detail::Seq<IIs...>, detail::Seq<OIs...>)
     {
-        call_and_postprocess<decltype(cv::detail::get_in<Ins>::get(ctx, IIs))...>
-                                      ::call(impl, cv::detail::get_in<Ins>::get(ctx, IIs)...,
-                                                   cv::detail::get_out<Outs>::get(ctx, OIs)...);
+        call_and_postprocess<decltype(get_in<Ins>::get(ctx, IIs))...>
+            ::call(impl, get_in<Ins>::get(ctx, IIs)..., get_out<Outs>::get(ctx, OIs)...);
     }
 
     static void call(GCPUContext &ctx)
@@ -326,30 +403,86 @@ struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
     }
 };
 
+// OCVStCallHelper is a helper class to call stateful OCV kernels.
+template<typename, typename, typename>
+struct OCVStCallHelper;
+
+template<typename Impl, typename... Ins, typename... Outs>
+struct OCVStCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>> :
+    OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>>
+{
+    template<typename... Inputs>
+    struct call_and_postprocess
+    {
+        template<typename... Outputs>
+        static void call(typename Impl::State& st, Inputs&&... ins, Outputs&&... outs)
+        {
+            Impl::run(std::forward<Inputs>(ins)..., outs..., st);
+            postprocess(outs...);
+        }
+    };
+
+    template<int... IIs, int... OIs>
+    static void call_impl(GCPUContext &ctx, detail::Seq<IIs...>, detail::Seq<OIs...>)
+    {
+        auto& st = *ctx.state().get<std::shared_ptr<typename Impl::State>>();
+        call_and_postprocess<decltype(get_in<Ins>::get(ctx, IIs))...>
+            ::call(st, get_in<Ins>::get(ctx, IIs)..., get_out<Outs>::get(ctx, OIs)...);
+    }
+
+    static void call(GCPUContext &ctx)
+    {
+        call_impl(ctx,
+                  typename detail::MkSeq<sizeof...(Ins)>::type(),
+                  typename detail::MkSeq<sizeof...(Outs)>::type());
+    }
+};
+
 } // namespace detail
 
 template<class Impl, class K>
-class GCPUKernelImpl: public cv::detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>,
-                      public cv::detail::KernelTag
+class GCPUKernelImpl: public cv::detail::KernelTag
 {
-    using P = detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
+    using CallHelper = detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
 
 public:
     using API = K;
 
-    static cv::gapi::GBackend backend()  { return cv::gapi::cpu::backend(); }
-    static cv::GCPUKernel     kernel()   { return GCPUKernel(&P::call);     }
+    static cv::gapi::GBackend backend() { return cv::gapi::cpu::backend(); }
+    static cv::GCPUKernel      kernel() { return GCPUKernel(&CallHelper::call); }
+};
+
+template<class Impl, class K, class S>
+class GCPUStKernelImpl: public cv::detail::KernelTag
+{
+    using StSetupHelper = detail::OCVSetupHelper<Impl, typename K::InArgs>;
+    using StCallHelper  = detail::OCVStCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
+
+public:
+    using API = K;
+    using State = S;
+
+    static cv::gapi::GBackend backend() { return cv::gapi::cpu::backend(); }
+    static cv::GCPUKernel     kernel()  { return GCPUKernel(&StCallHelper::call,
+                                                            &StSetupHelper::setup); }
 };
 
 #define GAPI_OCV_KERNEL(Name, API) struct Name: public cv::GCPUKernelImpl<Name, API>
 
+// TODO: Reuse Anatoliy's logic for support of types with commas in macro.
+//       Retrieve the common part from Anatoliy's logic to the separate place.
+#define GAPI_OCV_KERNEL_ST(Name, API, State)                   \
+    struct Name: public cv::GCPUStKernelImpl<Name, API, State> \
+
+
 class gapi::cpu::GOCVFunctor : public gapi::GFunctor
 {
 public:
     using Impl = std::function<void(GCPUContext &)>;
+    using Meta = cv::GKernel::M;
 
-    GOCVFunctor(const char* id, const Impl& impl)
-        : gapi::GFunctor(id), impl_{GCPUKernel(impl)}
+    GOCVFunctor(const char* id, const Meta &meta, const Impl& impl)
+        : gapi::GFunctor(id), impl_{GCPUKernel(impl), meta}
     {
     }
 
@@ -365,14 +498,20 @@ template<typename K, typename Callable>
 gapi::cpu::GOCVFunctor gapi::cpu::ocv_kernel(Callable& c)
 {
     using P = detail::OCVCallHelper<Callable, typename K::InArgs, typename K::OutArgs>;
-    return GOCVFunctor(K::id(), std::bind(&P::callFunctor, std::placeholders::_1, std::ref(c)));
+    return GOCVFunctor{ K::id()
+                      , &K::getOutMeta
+                      , std::bind(&P::callFunctor, std::placeholders::_1, std::ref(c))
+                      };
 }
 
 template<typename K, typename Callable>
 gapi::cpu::GOCVFunctor gapi::cpu::ocv_kernel(const Callable& c)
 {
     using P = detail::OCVCallHelper<Callable, typename K::InArgs, typename K::OutArgs>;
-    return GOCVFunctor(K::id(), std::bind(&P::callFunctor, std::placeholders::_1, c));
+    return GOCVFunctor{ K::id()
+                      , &K::getOutMeta
+                      , std::bind(&P::callFunctor, std::placeholders::_1, c)
+                      };
 }
 //! @endcond
 
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/video.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/video.hpp
new file mode 100644 (file)
index 0000000..d3c1f2e
--- /dev/null
@@ -0,0 +1,25 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_CPU_VIDEO_API_HPP
+#define OPENCV_GAPI_CPU_VIDEO_API_HPP
+
+#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
+
+namespace cv {
+namespace gapi {
+namespace video {
+namespace cpu {
+
+GAPI_EXPORTS GKernelPackage kernels();
+
+} // namespace cpu
+} // namespace video
+} // namespace gapi
+} // namespace cv
+
+
+#endif // OPENCV_GAPI_CPU_VIDEO_API_HPP
index 8c21f57..9eceb82 100644 (file)
@@ -13,7 +13,7 @@
 
 namespace cv { namespace gapi { namespace core { namespace fluid {
 
-GAPI_EXPORTS GKernelPackage kernels();
+GAPI_EXPORTS_W cv::gapi::GKernelPackage kernels();
 
 }}}}
 
index de776c2..daa9d41 100644 (file)
 #include <cstdint> // uint8_t
 
 #include <opencv2/gapi/opencv_includes.hpp>
-#include <opencv2/gapi/own/mat.hpp>
 #include <opencv2/gapi/gmat.hpp>
 
 #include <opencv2/gapi/util/optional.hpp>
-#include <opencv2/gapi/own/mat.hpp>
 
 namespace cv {
 namespace gapi {
@@ -58,8 +56,6 @@ public:
         }
     };
 
-    View() = default;
-
     const inline uint8_t* InLineB(int index) const // -(w-1)/2...0...+(w-1)/2 for Filters
     {
         return m_cache->linePtr(index);
@@ -82,11 +78,15 @@ public:
     Priv& priv();               // internal use only
     const Priv& priv() const;   // internal use only
 
-    View(Priv* p);
+    View();
+    View(std::unique_ptr<Priv>&& p);
+    View(View&& v);
+    View& operator=(View&& v);
+    ~View();
 
 private:
-    std::shared_ptr<Priv> m_priv;
-    const Cache* m_cache;
+    std::unique_ptr<Priv> m_priv;
+    const Cache* m_cache = nullptr;
 };
 
 class GAPI_EXPORTS Buffer
@@ -111,7 +111,9 @@ public:
            int wlpi,
            BorderOpt border);
     // Constructor for in/out buffers (for tests)
-    Buffer(const cv::gapi::own::Mat &data, bool is_input);
+    Buffer(const cv::Mat &data, bool is_input);
+    ~Buffer();
+    Buffer& operator=(Buffer&&);
 
     inline uint8_t* OutLineB(int index = 0)
     {
@@ -134,13 +136,14 @@ public:
     inline const GMatDesc& meta() const { return m_cache->m_desc; }
 
     View mkView(int borderSize, bool ownStorage);
+    void addView(const View* v);
 
     class GAPI_EXPORTS Priv;      // internal use only
     Priv& priv();               // internal use only
     const Priv& priv() const;   // internal use only
 
 private:
-    std::shared_ptr<Priv> m_priv;
+    std::unique_ptr<Priv> m_priv;
     const Cache* m_cache;
 };
 
index 0f11640..dbb36d8 100644 (file)
@@ -171,7 +171,7 @@ template<> struct fluid_get_in<cv::GMat>
 {
     static const cv::gapi::fluid::View& get(const cv::GArgs &in_args, int idx)
     {
-        return in_args[idx].unsafe_get<cv::gapi::fluid::View>();
+        return *in_args[idx].unsafe_get<cv::gapi::fluid::View*>();
     }
 };
 
index 5aaea55..cca080d 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GARG_HPP
@@ -46,6 +46,7 @@ public:
     template<typename T, typename std::enable_if<!detail::is_garg<T>::value, int>::type = 0>
     explicit GArg(const T &t)
         : kind(detail::GTypeTraits<T>::kind)
+        , opaque_kind(detail::GOpaqueTraits<T>::kind)
         , value(detail::wrap_gapi_helper<T>::wrap(t))
     {
     }
@@ -53,6 +54,7 @@ public:
     template<typename T, typename std::enable_if<!detail::is_garg<T>::value, int>::type = 0>
     explicit GArg(T &&t)
         : kind(detail::GTypeTraits<typename std::decay<T>::type>::kind)
+        , opaque_kind(detail::GOpaqueTraits<typename std::decay<T>::type>::kind)
         , value(detail::wrap_gapi_helper<T>::wrap(t))
     {
     }
@@ -78,6 +80,7 @@ public:
     }
 
     detail::ArgKind kind = detail::ArgKind::OPAQUE_VAL;
+    detail::OpaqueKind opaque_kind = detail::OpaqueKind::CV_UNKNOWN;
 
 protected:
     util::any value;
@@ -89,17 +92,33 @@ using GArgs = std::vector<GArg>;
 // FIXME: Move to a separate file!
 using GRunArg  = util::variant<
 #if !defined(GAPI_STANDALONE)
-    cv::Mat,
     cv::UMat,
 #endif // !defined(GAPI_STANDALONE)
     cv::gapi::wip::IStreamSource::Ptr,
-    cv::gapi::own::Mat,
+    cv::Mat,
     cv::Scalar,
     cv::detail::VectorRef,
     cv::detail::OpaqueRef
     >;
 using GRunArgs = std::vector<GRunArg>;
 
+// TODO: Think about the addition operator
+/**
+ * @brief This operator allows to complement the input vector at runtime.
+ *
+ * It's an ordinary overload of addition assignment operator.
+ *
+ * Example of usage:
+ * @snippet dynamic_graph.cpp GRunArgs usage
+ *
+ */
+inline GRunArgs& operator += (GRunArgs &lhs, const GRunArgs &rhs)
+{
+    lhs.reserve(lhs.size() + rhs.size());
+    lhs.insert(lhs.end(), rhs.begin(), rhs.end());
+    return lhs;
+}
+
 namespace gapi
 {
 namespace wip
@@ -122,16 +141,38 @@ struct Data: public GRunArg
 
 using GRunArgP = util::variant<
 #if !defined(GAPI_STANDALONE)
-    cv::Mat*,
     cv::UMat*,
 #endif // !defined(GAPI_STANDALONE)
-    cv::gapi::own::Mat*,
+    cv::Mat*,
     cv::Scalar*,
     cv::detail::VectorRef,
     cv::detail::OpaqueRef
     >;
 using GRunArgsP = std::vector<GRunArgP>;
 
+// TODO: Think about the addition operator
+/**
+ * @brief This operator allows to complement the output vector at runtime.
+ *
+ * It's an ordinary overload of addition assignment operator.
+ *
+ * Example of usage:
+ * @snippet dynamic_graph.cpp GRunArgsP usage
+ *
+ */
+inline GRunArgsP& operator += (GRunArgsP &lhs, const GRunArgsP &rhs)
+{
+    lhs.reserve(lhs.size() + rhs.size());
+    lhs.insert(lhs.end(), rhs.begin(), rhs.end());
+    return lhs;
+}
+
+namespace gapi
+{
+    GAPI_EXPORTS cv::GRunArgsP bind(cv::GRunArgs &results);
+    GAPI_EXPORTS cv::GRunArg   bind(cv::GRunArgP &out);     // FIXME: think more about it
+}
+
 template<typename... Ts> inline GRunArgs gin(const Ts&... args)
 {
     return GRunArgs{ GRunArg(detail::wrap_host_helper<Ts>::wrap_in(args))... };
index b989071..9118f4d 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GARRAY_HPP
@@ -29,7 +29,6 @@ namespace cv
 // (user-inaccessible) classes.
 class GNode;
 struct GOrigin;
-
 template<typename T> class GArray;
 
 /**
@@ -81,6 +80,7 @@ namespace detail
 
     protected:
         GArrayU();                                // Default constructor
+        GArrayU(const detail::VectorRef& vref);   // Constant value constructor
         template<class> friend class cv::GArray;  //  (available to GArray<T> only)
 
         void setConstructFcn(ConstructVec &&cv);  // Store T-aware constructor
@@ -88,6 +88,11 @@ namespace detail
         template <typename T>
         void specifyType();                       // Store type of initial GArray<T>
 
+        template <typename T>
+        void storeKind();
+
+        void setKind(cv::detail::OpaqueKind);
+
         std::shared_ptr<GOrigin> m_priv;
         std::shared_ptr<TypeHintBase> m_hint;
     };
@@ -104,6 +109,11 @@ namespace detail
         m_hint.reset(new TypeHint<typename std::decay<T>::type>);
     };
 
+    template <typename T>
+    void GArrayU::storeKind(){
+        setKind(cv::detail::GOpaqueTraits<T>::kind);
+    };
+
     // This class represents a typed STL vector reference.
     // Depending on origins, this reference may be either "just a" reference to
     // an object created externally, OR actually own the underlying object
@@ -111,11 +121,14 @@ namespace detail
     class BasicVectorRef
     {
     public:
+        // These fields are set by the derived class(es)
         std::size_t    m_elemSize = 0ul;
         cv::GArrayDesc m_desc;
         virtual ~BasicVectorRef() {}
 
         virtual void mov(BasicVectorRef &ref) = 0;
+        virtual const void* ptr() const = 0;
+        virtual std::size_t size() const = 0;
     };
 
     template<typename T> class VectorRefT final: public BasicVectorRef
@@ -208,6 +221,9 @@ namespace detail
             GAPI_Assert(tv != nullptr);
             wref() = std::move(tv->wref());
         }
+
+        virtual const void* ptr() const override { return &rref(); }
+        virtual std::size_t size() const override { return rref().size(); }
     };
 
     // This class strips type information from VectorRefT<> and makes it usable
@@ -220,6 +236,7 @@ namespace detail
     class VectorRef
     {
         std::shared_ptr<BasicVectorRef> m_ref;
+        cv::detail::OpaqueKind m_kind;
 
         template<typename T> inline void check() const
         {
@@ -229,18 +246,32 @@ namespace detail
 
     public:
         VectorRef() = default;
-        template<typename T> explicit VectorRef(const std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
-        template<typename T> explicit VectorRef(std::vector<T>& vec)       : m_ref(new VectorRefT<T>(vec)) {}
-        template<typename T> explicit VectorRef(std::vector<T>&& vec)      : m_ref(new VectorRefT<T>(vec)) {}
+        template<typename T> explicit VectorRef(const std::vector<T>& vec) :
+                                            m_ref(new VectorRefT<T>(vec)), m_kind(GOpaqueTraits<T>::kind) {}
+        template<typename T> explicit VectorRef(std::vector<T>& vec)       :
+                                            m_ref(new VectorRefT<T>(vec)), m_kind(GOpaqueTraits<T>::kind) {}
+        template<typename T> explicit VectorRef(std::vector<T>&& vec)      :
+                                            m_ref(new VectorRefT<T>(std::move(vec))), m_kind(GOpaqueTraits<T>::kind) {}
+
+        cv::detail::OpaqueKind getKind() const
+        {
+            return m_kind;
+        }
 
         template<typename T> void reset()
         {
             if (!m_ref) m_ref.reset(new VectorRefT<T>());
-
             check<T>();
+            storeKind<T>();
             static_cast<VectorRefT<T>&>(*m_ref).reset();
         }
 
+        template <typename T>
+        void storeKind()
+        {
+            m_kind = cv::detail::GOpaqueTraits<T>::kind;
+        }
+
         template<typename T> std::vector<T>& wref()
         {
             check<T>();
@@ -262,6 +293,14 @@ namespace detail
         {
             return m_ref->m_desc;
         }
+
+        std::size_t size() const
+        {
+            return m_ref->size();
+        }
+
+        // May be used to uniquely identify this object internally
+        const void *ptr() const { return m_ref->ptr(); }
     };
 
     // Helper (FIXME: work-around?)
@@ -290,6 +329,14 @@ namespace detail
 template<typename T> class GArray
 {
 public:
+    // Host type (or Flat type) - the type this GArray is actually
+    // specified to.
+    using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
+
+    explicit GArray(const std::vector<HT>& v) // Constant value constructor
+        : m_ref(detail::GArrayU(detail::VectorRef(v))) { putDetails(); }
+    explicit GArray(std::vector<HT>&& v)      // Move-constructor
+        : m_ref(detail::GArrayU(detail::VectorRef(std::move(v)))) { putDetails(); }
     GArray() { putDetails(); }             // Empty constructor
     explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
         : m_ref(ref) { putDetails(); }     //   (used by GCall, not for users)
@@ -297,16 +344,14 @@ public:
     detail::GArrayU strip() const { return m_ref; }
 
 private:
-    // Host type (or Flat type) - the type this GArray is actually
-    // specified to.
-    using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
-
     static void VCTor(detail::VectorRef& vref) {
         vref.reset<HT>();
+        vref.storeKind<HT>();
     }
     void putDetails() {
         m_ref.setConstructFcn(&VCTor);
-        m_ref.specifyType<HT>();
+        m_ref.specifyType<HT>();  // FIXME: to unify those 2 to avoid excessive dynamic_cast
+        m_ref.storeKind<HT>();    //
     }
 
     detail::GArrayU m_ref;
index 9ee75f7..dc2c8b9 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GCOMMON_HPP
 #include <opencv2/gapi/opencv_includes.hpp>
 
 #include <opencv2/gapi/util/any.hpp>
+#include <opencv2/gapi/util/optional.hpp>
 #include <opencv2/gapi/own/exports.hpp>
 #include <opencv2/gapi/own/assert.hpp>
+#include <opencv2/gapi/render/render_types.hpp>
 
 namespace cv {
 
+class GMat; // FIXME: forward declaration for GOpaqueTraits
+
 namespace detail
 {
     // This is a trait-like structure to mark backend-specific compile arguments
@@ -31,7 +35,42 @@ namespace detail
     {};
     struct TransformTag
     {};
-}
+
+    // This enum is utilized mostly by GArray and GOpaque to store and recognize their internal data
+    // types (aka Host type). Also it is widely used during serialization routine.
+    enum class OpaqueKind: int
+    {
+        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_DOUBLE,     // double 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
+    };
+
+    // Type traits helper which simplifies the extraction of kind from type
+    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<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<bool>        { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; };
+    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>;
+    // 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>;
+} // namespace detail
 
 // This definition is here because it is reused by both public(?) and internal
 // modules. Keeping it here wouldn't expose public details (e.g., API-level)
@@ -45,6 +84,7 @@ enum class GShape: int
     GSCALAR,
     GARRAY,
     GOPAQUE,
+    GFRAME,
 };
 
 struct GCompileArg;
@@ -52,7 +92,8 @@ struct GCompileArg;
 namespace detail {
     template<typename T>
     using is_compile_arg = std::is_same<GCompileArg, typename std::decay<T>::type>;
-}
+} // namespace detail
+
 // CompileArg is an unified interface over backend-specific compilation
 // information
 // FIXME: Move to a separate file?
@@ -91,9 +132,12 @@ namespace detail {
  * passed in (a variadic template parameter pack) into a vector of
  * cv::GCompileArg objects.
  */
-struct GAPI_EXPORTS GCompileArg
+struct GAPI_EXPORTS_W_SIMPLE GCompileArg
 {
 public:
+    // NB: Required for pythnon bindings
+    GCompileArg() = default;
+
     std::string tag;
 
     // FIXME: use decay in GArg/other trait-based wrapper before leg is shot!
@@ -121,8 +165,8 @@ private:
 using GCompileArgs = std::vector<GCompileArg>;
 
 /**
- * Wraps a list of arguments (a parameter pack) into a vector of
- * compilation arguments (cv::GCompileArg).
+ * @brief Wraps a list of arguments (a parameter pack) into a vector of
+ *        compilation arguments (cv::GCompileArg).
  */
 template<typename... Ts> GCompileArgs compile_args(Ts&&... args)
 {
@@ -130,6 +174,26 @@ template<typename... Ts> GCompileArgs compile_args(Ts&&... args)
 }
 
 /**
+ * @brief Retrieves particular compilation argument by its type from
+ *        cv::GCompileArgs
+ */
+namespace gapi
+{
+template<typename T>
+inline cv::util::optional<T> getCompileArg(const cv::GCompileArgs &args)
+{
+    for (auto &compile_arg : args)
+    {
+        if (compile_arg.tag == cv::detail::CompileArgTag<T>::tag())
+        {
+            return cv::util::optional<T>(compile_arg.get<T>());
+        }
+    }
+    return cv::util::optional<T>();
+}
+} // namespace gapi
+
+/**
  * @brief Ask G-API to dump compiled graph in Graphviz format under
  * the given file name.
  *
index b08451a..ac36783 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GCOMPILED_HPP
@@ -208,6 +208,19 @@ public:
     // FIXME: Why it requires compile args?
     void reshape(const GMetaArgs& inMetas, const GCompileArgs& args);
 
+    /**
+     * @brief Prepare inner kernels states for a new video-stream.
+     *
+     * GCompiled objects may be used to process video streams frame by frame.
+     * In this case, a GCompiled is called on every image frame individually.
+     * Starting OpenCV 4.4, some kernels in the graph may have their internal
+     * states (see GAPI_OCV_KERNEL_ST for the OpenCV backend).
+     * In this case, if user starts processing another video stream with
+     * this GCompiled, this method needs to be called to let kernels re-initialize
+     * their internal states to a new video stream.
+     */
+    void prepareForNewStream();
+
 protected:
     /// @private
     std::shared_ptr<Priv> m_priv;
index 2f17064..df0ce34 100644 (file)
@@ -75,6 +75,16 @@ template<typename U> struct get_compound_in<cv::GOpaque<U>>
     }
 };
 
+template<> struct get_compound_in<cv::GMatP>
+{
+    static cv::GMatP get(GCompoundContext &ctx, int idx)
+    {
+        auto mat = cv::GMatP();
+        ctx.m_args[idx] = GArg(mat);
+        return mat;
+    }
+};
+
 template<typename, typename, typename>
 struct GCompoundCallHelper;
 
index 1ff874a..b24766a 100644 (file)
@@ -36,6 +36,16 @@ namespace detail
     using last_type_t = typename last_type<Ts...>::type;
 }
 
+// Forward-declare the serialization objects
+namespace gimpl {
+namespace s11n {
+namespace I {
+    struct IStream;
+    struct OStream;
+} // namespace I
+} // namespace s11n
+} // namespace gimpl
+
 /**
  * \addtogroup gapi_main_classes
  * @{
@@ -108,7 +118,7 @@ namespace detail
  *
  * @sa GCompiled
  */
-class GAPI_EXPORTS GComputation
+class GAPI_EXPORTS_W GComputation
 {
 public:
     class Priv;
@@ -151,8 +161,8 @@ public:
      *
      * @sa @ref gapi_data_objects
      */
-    GComputation(GProtoInputArgs &&ins,
-                 GProtoOutputArgs &&outs);             // Arg-to-arg overload
+    GAPI_WRAP GComputation(GProtoInputArgs &&ins,
+                           GProtoOutputArgs &&outs);             // Arg-to-arg overload
 
     // 2. Syntax sugar and compatibility overloads
     /**
@@ -162,7 +172,7 @@ public:
      * @param in input GMat of the defined unary computation
      * @param out output GMat of the defined unary computation
      */
-    GComputation(GMat in, GMat out);                   // Unary overload
+    GAPI_WRAP GComputation(GMat in, GMat out);  // Unary overload
 
     /**
      * @brief Defines an unary (one input -- one output) computation
@@ -171,7 +181,7 @@ public:
      * @param in input GMat of the defined unary computation
      * @param out output GScalar of the defined unary computation
      */
-    GComputation(GMat in, GScalar out);                // Unary overload (scalar)
+    GAPI_WRAP GComputation(GMat in, GScalar out);      // Unary overload (scalar)
 
     /**
      * @brief Defines a binary (two inputs -- one output) computation
@@ -181,7 +191,7 @@ public:
      * @param in2 second input GMat of the defined binary computation
      * @param out output GMat of the defined binary computation
      */
-    GComputation(GMat in1, GMat in2, GMat out);        // Binary overload
+    GAPI_WRAP GComputation(GMat in1, GMat in2, GMat out);        // Binary overload
 
     /**
      * @brief Defines a binary (two inputs -- one output) computation
@@ -250,8 +260,8 @@ public:
     void apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {});       // Arg-to-arg overload
 
     /// @private -- Exclude this function from OpenCV documentation
-    void apply(const std::vector<cv::gapi::own::Mat>& ins,                        // Compatibility overload
-               const std::vector<cv::gapi::own::Mat>& outs,
+    void apply(const std::vector<cv::Mat>& ins,                                   // Compatibility overload
+               const std::vector<cv::Mat>& outs,
                GCompileArgs &&args = {});
 
     // 2. Syntax sugar and compatibility overloads
@@ -265,7 +275,7 @@ public:
      * @param args compilation arguments for underlying compilation
      * process.
      */
-    void apply(cv::Mat in, cv::Mat &out, GCompileArgs &&args = {});               // Unary overload
+    void apply(cv::Mat in, cv::Mat &out, GCompileArgs &&args = {}); // Unary overload
 
     /**
      * @brief Execute an unary computation (with compilation on the fly)
@@ -276,7 +286,7 @@ public:
      * @param args compilation arguments for underlying compilation
      * process.
      */
-    void apply(cv::Mat in, cv::Scalar &out, GCompileArgs &&args = {});            // Unary overload (scalar)
+    GAPI_WRAP void apply(cv::Mat in, CV_OUT cv::Scalar &out, GCompileArgs &&args = {}); // Unary overload (scalar)
 
     /**
      * @brief Execute a binary computation (with compilation on the fly)
@@ -288,7 +298,7 @@ public:
      * @param args compilation arguments for underlying compilation
      * process.
      */
-    void apply(cv::Mat in1, cv::Mat in2, cv::Mat &out, GCompileArgs &&args = {}); // Binary overload
+    GAPI_WRAP void apply(cv::Mat in1, cv::Mat in2, CV_OUT cv::Mat &out, GCompileArgs &&args = {}); // Binary overload
 
     /**
      * @brief Execute an binary computation (with compilation on the fly)
@@ -495,6 +505,10 @@ public:
     Priv& priv();
     /// @private
     const Priv& priv() const;
+    /// @private
+    explicit GComputation(cv::gimpl::s11n::I::IStream &);
+    /// @private
+    void serialize(cv::gimpl::s11n::I::OStream &) const;
 
 protected:
 
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gframe.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gframe.hpp
new file mode 100644 (file)
index 0000000..7e19dbf
--- /dev/null
@@ -0,0 +1,59 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GFRAME_HPP
+#define OPENCV_GAPI_GFRAME_HPP
+
+#include <ostream>
+#include <memory>                 // std::shared_ptr
+
+#include <opencv2/gapi/opencv_includes.hpp>
+#include <opencv2/gapi/gcommon.hpp> // GShape
+
+#include <opencv2/gapi/gmat.hpp>
+#include <opencv2/gapi/own/assert.hpp>
+
+// TODO GAPI_EXPORTS or so
+namespace cv
+{
+// Forward declaration; GNode and GOrigin are an internal
+// (user-inaccessible) classes.
+class GNode;
+struct GOrigin;
+
+/** \addtogroup gapi_data_objects
+ * @{
+ */
+class GAPI_EXPORTS_W_SIMPLE GFrame
+{
+public:
+    GAPI_WRAP GFrame();                       // Empty constructor
+    GFrame(const GNode &n, std::size_t out);  // Operation result constructor
+
+    GOrigin& priv();                        // Internal use only
+    const GOrigin& priv()  const;           // Internal use only
+
+private:
+    std::shared_ptr<GOrigin> m_priv;
+};
+/** @} */
+
+/**
+ * \addtogroup gapi_meta_args
+ * @{
+ */
+struct GAPI_EXPORTS GFrameDesc
+{
+};
+static inline GFrameDesc empty_gframe_desc() { return GFrameDesc{}; }
+/** @} */
+
+GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const cv::GFrameDesc &desc);
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GFRAME_HPP
index becd779..7752b10 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018-2019 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GKERNEL_HPP
@@ -27,6 +27,7 @@
 namespace cv {
 
 using GShapes = std::vector<GShape>;
+using GKinds = std::vector<cv::detail::OpaqueKind>;
 
 // GKernel describes kernel API to the system
 // FIXME: add attributes of a kernel, (e.g. number and types
@@ -35,16 +36,20 @@ struct GAPI_EXPORTS GKernel
 {
     using M = std::function<GMetaArgs(const GMetaArgs &, const GArgs &)>;
 
-    const std::string name;       // kernel ID, defined by its API (signature)
-    const std::string tag;        // some (implementation-specific) tag
-    const M           outMeta;    // generic adaptor to API::outMeta(...)
-    const GShapes     outShapes;  // types (shapes) kernel's outputs
+    std::string name;       // kernel ID, defined by its API (signature)
+    std::string tag;        // some (implementation-specific) tag
+    M           outMeta;    // generic adaptor to API::outMeta(...)
+    GShapes     outShapes;  // types (shapes) kernel's outputs
+    GKinds      inKinds;    // kinds of kernel's inputs (fixme: below)
 };
+// TODO: It's questionable if inKinds should really be here. Instead,
+// this information could come from meta.
 
 // GKernelImpl describes particular kernel implementation to the system
 struct GAPI_EXPORTS GKernelImpl
 {
     util::any         opaque;    // backend-specific opaque info
+    GKernel::M        outMeta;   // for deserialized graphs, the outMeta is taken here
 };
 
 template<typename, typename> class GKernelTypeM;
@@ -90,6 +95,7 @@ namespace detail
     template<typename T> struct MetaType;
     template<> struct MetaType<cv::GMat>    { using type = GMatDesc; };
     template<> struct MetaType<cv::GMatP>   { using type = GMatDesc; };
+    template<> struct MetaType<cv::GFrame>  { using type = GMatDesc; };
     template<> struct MetaType<cv::GScalar> { using type = GScalarDesc; };
     template<typename U> struct MetaType<cv::GArray<U> >  { using type = GArrayDesc; };
     template<typename U> struct MetaType<cv::GOpaque<U> > { using type = GOpaqueDesc; };
@@ -201,10 +207,15 @@ public:
     using InArgs  = std::tuple<Args...>;
     using OutArgs = std::tuple<R...>;
 
+    // TODO: Args&&... here?
     static std::tuple<R...> on(Args... args)
     {
-        cv::GCall call(GKernel{K::id(), K::tag(), &K::getOutMeta, {detail::GTypeTraits<R>::shape...}});
-        call.pass(args...);
+        cv::GCall call(GKernel{ K::id()
+                              , K::tag()
+                              , &K::getOutMeta
+                              , {detail::GTypeTraits<R>::shape...}
+                              , {detail::GTypeTraits<Args>::op_kind...}});
+        call.pass(args...); // TODO: std::forward() here?
         return yield(call, typename detail::MkSeq<sizeof...(R)>::type());
     }
 };
@@ -220,9 +231,15 @@ public:
     using InArgs  = std::tuple<Args...>;
     using OutArgs = std::tuple<R>;
 
+    static_assert(!cv::detail::contains<GFrame, OutArgs>::value, "Values of GFrame type can't be used as operation outputs");
+
     static R on(Args... args)
     {
-        cv::GCall call(GKernel{K::id(), K::tag(), &K::getOutMeta, {detail::GTypeTraits<R>::shape}});
+        cv::GCall call(GKernel{ K::id()
+                              , K::tag()
+                              , &K::getOutMeta
+                              , {detail::GTypeTraits<R>::shape}
+                              , {detail::GTypeTraits<Args>::op_kind...}});
         call.pass(args...);
         return detail::Yield<R>::yield(call, 0);
     }
@@ -428,7 +445,7 @@ namespace gapi {
      * Finally, two kernel packages can be combined into a new one
      * with function cv::gapi::combine().
      */
-    class GAPI_EXPORTS GKernelPackage
+    class GAPI_EXPORTS_W_SIMPLE GKernelPackage
     {
 
         /// @private
@@ -453,12 +470,12 @@ namespace gapi {
         /// @private
         // Partial include() specialization for kernels
         template <typename KImpl>
-        typename std::enable_if<(std::is_base_of<detail::KernelTag, KImpl>::value), void>::type
+        typename std::enable_if<(std::is_base_of<cv::detail::KernelTag, KImpl>::value), void>::type
         includeHelper()
         {
             auto backend     = KImpl::backend();
             auto kernel_id   = KImpl::API::id();
-            auto kernel_impl = GKernelImpl{KImpl::kernel()};
+            auto kernel_impl = GKernelImpl{KImpl::kernel(), &KImpl::API::getOutMeta};
             removeAPI(kernel_id);
 
             m_id_kernels[kernel_id] = std::make_pair(backend, kernel_impl);
@@ -467,7 +484,7 @@ namespace gapi {
         /// @private
         // Partial include() specialization for transformations
         template <typename TImpl>
-        typename std::enable_if<(std::is_base_of<detail::TransformTag, TImpl>::value), void>::type
+        typename std::enable_if<(std::is_base_of<cv::detail::TransformTag, TImpl>::value), void>::type
         includeHelper()
         {
             m_transformations.emplace_back(TImpl::transformation());
@@ -506,7 +523,7 @@ namespace gapi {
         template<typename KImpl>
         bool includes() const
         {
-            static_assert(std::is_base_of<detail::KernelTag, KImpl>::value,
+            static_assert(std::is_base_of<cv::detail::KernelTag, KImpl>::value,
                           "includes() can be applied to kernels only");
 
             auto kernel_it = m_id_kernels.find(KImpl::API::id());
@@ -621,7 +638,7 @@ namespace gapi {
     {
         // FIXME: currently there is no check that transformations' signatures are unique
         // and won't be any intersection in graph compilation stage
-        static_assert(detail::all_unique<typename KK::API...>::value, "Kernels API must be unique");
+        static_assert(cv::detail::all_unique<typename KK::API...>::value, "Kernels API must be unique");
 
         GKernelPackage pkg;
 
@@ -695,6 +712,7 @@ namespace detail
         static const char* tag() { return "gapi.use_only"; }
     };
 } // namespace detail
+
 } // namespace cv
 
 #endif // OPENCV_GAPI_GKERNEL_HPP
index ffe1c07..b38ce48 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GMAT_HPP
@@ -46,10 +46,10 @@ struct GOrigin;
  *    `cv::GArray<T>`    | std::vector<T>
  *    `cv::GOpaque<T>`   | T
  */
-class GAPI_EXPORTS GMat
+class GAPI_EXPORTS_W_SIMPLE GMat
 {
 public:
-    GMat();                                 // Empty constructor
+    GAPI_WRAP GMat();                       // Empty constructor
     GMat(const GNode &n, std::size_t out);  // Operation result constructor
 
     GOrigin& priv();                        // Internal use only
@@ -65,10 +65,6 @@ public:
     using GMat::GMat;
 };
 
-namespace gapi { namespace own {
-    class Mat;
-}}//gapi::own
-
 /** @} */
 
 /**
@@ -115,7 +111,7 @@ struct GAPI_EXPORTS GMatDesc
     // (it handles the case when
     // 1-channel mat can be reinterpreted as is (1-channel mat)
     // and as a 3-channel planar mat with height divided by 3)
-    bool canDescribe(const cv::gapi::own::Mat& mat) const;
+    bool canDescribe(const cv::Mat& mat) const;
 
     // Meta combinator: return a new GMatDesc which differs in size by delta
     // (all other fields are taken unchanged from this GMatDesc)
@@ -126,9 +122,6 @@ struct GAPI_EXPORTS GMatDesc
         desc.size += delta;
         return desc;
     }
-#if !defined(GAPI_STANDALONE)
-    bool canDescribe(const cv::Mat& mat) const;
-#endif // !defined(GAPI_STANDALONE)
     // Meta combinator: return a new GMatDesc which differs in size by delta
     // (all other fields are taken unchanged from this GMatDesc)
     //
@@ -207,18 +200,23 @@ struct GAPI_EXPORTS GMatDesc
 static inline GMatDesc empty_gmat_desc() { return GMatDesc{-1,-1,{-1,-1}}; }
 
 #if !defined(GAPI_STANDALONE)
-class Mat;
-GAPI_EXPORTS GMatDesc descr_of(const cv::Mat &mat);
 GAPI_EXPORTS GMatDesc descr_of(const cv::UMat &mat);
 #endif // !defined(GAPI_STANDALONE)
 
-/** @} */
-
-// FIXME: WHY??? WHY it is under different namespace?
+//Fwd declarations
 namespace gapi { namespace own {
+    class Mat;
     GAPI_EXPORTS GMatDesc descr_of(const Mat &mat);
 }}//gapi::own
 
+#if !defined(GAPI_STANDALONE)
+GAPI_EXPORTS GMatDesc descr_of(const cv::Mat &mat);
+#else
+using gapi::own::descr_of;
+#endif
+
+/** @} */
+
 GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const cv::GMatDesc &desc);
 
 } // namespace cv
index 39f087f..499de45 100644 (file)
@@ -66,12 +66,10 @@ namespace detail
 
 // Note: descr_of(std::vector<..>) returns a GArrayDesc, while
 //       descrs_of(std::vector<..>) returns an array of Meta args!
-class Mat;
 class UMat;
 GAPI_EXPORTS cv::GMetaArgs descrs_of(const std::vector<cv::Mat> &vec);
 GAPI_EXPORTS cv::GMetaArgs descrs_of(const std::vector<cv::UMat> &vec);
 namespace gapi { namespace own {
-    class Mat;
     GAPI_EXPORTS cv::GMetaArgs descrs_of(const std::vector<Mat> &vec);
 }} // namespace gapi::own
 
index a8b0c59..1c45d46 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2019 Intel Corporation
+// Copyright (C) 2019-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GOPAQUE_HPP
@@ -17,6 +17,7 @@
 
 #include <opencv2/gapi/util/variant.hpp>
 #include <opencv2/gapi/util/throw.hpp>
+#include <opencv2/gapi/util/type_traits.hpp>
 #include <opencv2/gapi/own/assert.hpp>
 
 namespace cv
@@ -25,7 +26,6 @@ namespace cv
 // (user-inaccessible) classes.
 class GNode;
 struct GOrigin;
-
 template<typename T> class GOpaque;
 
 /**
@@ -80,6 +80,11 @@ namespace detail
         template <typename T>
         void specifyType();                       // Store type of initial GOpaque<T>
 
+        template <typename T>
+        void storeKind();
+
+        void setKind(cv::detail::OpaqueKind);
+
         std::shared_ptr<GOrigin> m_priv;
         std::shared_ptr<TypeHintBase> m_hint;
     };
@@ -87,13 +92,19 @@ namespace detail
     template <typename T>
     bool GOpaqueU::holds() const{
         GAPI_Assert(m_hint != nullptr);
-        using U = typename std::decay<T>::type;
+        using U = util::decay_t<T>;
         return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
     };
 
     template <typename T>
     void GOpaqueU::specifyType(){
-        m_hint.reset(new TypeHint<typename std::decay<T>::type>);
+        m_hint.reset(new TypeHint<util::decay_t<T>>);
+    };
+
+    template <typename T>
+    void GOpaqueU::storeKind(){
+        // FIXME: Add assert here on cv::Mat and cv::Scalar?
+        setKind(cv::detail::GOpaqueTraits<T>::kind);
     };
 
     // This class represents a typed object reference.
@@ -107,6 +118,7 @@ namespace detail
         virtual ~BasicOpaqueRef() {}
 
         virtual void mov(BasicOpaqueRef &ref) = 0;
+        virtual const void* ptr() const = 0;
     };
 
     template<typename T> class OpaqueRefT final: public BasicOpaqueRef
@@ -198,6 +210,8 @@ namespace detail
             GAPI_Assert(tv != nullptr);
             wref() = std::move(tv->wref());
         }
+
+        virtual const void* ptr() const override { return &rref(); }
     };
 
     // This class strips type information from OpaqueRefT<> and makes it usable
@@ -209,6 +223,7 @@ namespace detail
     class OpaqueRef
     {
         std::shared_ptr<BasicOpaqueRef> m_ref;
+        cv::detail::OpaqueKind m_kind;
 
         template<typename T> inline void check() const
         {
@@ -218,17 +233,34 @@ namespace detail
     public:
         OpaqueRef() = default;
 
-        template<typename T> explicit OpaqueRef(T&& obj) :
-            m_ref(new OpaqueRefT<typename std::decay<T>::type>(std::forward<T>(obj))) {}
+        template<
+            typename T,
+            typename = util::are_different_t<OpaqueRef, T>
+        >
+        // 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) {}
+
+        cv::detail::OpaqueKind getKind() const
+        {
+            return m_kind;
+        }
 
         template<typename T> void reset()
         {
             if (!m_ref) m_ref.reset(new OpaqueRefT<T>());
-
             check<T>();
+            storeKind<T>();
             static_cast<OpaqueRefT<T>&>(*m_ref).reset();
         }
 
+        template <typename T>
+        void storeKind()
+        {
+            m_kind = cv::detail::GOpaqueTraits<T>::kind;
+        }
+
         template<typename T> T& wref()
         {
             check<T>();
@@ -250,6 +282,9 @@ namespace detail
         {
             return m_ref->m_desc;
         }
+
+        // May be used to uniquely identify this object internally
+        const void *ptr() const { return m_ref->ptr(); }
     };
 } // namespace detail
 
@@ -269,14 +304,16 @@ public:
 private:
     // Host type (or Flat type) - the type this GOpaque is actually
     // specified to.
-    using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
+    using HT = typename detail::flatten_g<util::decay_t<T>>::type;
 
     static void CTor(detail::OpaqueRef& ref) {
         ref.reset<HT>();
+        ref.storeKind<HT>();
     }
     void putDetails() {
         m_ref.setConstructFcn(&CTor);
-        m_ref.specifyType<HT>();
+        m_ref.specifyType<HT>(); // FIXME: to unify those 2 to avoid excessive dynamic_cast
+        m_ref.storeKind<HT>();   //
     }
 
     detail::GOpaqueU m_ref;
index 921a588..fbcccb3 100644 (file)
@@ -36,6 +36,7 @@ namespace cv {
 using GProtoArg = util::variant
     < GMat
     , GMatP
+    , GFrame
     , GScalar
     , detail::GArrayU  // instead of GArray<T>
     , detail::GOpaqueU // instead of GOpaque<T>
@@ -56,12 +57,35 @@ template<class Tag>
 struct GIOProtoArgs
 {
 public:
+    // NB: Used by python wrapper
+    GIOProtoArgs() = default;
     explicit GIOProtoArgs(const GProtoArgs& args) : m_args(args) {}
     explicit GIOProtoArgs(GProtoArgs &&args)      : m_args(std::move(args)) {}
 
     GProtoArgs m_args;
+
+    // TODO: Think about the addition operator
+    /**
+     * @brief This operator allows to complement the proto vectors at runtime.
+     *
+     * It's an ordinary overload of addition assignment operator.
+     *
+     * Example of usage:
+     * @snippet dynamic_graph.cpp  GIOProtoArgs usage
+     *
+     */
+    template<typename Tg>
+    friend GIOProtoArgs<Tg>& operator += (GIOProtoArgs<Tg> &lhs, const GIOProtoArgs<Tg> &rhs);
 };
 
+template<typename Tg>
+cv::GIOProtoArgs<Tg>& operator += (cv::GIOProtoArgs<Tg> &lhs, const cv::GIOProtoArgs<Tg> &rhs)
+{
+    lhs.m_args.reserve(lhs.m_args.size() + rhs.m_args.size());
+    lhs.m_args.insert(lhs.m_args.end(), rhs.m_args.begin(), rhs.m_args.end());
+    return lhs;
+}
+
 struct In_Tag{};
 struct Out_Tag{};
 
index be20048..00abdd1 100644 (file)
@@ -26,10 +26,10 @@ struct GOrigin;
  * @{
  */
 
-class GAPI_EXPORTS GScalar
+class GAPI_EXPORTS_W_SIMPLE GScalar
 {
 public:
-    GScalar();                                         // Empty constructor
+    GAPI_WRAP GScalar();                    // Empty constructor
     explicit GScalar(const cv::Scalar& s);  // Constant value constructor from cv::Scalar
     explicit GScalar(cv::Scalar&& s);       // Constant value move-constructor from cv::Scalar
 
index 85bcb69..3235b1a 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GTYPE_TRAITS_HPP
@@ -15,9 +15,9 @@
 #include <opencv2/gapi/gscalar.hpp>
 #include <opencv2/gapi/garray.hpp>
 #include <opencv2/gapi/gopaque.hpp>
+#include <opencv2/gapi/gframe.hpp>
 #include <opencv2/gapi/streaming/source.hpp>
 #include <opencv2/gapi/gcommon.hpp>
-#include <opencv2/gapi/own/convert.hpp>
 
 namespace cv
 {
@@ -36,6 +36,7 @@ namespace detail
         GOBJREF,      // <internal> reference to object
         GMAT,         // a cv::GMat
         GMATP,        // a cv::GMatP
+        GFRAME,       // a cv::GFrame
         GSCALAR,      // a cv::GScalar
         GARRAY,       // a cv::GArrayU  (note - exactly GArrayU,  not GArray<T>!)
         GOPAQUE,      // a cv::GOpaqueU (note - exactly GOpaqueU, not GOpaque<T>!)
@@ -49,26 +50,37 @@ namespace detail
     template<typename T> struct GTypeTraits
     {
         static constexpr const ArgKind kind = ArgKind::OPAQUE_VAL;
+        static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
     };
     template<>           struct GTypeTraits<cv::GMat>
     {
         static constexpr const ArgKind kind = ArgKind::GMAT;
         static constexpr const GShape shape = GShape::GMAT;
+        static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
     };
     template<>           struct GTypeTraits<cv::GMatP>
     {
         static constexpr const ArgKind kind = ArgKind::GMATP;
         static constexpr const GShape shape = GShape::GMAT;
+        static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
+    };
+    template<>           struct GTypeTraits<cv::GFrame>
+    {
+        static constexpr const ArgKind kind = ArgKind::GFRAME;
+        static constexpr const GShape shape = GShape::GMAT;
+        static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
     };
     template<>           struct GTypeTraits<cv::GScalar>
     {
         static constexpr const ArgKind kind = ArgKind::GSCALAR;
         static constexpr const GShape shape = GShape::GSCALAR;
+        static constexpr const OpaqueKind op_kind = OpaqueKind::CV_UNKNOWN;
     };
     template<class T> struct GTypeTraits<cv::GArray<T> >
     {
         static constexpr const ArgKind kind = ArgKind::GARRAY;
         static constexpr const GShape shape = GShape::GARRAY;
+        static constexpr const OpaqueKind op_kind = GOpaqueTraits<T>::kind;
         using host_type  = std::vector<T>;
         using strip_type = cv::detail::VectorRef;
         static cv::detail::GArrayU   wrap_value(const cv::GArray<T>  &t) { return t.strip();}
@@ -79,6 +91,7 @@ namespace detail
     {
         static constexpr const ArgKind kind = ArgKind::GOPAQUE;
         static constexpr const GShape shape = GShape::GOPAQUE;
+        static constexpr const OpaqueKind op_kind = GOpaqueTraits<T>::kind;
         using host_type  = T;
         using strip_type = cv::detail::OpaqueRef;
         static cv::detail::GOpaqueU  wrap_value(const cv::GOpaque<T>  &t) { return t.strip();}
@@ -105,10 +118,9 @@ namespace detail
     // and GMat behavior is correct for GMatP)
     template<typename T> struct GTypeOf;
 #if !defined(GAPI_STANDALONE)
-    template<>           struct GTypeOf<cv::Mat>               { using type = cv::GMat;      };
     template<>           struct GTypeOf<cv::UMat>              { using type = cv::GMat;      };
 #endif // !defined(GAPI_STANDALONE)
-    template<>           struct GTypeOf<cv::gapi::own::Mat>    { using type = cv::GMat;      };
+    template<>           struct GTypeOf<cv::Mat>               { using type = cv::GMat;      };
     template<>           struct GTypeOf<cv::Scalar>            { using type = cv::GScalar;   };
     template<typename U> struct GTypeOf<std::vector<U> >       { using type = cv::GArray<U>; };
     template<typename U> struct GTypeOf                        { using type = cv::GOpaque<U>;};
index 1ce6201..6fe52a6 100644 (file)
@@ -26,6 +26,7 @@ namespace detail
     template<> struct ProtoToParam<cv::GMat>    { using type = cv::Mat; };
     template<> struct ProtoToParam<cv::GScalar> { using type = cv::Scalar; };
     template<typename U> struct ProtoToParam<cv::GArray<U> >  { using type = std::vector<U>; };
+    template<> struct ProtoToParam<cv::GArray<cv::GMat>>      { using type = std::vector<cv::Mat>; };
     template<typename U> struct ProtoToParam<cv::GOpaque<U> > { using type = U; };
     template<typename T> using ProtoToParamT = typename ProtoToParam<T>::type;
 
@@ -133,11 +134,19 @@ public:
     }
 
     void apply(detail::ProtoToParamT<Args>... inArgs,
+               detail::ProtoToParamT<R> &outArg,
+               GCompileArgs &&args)
+    {
+        m_comp.apply(cv::gin(inArgs...), cv::gout(outArg), std::move(args));
+    }
+
+    void apply(detail::ProtoToParamT<Args>... inArgs,
                detail::ProtoToParamT<R> &outArg)
     {
-        m_comp.apply(cv::gin(inArgs...), cv::gout(outArg));
+        apply(inArgs..., outArg, GCompileArgs());
     }
 
+
     GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs)
     {
         GMetaArgs inMetas = { GMetaArg(inDescs)... };
@@ -206,11 +215,19 @@ public:
     }
 
     void apply(detail::ProtoToParamT<Args>... inArgs,
+               detail::ProtoToParamT<R>&... outArgs,
+               GCompileArgs &&args)
+    {
+        m_comp.apply(cv::gin(inArgs...), cv::gout(outArgs...), std::move(args));
+    }
+
+    void apply(detail::ProtoToParamT<Args>... inArgs,
                detail::ProtoToParamT<R>&... outArgs)
     {
-        m_comp.apply(cv::gin(inArgs...), cv::gout(outArgs...));
+        apply(inArgs..., outArgs..., GCompileArgs());
     }
 
+
     GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs)
     {
         GMetaArgs inMetas = { GMetaArg(inDescs)... };
index 775c30a..b4905e9 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_IMGPROC_HPP
@@ -90,6 +90,20 @@ namespace imgproc {
         }
     };
 
+    G_TYPED_KERNEL(GLaplacian, <GMat(GMat,int, int, double, double, int)>,
+                   "org.opencv.imgproc.filters.laplacian") {
+        static GMatDesc outMeta(GMatDesc in, int ddepth, int, double, double, int) {
+            return in.withDepth(ddepth);
+        }
+    };
+
+    G_TYPED_KERNEL(GBilateralFilter, <GMat(GMat,int, double, double, int)>,
+                   "org.opencv.imgproc.filters.bilateralfilter") {
+        static GMatDesc outMeta(GMatDesc in, int, double, double, int) {
+            return in;
+        }
+    };
+
     G_TYPED_KERNEL(GEqHist, <GMat(GMat)>, "org.opencv.imgproc.equalizeHist"){
         static GMatDesc outMeta(GMatDesc in) {
             return in.withType(CV_8U, 1);
@@ -102,6 +116,14 @@ namespace imgproc {
         }
     };
 
+    G_TYPED_KERNEL(GGoodFeatures,
+                   <cv::GArray<cv::Point2f>(GMat,int,double,double,Mat,int,bool,double)>,
+                   "org.opencv.imgproc.goodFeaturesToTrack") {
+        static GArrayDesc outMeta(GMatDesc, int, double, double, const Mat&, int, bool, double) {
+            return empty_array_desc();
+        }
+    };
+
     G_TYPED_KERNEL(GRGB2YUV, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.rgb2yuv") {
         static GMatDesc outMeta(GMatDesc in) {
             return in; // type still remains CV_8UC3;
@@ -251,8 +273,7 @@ namespace imgproc {
         }
     };
 
-}
-
+} //namespace imgproc
 
 //! @addtogroup gapi_filters
 //! @{
@@ -298,7 +319,7 @@ according to the specified border mode.
 
 The function does actually compute correlation, not the convolution:
 
-\f[\texttt{dst} (x,y) =  \sum _{ \stackrel{0\leq x' < \texttt{kernel.cols},}{0\leq y' < \texttt{kernel.rows}} }  \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f]
+\f[\texttt{dst} (x,y) =  \sum _{ \substack{0\leq x' < \texttt{kernel.cols}\\{0\leq y' < \texttt{kernel.rows}}}}  \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f]
 
 That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip
 the kernel using flip and set the new anchor to `(kernel.cols - anchor.x - 1, kernel.rows -
@@ -335,7 +356,7 @@ The function smooths an image using the kernel:
 
 where
 
-\f[\alpha = \fork{\frac{1}{\texttt{ksize.width*ksize.height}}}{when \texttt{normalize=true}}{1}{otherwise}\f]
+\f[\alpha = \begin{cases} \frac{1}{\texttt{ksize.width*ksize.height}} & \texttt{when } \texttt{normalize=true}  \\1 & \texttt{otherwise} \end{cases}\f]
 
 Unnormalized box filter is useful for computing various integral characteristics over each pixel
 neighborhood, such as covariance matrices of image derivatives (used in dense optical flow
@@ -367,8 +388,8 @@ The function smooths an image using the kernel:
 
 \f[\texttt{K} =  \frac{1}{\texttt{ksize.width*ksize.height}} \begin{bmatrix} 1 & 1 & 1 &  \cdots & 1 & 1  \\ 1 & 1 & 1 &  \cdots & 1 & 1  \\ \hdotsfor{6} \\ 1 & 1 & 1 &  \cdots & 1 & 1  \\ \end{bmatrix}\f]
 
-The call `blur(src, dst, ksize, anchor, borderType)` is equivalent to `boxFilter(src, dst, src.type(),
-anchor, true, borderType)`.
+The call `blur(src, ksize, anchor, borderType)` is equivalent to `boxFilter(src, src.type(), ksize, anchor,
+true, borderType)`.
 
 Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
 Output image must have the same type, size, and number of channels as the input image.
@@ -636,6 +657,68 @@ GAPI_EXPORTS std::tuple<GMat, GMat> SobelXY(const GMat& src, int ddepth, int ord
                         int borderType = BORDER_DEFAULT,
                         const Scalar& borderValue = Scalar(0));
 
+/** @brief Calculates the Laplacian of an image.
+
+The function calculates the Laplacian of the source image by adding up the second x and y
+derivatives calculated using the Sobel operator:
+
+\f[\texttt{dst} =  \Delta \texttt{src} =  \frac{\partial^2 \texttt{src}}{\partial x^2} +  \frac{\partial^2 \texttt{src}}{\partial y^2}\f]
+
+This is done when `ksize > 1`. When `ksize == 1`, the Laplacian is computed by filtering the image
+with the following \f$3 \times 3\f$ aperture:
+
+\f[\vecthreethree {0}{1}{0}{1}{-4}{1}{0}{1}{0}\f]
+
+@note Function textual ID is "org.opencv.imgproc.filters.laplacian"
+
+@param src Source image.
+@param ddepth Desired depth of the destination image.
+@param ksize Aperture size used to compute the second-derivative filters. See #getDerivKernels for
+details. The size must be positive and odd.
+@param scale Optional scale factor for the computed Laplacian values. By default, no scaling is
+applied. See #getDerivKernels for details.
+@param delta Optional delta value that is added to the results prior to storing them in dst .
+@param borderType Pixel extrapolation method, see #BorderTypes. #BORDER_WRAP is not supported.
+@return Destination image of the same size and the same number of channels as src.
+@sa  Sobel, Scharr
+ */
+GAPI_EXPORTS GMat Laplacian(const GMat& src, int ddepth, int ksize = 1,
+                            double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT);
+
+/** @brief Applies the bilateral filter to an image.
+
+The function applies bilateral filtering to the input image, as described in
+http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html
+bilateralFilter can reduce unwanted noise very well while keeping edges fairly sharp. However, it is
+very slow compared to most filters.
+
+_Sigma values_: For simplicity, you can set the 2 sigma values to be the same. If they are small (\<
+10), the filter will not have much effect, whereas if they are large (\> 150), they will have a very
+strong effect, making the image look "cartoonish".
+
+_Filter size_: Large filters (d \> 5) are very slow, so it is recommended to use d=5 for real-time
+applications, and perhaps d=9 for offline applications that need heavy noise filtering.
+
+This filter does not work inplace.
+
+@note Function textual ID is "org.opencv.imgproc.filters.bilateralfilter"
+
+@param src Source 8-bit or floating-point, 1-channel or 3-channel image.
+@param d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive,
+it is computed from sigmaSpace.
+@param sigmaColor Filter sigma in the color space. A larger value of the parameter means that
+farther colors within the pixel neighborhood (see sigmaSpace) will be mixed together, resulting
+in larger areas of semi-equal color.
+@param sigmaSpace Filter sigma in the coordinate space. A larger value of the parameter means that
+farther pixels will influence each other as long as their colors are close enough (see sigmaColor
+). When d\>0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is
+proportional to sigmaSpace.
+@param borderType border mode used to extrapolate pixels outside of the image, see #BorderTypes
+@return Destination image of the same size and type as src.
+ */
+GAPI_EXPORTS GMat bilateralFilter(const GMat& src, int d, double sigmaColor, double sigmaSpace,
+                                  int borderType = BORDER_DEFAULT);
+
 /** @brief Finds edges in an image using the Canny algorithm.
 
 The function finds edges in the input image and marks them in the output map edges using the
@@ -657,6 +740,59 @@ L2gradient=false ).
 GAPI_EXPORTS GMat Canny(const GMat& image, double threshold1, double threshold2,
                         int apertureSize = 3, bool L2gradient = false);
 
+/** @brief Determines strong corners on an image.
+
+The function finds the most prominent corners in the image or in the specified image region, as
+described in @cite Shi94
+
+-   Function calculates the corner quality measure at every source image pixel using the
+    #cornerMinEigenVal or #cornerHarris .
+-   Function performs a non-maximum suppression (the local maximums in *3 x 3* neighborhood are
+    retained).
+-   The corners with the minimal eigenvalue less than
+    \f$\texttt{qualityLevel} \cdot \max_{x,y} qualityMeasureMap(x,y)\f$ are rejected.
+-   The remaining corners are sorted by the quality measure in the descending order.
+-   Function throws away each corner for which there is a stronger corner at a distance less than
+    maxDistance.
+
+The function can be used to initialize a point-based tracker of an object.
+
+@note If the function is called with different values A and B of the parameter qualityLevel , and
+A \> B, the vector of returned corners with qualityLevel=A will be the prefix of the output vector
+with qualityLevel=B .
+
+@note Function textual ID is "org.opencv.imgproc.goodFeaturesToTrack"
+
+@param image Input 8-bit or floating-point 32-bit, single-channel image.
+@param maxCorners Maximum number of corners to return. If there are more corners than are found,
+the strongest of them is returned. `maxCorners <= 0` implies that no limit on the maximum is set
+and all detected corners are returned.
+@param qualityLevel Parameter characterizing the minimal accepted quality of image corners. The
+parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue
+(see #cornerMinEigenVal ) or the Harris function response (see #cornerHarris ). The corners with the
+quality measure less than the product are rejected. For example, if the best corner has the
+quality measure = 1500, and the qualityLevel=0.01 , then all the corners with the quality measure
+less than 15 are rejected.
+@param minDistance Minimum possible Euclidean distance between the returned corners.
+@param mask Optional region of interest. If the image is not empty (it needs to have the type
+CV_8UC1 and the same size as image ), it specifies the region in which the corners are detected.
+@param blockSize Size of an average block for computing a derivative covariation matrix over each
+pixel neighborhood. See cornerEigenValsAndVecs .
+@param useHarrisDetector Parameter indicating whether to use a Harris detector (see #cornerHarris)
+or #cornerMinEigenVal.
+@param k Free parameter of the Harris detector.
+
+@return vector of detected corners.
+ */
+GAPI_EXPORTS GArray<Point2f> goodFeaturesToTrack(const GMat  &image,
+                                                       int    maxCorners,
+                                                       double qualityLevel,
+                                                       double minDistance,
+                                                 const Mat   &mask = Mat(),
+                                                       int    blockSize = 3,
+                                                       bool   useHarrisDetector = false,
+                                                       double k = 0.04);
+
 /** @brief Equalizes the histogram of a grayscale image.
 
 The function equalizes the histogram of the input image using the following algorithm:
index 5a4caff..50086dd 100644 (file)
@@ -14,6 +14,7 @@
 #include <functional>
 #include <string>  // string
 #include <utility> // tuple
+#include <type_traits> // is_same, false_type
 
 #include <opencv2/gapi/util/any.hpp>  // any<>
 #include <opencv2/gapi/gkernel.hpp>   // GKernelType[M], GBackend
@@ -25,6 +26,43 @@ namespace cv {
 
 template<typename, typename> class GNetworkType;
 
+namespace detail {
+    template<typename, typename>
+    struct valid_infer2_types;
+
+    // Terminal case 1 (50/50 success)
+    template<typename T>
+    struct valid_infer2_types< std::tuple<cv::GMat>, std::tuple<T> > {
+        // By default, Nets are limited to GMat argument types only
+        // for infer2, every GMat argument may translate to either
+        // GArray<GMat> or GArray<Rect>. GArray<> part is stripped
+        // already at this point.
+        static constexpr const auto value =
+                std::is_same<typename std::decay<T>::type, cv::GMat>::value
+             || std::is_same<typename std::decay<T>::type, cv::Rect>::value;
+    };
+
+    // Terminal case 2 (100% failure)
+    template<typename... Ts>
+    struct valid_infer2_types< std::tuple<>, std::tuple<Ts...> >
+        : public std::false_type {
+    };
+
+    // Terminal case 3 (100% failure)
+    template<typename... Ns>
+    struct valid_infer2_types< std::tuple<Ns...>, std::tuple<> >
+        : public std::false_type {
+    };
+
+    // Recursion -- generic
+    template<typename... Ns, typename T, typename...Ts>
+    struct valid_infer2_types< std::tuple<cv::GMat,Ns...>, std::tuple<T,Ts...> > {
+        static constexpr const auto value =
+               valid_infer2_types< std::tuple<cv::GMat>, std::tuple<T> >::value
+            && valid_infer2_types< std::tuple<Ns...>, std::tuple<Ts...> >::value;
+    };
+} // namespace detail
+
 // TODO: maybe tuple_wrap_helper from util.hpp may help with this.
 // Multiple-return-value network definition (specialized base class)
 template<typename K, typename... R, typename... Args>
@@ -56,6 +94,17 @@ public:
     using APIList = std::function<ResultL(cv::GArray<cv::Rect>, Args...)>;
 };
 
+// APIList2 is also template to allow different calling options
+// (GArray<cv::Rect> vs GArray<cv::GMat> per input)
+template<class Net, class... Ts>
+struct InferAPIList2 {
+    using type = typename std::enable_if
+        < cv::detail::valid_infer2_types< typename Net::InArgs
+                                        , std::tuple<Ts...> >::value,
+          std::function<typename Net::ResultL(cv::GMat, cv::GArray<Ts>...)>
+        >::type;
+};
+
 // Base "Infer" kernel. Note - for whatever network, kernel ID
 // is always the same. Different inference calls are distinguished by
 // network _tag_ (an extra field in GCall)
@@ -77,10 +126,21 @@ struct GInferBase {
 // All notes from "Infer" kernel apply here as well.
 struct GInferListBase {
     static constexpr const char * id() {
-        return "org.opencv.dnn.infer-roi"; // Universal stub
+        return "org.opencv.dnn.infer-roi";      // Universal stub
     }
     static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) {
-        return GMetaArgs{};                // One more universal stub
+        return GMetaArgs{};                     // One more universal stub
+    }
+};
+
+// Base "Infer list 2" kernel.
+// All notes from "Infer" kernel apply here as well.
+struct GInferList2Base {
+    static constexpr const char * id() {
+        return "org.opencv.dnn.infer-roi-list"; // Universal stub
+    }
+    static GMetaArgs getOutMeta(const GMetaArgs &, const GArgs &) {
+        return GMetaArgs{};                     // One more universal stub
     }
 };
 
@@ -109,6 +169,21 @@ struct GInferList final
     static constexpr const char* tag() { return Net::tag(); }
 };
 
+// An even more generic roi-list inference kernel. API (::on()) is
+// derived from the Net template parameter (see more in infer<>
+// overload).
+// Takes an extra variadic template list to reflect how this network
+// was called (with Rects or GMats as array parameters)
+template<typename Net, typename... Args>
+struct GInferList2 final
+    : public GInferList2Base
+    , public detail::KernelTypeMedium< GInferList2<Net, Args...>
+                                     , typename InferAPIList2<Net, Args...>::type > {
+    using GInferList2Base::getOutMeta; // FIXME: name lookup conflict workaround?
+
+    static constexpr const char* tag() { return Net::tag(); }
+};
+
 } // namespace cv
 
 // FIXME: Probably the <API> signature makes a function/tuple/function round-trip
@@ -139,6 +214,30 @@ typename Net::ResultL infer(cv::GArray<cv::Rect> roi, Args&&... args) {
     return GInferList<Net>::on(roi, std::forward<Args>(args)...);
 }
 
+/** @brief Calculates responses for the specified network (template
+ *     parameter) for every region in the source image, extended version.
+ *
+ * @tparam A network type defined with G_API_NET() macro.
+ * @param image A source image containing regions of interest
+ * @param args GArray<> objects of cv::Rect or cv::GMat, one per every
+ * network input:
+ * - If a cv::GArray<cv::Rect> is passed, the appropriate
+ *   regions are taken from `image` and preprocessed to this particular
+ *   network input;
+ * - If a cv::GArray<cv::GMat> is passed, the underlying data traited
+ *   as tensor (no automatic preprocessing happen).
+ * @return a list of objects of return type as defined in G_API_NET().
+ *   If a network has multiple return values (defined with a tuple), a tuple of
+ *   GArray<> objects is returned with the appropriate types inside.
+ * @sa  G_API_NET()
+ */
+template<typename Net, typename... Args>
+typename Net::ResultL infer2(cv::GMat image, cv::GArray<Args>... args) {
+    // FIXME: Declared as "2" because in the current form it steals
+    // overloads from the regular infer
+    return GInferList2<Net, Args...>::on(image, args...);
+}
+
 /**
  * @brief Calculates response for the specified network (template
  *     parameter) given the input data.
index 6e8c2c3..c6d7f27 100644 (file)
@@ -78,8 +78,8 @@ public:
            const std::string &weights,
            const std::string &device)
         : desc{ model, weights, device, {}, {}, {}
-              , std::tuple_size<typename Net::InArgs>::value
-              , std::tuple_size<typename Net::OutArgs>::value
+              , std::tuple_size<typename Net::InArgs>::value  // num_in
+              , std::tuple_size<typename Net::OutArgs>::value // num_out
               } {
     };
 
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/parsers.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/parsers.hpp
new file mode 100644 (file)
index 0000000..c3488f5
--- /dev/null
@@ -0,0 +1,125 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_PARSERS_HPP
+#define OPENCV_GAPI_PARSERS_HPP
+
+#include <utility> // std::tuple
+
+#include <opencv2/gapi/gmat.hpp>
+#include <opencv2/gapi/gkernel.hpp>
+
+namespace cv { namespace gapi {
+namespace nn {
+namespace parsers {
+    using GRects      = GArray<Rect>;
+    using GDetections = std::tuple<GArray<Rect>, GArray<int>>;
+
+    G_TYPED_KERNEL(GParseSSDBL, <GDetections(GMat, GOpaque<Size>, float, int)>,
+                   "org.opencv.nn.parsers.parseSSD_BL") {
+        static std::tuple<GArrayDesc,GArrayDesc> outMeta(const GMatDesc&, const GOpaqueDesc&, float, int) {
+            return std::make_tuple(empty_array_desc(), empty_array_desc());
+        }
+    };
+
+    G_TYPED_KERNEL(GParseSSD, <GRects(GMat, GOpaque<Size>, float, bool, bool)>,
+                   "org.opencv.nn.parsers.parseSSD") {
+        static GArrayDesc outMeta(const GMatDesc&, const GOpaqueDesc&, float, bool, bool) {
+            return empty_array_desc();
+        }
+    };
+
+    G_TYPED_KERNEL(GParseYolo, <GDetections(GMat, GOpaque<Size>, float, float, std::vector<float>)>,
+                   "org.opencv.nn.parsers.parseYolo") {
+        static std::tuple<GArrayDesc, GArrayDesc> outMeta(const GMatDesc&, const GOpaqueDesc&,
+                                                          float, float, const std::vector<float>&) {
+            return std::make_tuple(empty_array_desc(), empty_array_desc());
+        }
+        static const std::vector<float>& defaultAnchors() {
+            static std::vector<float> anchors {
+                0.57273f, 0.677385f, 1.87446f, 2.06253f, 3.33843f, 5.47434f, 7.88282f, 3.52778f, 9.77052f, 9.16828f
+            };
+            return anchors;
+        }
+    };
+} // namespace parsers
+} // namespace nn
+
+/** @brief Parses output of SSD network.
+
+Extracts detection information (box, confidence, label) from SSD output and
+filters it by given confidence and label.
+
+@note Function textual ID is "org.opencv.nn.parsers.parseSSD_BL"
+
+@param in Input CV_32F tensor with {1,1,N,7} dimensions.
+@param inSz Size to project detected boxes to (size of the input image).
+@param confidenceThreshold If confidence of the
+detection is smaller than confidence threshold, detection is rejected.
+@param filterLabel If provided (!= -1), only detections with
+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);
+
+/** @overload
+Extracts detection information (box, confidence) from SSD output and
+filters it by given confidence and by going out of bounds.
+
+@note Function textual ID is "org.opencv.nn.parsers.parseSSD"
+
+@param in Input CV_32F tensor with {1,1,N,7} dimensions.
+@param inSz Size to project detected boxes to (size of the input image).
+@param confidenceThreshold If confidence of the
+detection is smaller than confidence threshold, detection is rejected.
+@param alignmentToSquare If provided true, bounding boxes are extended to squares.
+The center of the rectangle remains unchanged, the side of the square is
+the larger side of the rectangle.
+@param filterOutOfBounds If provided true, out-of-frame boxes are filtered.
+@return a vector of detected bounding boxes.
+*/
+GAPI_EXPORTS GArray<Rect> parseSSD(const GMat& in,
+                                   const GOpaque<Size>& inSz,
+                                   const float confidenceThreshold = 0.5f,
+                                   const bool alignmentToSquare = false,
+                                   const bool filterOutOfBounds = false);
+
+/** @brief Parses output of Yolo network.
+
+Extracts detection information (box, confidence, label) from Yolo output,
+filters it by given confidence and performs non-maximum supression for overlapping boxes.
+
+@note Function textual ID is "org.opencv.nn.parsers.parseYolo"
+
+@param in Input CV_32F tensor with {1,13,13,N} dimensions, N should satisfy:
+\f[\texttt{N} = (\texttt{num_classes} + \texttt{5}) * \texttt{5},\f]
+where num_classes - a number of classes Yolo network was trained with.
+@param inSz Size to project detected boxes to (size of the input image).
+@param confidenceThreshold If confidence of the
+detection is smaller than confidence threshold, detection is rejected.
+@param nmsThreshold Non-maximum supression threshold which controls minimum
+relative box intersection area required for rejecting the box with a smaller confidence.
+If 1.f, nms is not performed and no boxes are rejected.
+@param anchors Anchors Yolo network was trained with.
+@note The default anchor values are taken from openvinotoolkit docs:
+https://docs.openvinotoolkit.org/latest/omz_models_intel_yolo_v2_tiny_vehicle_detection_0001_description_yolo_v2_tiny_vehicle_detection_0001.html#output.
+@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());
+
+} // namespace gapi
+} // namespace cv
+
+#endif // OPENCV_GAPI_PARSERS_HPP
index 4ab85e2..6c75870 100644 (file)
@@ -16,7 +16,7 @@ namespace gapi {
 namespace core {
 namespace ocl {
 
-        GAPI_EXPORTS GKernelPackage kernels();
+        GAPI_EXPORTS_W cv::gapi::GKernelPackage kernels();
 
 } // namespace ocl
 } // namespace core
index 5acf280..5f25fe4 100644 (file)
 #  include <opencv2/core/base.hpp>
 #else   // Without OpenCV
 #  include <opencv2/gapi/own/cvdefs.hpp>
+#  include <opencv2/gapi/own/types.hpp>  // cv::gapi::own::Rect/Size/Point
+#  include <opencv2/gapi/own/scalar.hpp> // cv::gapi::own::Scalar
+#  include <opencv2/gapi/own/mat.hpp>
+// replacement of cv's structures:
+namespace cv {
+    using Rect   = gapi::own::Rect;
+    using Size   = gapi::own::Size;
+    using Point  = gapi::own::Point;
+    using Scalar = gapi::own::Scalar;
+    using Mat    = gapi::own::Mat;
+}  // namespace cv
 #endif // !defined(GAPI_STANDALONE)
 
 #endif // OPENCV_GAPI_OPENCV_INCLUDES_HPP
index b20062c..6794b44 100644 (file)
@@ -11,6 +11,8 @@
 #include <opencv2/gapi/gmat.hpp>
 #include <opencv2/gapi/gscalar.hpp>
 
+namespace cv
+{
 GAPI_EXPORTS cv::GMat operator+(const cv::GMat&    lhs, const cv::GMat&    rhs);
 
 GAPI_EXPORTS cv::GMat operator+(const cv::GMat&    lhs, const cv::GScalar& rhs);
@@ -63,7 +65,6 @@ GAPI_EXPORTS cv::GMat operator<(const cv::GScalar&    lhs, const cv::GMat& rhs);
 GAPI_EXPORTS cv::GMat operator<=(const cv::GScalar&   lhs, const cv::GMat& rhs);
 GAPI_EXPORTS cv::GMat operator==(const cv::GScalar&   lhs, const cv::GMat& rhs);
 GAPI_EXPORTS cv::GMat operator!=(const cv::GScalar&   lhs, const cv::GMat& rhs);
-
-
+} // cv
 
 #endif // OPENCV_GAPI_OPERATORS_HPP
index 92b246f..d0e0f1c 100644 (file)
@@ -20,7 +20,7 @@
 
 namespace detail
 {
-    inline void assert_abort(const char* str, int line, const char* file, const char* func)
+    [[noreturn]] inline void assert_abort(const char* str, int line, const char* file, const char* func)
     {
         std::stringstream ss;
         ss << file << ":" << line << ": Assertion " << str << " in function " << func << " failed\n";
index 58f291c..1a8ecd8 100644 (file)
@@ -25,23 +25,27 @@ namespace cv
         return result;
     }
 
-           cv::gapi::own::Mat to_own(Mat&&) = delete;
+    cv::gapi::own::Mat to_own(Mat&&) = delete;
 
     inline cv::gapi::own::Mat to_own(Mat const& m) {
         return (m.dims == 2)
             ?  cv::gapi::own::Mat{m.rows, m.cols, m.type(), m.data, m.step}
             :  cv::gapi::own::Mat{to_own<int>(m.size), m.type(), m.data};
     };
+
 namespace gapi
 {
 namespace own
 {
+
     inline cv::Mat to_ocv(Mat const& m) {
         return m.dims.empty()
             ? cv::Mat{m.rows, m.cols, m.type(), m.data, m.step}
             : cv::Mat{m.dims, m.type(), m.data};
     }
-           cv::Mat to_ocv(Mat&&)    = delete;
+
+    cv::Mat to_ocv(Mat&&) = delete;
+
 } // namespace own
 } // namespace gapi
 } // namespace cv
index 354609b..9ec0f89 100644 (file)
@@ -9,9 +9,6 @@
 #define OPENCV_GAPI_CV_DEFS_HPP
 
 #if defined(GAPI_STANDALONE)
-#include <opencv2/gapi/own/types.hpp> // cv::gapi::own::Rect/Size/Point
-#include <opencv2/gapi/own/scalar.hpp> // cv::gapi::own::Scalar
-
 // Simulate OpenCV definitions taken from various
 // OpenCV interface headers if G-API is built in a
 // standalone mode.
@@ -139,11 +136,6 @@ enum InterpolationFlags{
     INTER_LINEAR_EXACT   = 5,
     INTER_MAX            = 7,
 };
-// replacement of cv's structures:
-using Rect   = gapi::own::Rect;
-using Size   = gapi::own::Size;
-using Point  = gapi::own::Point;
-using Scalar = gapi::own::Scalar;
 } // namespace cv
 
 static inline int cvFloor( double value )
index 53bff2a..da42a32 100644 (file)
 #   if defined(__OPENCV_BUILD)
 #       include <opencv2/core/base.hpp>
 #       define GAPI_EXPORTS CV_EXPORTS
+        /* special informative macros for wrapper generators */
+#       define GAPI_WRAP CV_WRAP
+#       define GAPI_EXPORTS_W_SIMPLE CV_EXPORTS_W_SIMPLE
+#       define GAPI_EXPORTS_W CV_EXPORTS_W
 #   else
+#       define GAPI_WRAP
 #       define GAPI_EXPORTS
+#       define GAPI_EXPORTS_W_SIMPLE
+#       define GAPI_EXPORTS_W
 
 #if 0  // Note: the following version currently is not needed for non-OpenCV build
 #       if defined _WIN32
index a5f5b5e..a109858 100644 (file)
@@ -17,6 +17,7 @@
 #include <memory>                   //std::shared_ptr
 #include <cstring>                  //std::memcpy
 #include <numeric>                  //std::accumulate
+#include <vector>
 #include <opencv2/gapi/util/throw.hpp>
 
 namespace cv { namespace gapi { namespace own {
@@ -123,11 +124,11 @@ namespace cv { namespace gapi { namespace own {
            data = ptr(roi.y, roi.x);
         }
 
-        Mat(Mat const& src) = default;
-        Mat(Mat&& src) = default;
+        Mat(Mat const& ) = default;
+        Mat(Mat&& ) = default;
 
-        Mat& operator=(Mat const& src) = default;
-        Mat& operator=(Mat&& src) = default;
+        Mat& operator=(Mat const& ) = default;
+        Mat& operator=(Mat&& ) = default;
 
         /** @brief Sets all or some of the array elements to the specified value.
         @param s Assigned scalar converted to the actual array type.
index 47ac486..3c63fed 100644 (file)
@@ -13,7 +13,7 @@
 
 namespace cv { namespace gapi { namespace core { namespace plaidml {
 
-GAPI_EXPORTS GKernelPackage kernels();
+GAPI_EXPORTS cv::gapi::GKernelPackage kernels();
 
 }}}}
 
index fcb69cb..a4df304 100644 (file)
@@ -2,23 +2,16 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018-2019 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_RENDER_HPP
 #define OPENCV_GAPI_RENDER_HPP
 
-#include <string>
-#include <vector>
+#include <opencv2/gapi/render/render_types.hpp>
 
-#include <opencv2/imgproc.hpp>
 #include <opencv2/gapi.hpp>
 
-#include <opencv2/gapi/opencv_includes.hpp>
-#include <opencv2/gapi/util/variant.hpp>
-#include <opencv2/gapi/own/exports.hpp>
-
-
 /** \defgroup gapi_draw G-API Drawing and composition functionality
  *  @{
  *
@@ -77,309 +70,9 @@ namespace wip
 namespace draw
 {
 
-/**
- * @brief This structure specifies which FreeType font to use by FText primitives.
- */
-struct freetype_font
-{
-    /*@{*/
-    std::string path; //!< The path to the font file (.ttf)
-    /*@{*/
-};
-
-//! @addtogroup gapi_draw_prims
-//! @{
-/**
- * @brief This structure represents a text string to draw.
- *
- * Parameters match cv::putText().
- */
-struct Text
-{
-    /**
-     * @brief Text constructor
-     *
-     * @param text_               The text string to be drawn
-     * @param org_                The bottom-left corner of the text string in the image
-     * @param ff_                 The font type, see #HersheyFonts
-     * @param fs_                 The font scale factor that is multiplied by the font-specific base size
-     * @param color_              The text color
-     * @param thick_              The thickness of the lines used to draw a text
-     * @param lt_                 The line type. See #LineTypes
-     * @param bottom_left_origin_ When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
-     */
-    Text(const std::string& text_,
-         const cv::Point& org_,
-         int ff_,
-         double fs_,
-         const cv::Scalar& color_,
-         int thick_ = 1,
-         int lt_ = cv::LINE_8,
-         bool bottom_left_origin_ = false) :
-        text(text_), org(org_), ff(ff_), fs(fs_),
-        color(color_), thick(thick_), lt(lt_), bottom_left_origin(bottom_left_origin_)
-    {
-    }
-
-    /*@{*/
-    std::string text;               //!< The text string to be drawn
-    cv::Point   org;                //!< The bottom-left corner of the text string in the image
-    int         ff;                 //!< The font type, see #HersheyFonts
-    double      fs;                 //!< The font scale factor that is multiplied by the font-specific base size
-    cv::Scalar  color;              //!< The text color
-    int         thick;              //!< The thickness of the lines used to draw a text
-    int         lt;                 //!< The line type. See #LineTypes
-    bool        bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
-    /*@{*/
-};
-
-/**
- * @brief This structure represents a text string to draw using
- * FreeType renderer.
- *
- * If OpenCV is built without FreeType support, this primitive will
- * fail at the execution stage.
- */
-struct FText
-{
-    /**
-     * @brief FText constructor
-     *
-     * @param text_ The text string to be drawn
-     * @param org_  The bottom-left corner of the text string in the image
-     * @param fh_   The height of text
-     * @param color_ The text color
-     */
-    FText(const std::wstring& text_,
-          const cv::Point& org_,
-          int fh_,
-          const cv::Scalar& color_) :
-        text(text_), org(org_), fh(fh_), color(color_)
-    {
-    }
-
-    /*@{*/
-    std::wstring text;              //!< The text string to be drawn
-    cv::Point    org;               //!< The bottom-left corner of the text string in the image
-    int          fh;                //!< The height of text
-    cv::Scalar   color;             //!< The text color
-    /*@{*/
-};
-
-/**
- * @brief This structure represents a rectangle to draw.
- *
- * Parameters match cv::rectangle().
- */
-struct Rect
-{
-    /**
-     * @brief Rect constructor
-     *
-     * @param rect_   Coordinates of the rectangle
-     * @param color_  The bottom-left corner of the text string in the image
-     * @param thick_  The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
-     * @param lt_     The type of the line. See #LineTypes
-     * @param shift_  The number of fractional bits in the point coordinates
-     */
-    Rect(const cv::Rect& rect_,
-         const cv::Scalar& color_,
-         int thick_ = 1,
-         int lt_ = cv::LINE_8,
-         int shift_ = 0) :
-        rect(rect_), color(color_), thick(thick_), lt(lt_), shift(shift_)
-    {
-    }
-
-    /*@{*/
-    cv::Rect   rect;  //!< Coordinates of the rectangle
-    cv::Scalar color; //!< The rectangle color or brightness (grayscale image)
-    int        thick; //!< The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
-    int        lt;    //!< The type of the line. See #LineTypes
-    int        shift; //!< The number of fractional bits in the point coordinates
-    /*@{*/
-};
-
-/**
- * @brief This structure represents a circle to draw.
- *
- * Parameters match cv::circle().
- */
-struct Circle
-{
-    /**
-     * @brief Circle constructor
-     *
-     * @param  center_ The center of the circle
-     * @param  radius_ The radius of the circle
-     * @param  color_  The color of the  circle
-     * @param  thick_  The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
-     * @param  lt_     The Type of the circle boundary. See #LineTypes
-     * @param  shift_  The Number of fractional bits in the coordinates of the center and in the radius value
-     */
-    Circle(const cv::Point& center_,
-           int radius_,
-           const cv::Scalar& color_,
-           int thick_ = 1,
-           int lt_ = cv::LINE_8,
-           int shift_ = 0) :
-        center(center_), radius(radius_), color(color_), thick(thick_), lt(lt_), shift(shift_)
-    {
-    }
-
-    /*@{*/
-    cv::Point  center; //!< The center of the circle
-    int        radius; //!< The radius of the circle
-    cv::Scalar color;  //!< The color of the  circle
-    int        thick;  //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
-    int        lt;     //!< The Type of the circle boundary. See #LineTypes
-    int        shift;  //!< The Number of fractional bits in the coordinates of the center and in the radius value
-    /*@{*/
-};
-
-/**
- * @brief This structure represents a line to draw.
- *
- * Parameters match cv::line().
- */
-struct Line
-{
-    /**
-     * @brief Line constructor
-     *
-     * @param  pt1_    The first point of the line segment
-     * @param  pt2_    The second point of the line segment
-     * @param  color_  The line color
-     * @param  thick_  The thickness of line
-     * @param  lt_     The Type of the line. See #LineTypes
-     * @param  shift_  The number of fractional bits in the point coordinates
-    */
-    Line(const cv::Point& pt1_,
-         const cv::Point& pt2_,
-         const cv::Scalar& color_,
-         int thick_ = 1,
-         int lt_ = cv::LINE_8,
-         int shift_ = 0) :
-        pt1(pt1_), pt2(pt2_), color(color_), thick(thick_), lt(lt_), shift(shift_)
-    {
-    }
-
-    /*@{*/
-    cv::Point  pt1;    //!< The first point of the line segment
-    cv::Point  pt2;    //!< The second point of the line segment
-    cv::Scalar color;  //!< The line color
-    int        thick;  //!< The thickness of line
-    int        lt;     //!< The Type of the line. See #LineTypes
-    int        shift;  //!< The number of fractional bits in the point coordinates
-    /*@{*/
-};
-
-/**
- * @brief This structure represents a mosaicing operation.
- *
- * Mosaicing is a very basic method to obfuscate regions in the image.
- */
-struct Mosaic
-{
-    /**
-     * @brief Mosaic constructor
-     *
-     * @param mos_    Coordinates of the mosaic
-     * @param cellSz_ Cell size (same for X, Y)
-     * @param decim_  Decimation (0 stands for no decimation)
-    */
-    Mosaic(const cv::Rect& mos_,
-           int cellSz_,
-           int decim_) :
-        mos(mos_), cellSz(cellSz_), decim(decim_)
-    {
-    }
-
-    /*@{*/
-    cv::Rect   mos;    //!< Coordinates of the mosaic
-    int        cellSz; //!< Cell size (same for X, Y)
-    int        decim;  //!< Decimation (0 stands for no decimation)
-    /*@{*/
-};
-
-/**
- * @brief This structure represents an image to draw.
- *
- * Image is blended on a frame using the specified mask.
- */
-struct Image
-{
-    /**
-     * @brief Mosaic constructor
-     *
-     * @param  org_   The bottom-left corner of the image
-     * @param  img_   Image to draw
-     * @param  alpha_ Alpha channel for image to draw (same size and number of channels)
-    */
-    Image(const cv::Point& org_,
-          const cv::Mat& img_,
-          const cv::Mat& alpha_) :
-        org(org_), img(img_), alpha(alpha_)
-    {
-    }
-
-    /*@{*/
-    cv::Point org;   //!< The bottom-left corner of the image
-    cv::Mat   img;   //!< Image to draw
-    cv::Mat   alpha; //!< Alpha channel for image to draw (same size and number of channels)
-    /*@{*/
-};
-
-/**
- * @brief This structure represents a polygon to draw.
- */
-struct Poly
-{
-    /**
-     * @brief Mosaic constructor
-     *
-     * @param points_ Points to connect
-     * @param color_  The line color
-     * @param thick_  The thickness of line
-     * @param lt_     The Type of the line. See #LineTypes
-     * @param shift_  The number of fractional bits in the point coordinate
-    */
-    Poly(const std::vector<cv::Point>& points_,
-         const cv::Scalar& color_,
-         int thick_ = 1,
-         int lt_ = cv::LINE_8,
-         int shift_ = 0) :
-        points(points_), color(color_), thick(thick_), lt(lt_), shift(shift_)
-    {
-    }
-
-    /*@{*/
-    std::vector<cv::Point> points;  //!< Points to connect
-    cv::Scalar             color;   //!< The line color
-    int                    thick;   //!< The thickness of line
-    int                    lt;      //!< The Type of the line. See #LineTypes
-    int                    shift;   //!< The number of fractional bits in the point coordinate
-    /*@{*/
-};
-
-using Prim  = util::variant
-    < Text
-    , FText
-    , Rect
-    , Circle
-    , Line
-    , Mosaic
-    , Image
-    , Poly
-    >;
-
-using Prims     = std::vector<Prim>;
-//! @} gapi_draw_prims
-
 using GMat2     = std::tuple<cv::GMat,cv::GMat>;
 using GMatDesc2 = std::tuple<cv::GMatDesc,cv::GMatDesc>;
 
-
 //! @addtogroup gapi_draw_api
 //! @{
 /** @brief The function renders on the input image passed drawing primitivies
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render_types.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render_types.hpp
new file mode 100644 (file)
index 0000000..08b14d1
--- /dev/null
@@ -0,0 +1,347 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_RENDER_TYPES_HPP
+#define OPENCV_GAPI_RENDER_TYPES_HPP
+
+#include <string>
+#include <vector>
+
+#include <opencv2/gapi/opencv_includes.hpp>
+#include <opencv2/gapi/util/variant.hpp>
+#include <opencv2/gapi/own/exports.hpp>
+
+namespace cv
+{
+namespace gapi
+{
+namespace wip
+{
+namespace draw
+{
+
+/**
+ * @brief This structure specifies which FreeType font to use by FText primitives.
+ */
+struct freetype_font
+{
+    /*@{*/
+    std::string path; //!< The path to the font file (.ttf)
+    /*@{*/
+};
+
+//! @addtogroup gapi_draw_prims
+//! @{
+/**
+ * @brief This structure represents a text string to draw.
+ *
+ * Parameters match cv::putText().
+ */
+struct Text
+{
+    /**
+     * @brief Text constructor
+     *
+     * @param text_               The text string to be drawn
+     * @param org_                The bottom-left corner of the text string in the image
+     * @param ff_                 The font type, see #HersheyFonts
+     * @param fs_                 The font scale factor that is multiplied by the font-specific base size
+     * @param color_              The text color
+     * @param thick_              The thickness of the lines used to draw a text
+     * @param lt_                 The line type. See #LineTypes
+     * @param bottom_left_origin_ When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
+     */
+    Text(const std::string& text_,
+         const cv::Point& org_,
+         int ff_,
+         double fs_,
+         const cv::Scalar& color_,
+         int thick_ = 1,
+         int lt_ = 8,
+         bool bottom_left_origin_ = false) :
+        text(text_), org(org_), ff(ff_), fs(fs_),
+        color(color_), thick(thick_), lt(lt_), bottom_left_origin(bottom_left_origin_)
+    {
+    }
+
+    Text() = default;
+
+    /*@{*/
+    std::string text;               //!< The text string to be drawn
+    cv::Point   org;                //!< The bottom-left corner of the text string in the image
+    int         ff;                 //!< The font type, see #HersheyFonts
+    double      fs;                 //!< The font scale factor that is multiplied by the font-specific base size
+    cv::Scalar  color;              //!< The text color
+    int         thick;              //!< The thickness of the lines used to draw a text
+    int         lt;                 //!< The line type. See #LineTypes
+    bool        bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
+    /*@{*/
+};
+
+/**
+ * @brief This structure represents a text string to draw using
+ * FreeType renderer.
+ *
+ * If OpenCV is built without FreeType support, this primitive will
+ * fail at the execution stage.
+ */
+struct FText
+{
+    /**
+     * @brief FText constructor
+     *
+     * @param text_ The text string to be drawn
+     * @param org_  The bottom-left corner of the text string in the image
+     * @param fh_   The height of text
+     * @param color_ The text color
+     */
+    FText(const std::wstring& text_,
+          const cv::Point& org_,
+          int fh_,
+          const cv::Scalar& color_) :
+        text(text_), org(org_), fh(fh_), color(color_)
+    {
+    }
+
+    FText() = default;
+
+    /*@{*/
+    std::wstring text;              //!< The text string to be drawn
+    cv::Point    org;               //!< The bottom-left corner of the text string in the image
+    int          fh;                //!< The height of text
+    cv::Scalar   color;             //!< The text color
+    /*@{*/
+};
+
+/**
+ * @brief This structure represents a rectangle to draw.
+ *
+ * Parameters match cv::rectangle().
+ */
+struct Rect
+{
+    /**
+     * @brief Rect constructor
+     *
+     * @param rect_   Coordinates of the rectangle
+     * @param color_  The bottom-left corner of the text string in the image
+     * @param thick_  The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
+     * @param lt_     The type of the line. See #LineTypes
+     * @param shift_  The number of fractional bits in the point coordinates
+     */
+    Rect(const cv::Rect& rect_,
+         const cv::Scalar& color_,
+         int thick_ = 1,
+         int lt_ = 8,
+         int shift_ = 0) :
+        rect(rect_), color(color_), thick(thick_), lt(lt_), shift(shift_)
+    {
+    }
+
+    Rect() = default;
+
+    /*@{*/
+    cv::Rect   rect;  //!< Coordinates of the rectangle
+    cv::Scalar color; //!< The rectangle color or brightness (grayscale image)
+    int        thick; //!< The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
+    int        lt;    //!< The type of the line. See #LineTypes
+    int        shift; //!< The number of fractional bits in the point coordinates
+    /*@{*/
+};
+
+/**
+ * @brief This structure represents a circle to draw.
+ *
+ * Parameters match cv::circle().
+ */
+struct Circle
+{
+    /**
+     * @brief Circle constructor
+     *
+     * @param  center_ The center of the circle
+     * @param  radius_ The radius of the circle
+     * @param  color_  The color of the  circle
+     * @param  thick_  The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
+     * @param  lt_     The Type of the circle boundary. See #LineTypes
+     * @param  shift_  The Number of fractional bits in the coordinates of the center and in the radius value
+     */
+    Circle(const cv::Point& center_,
+           int radius_,
+           const cv::Scalar& color_,
+           int thick_ = 1,
+           int lt_ = 8,
+           int shift_ = 0) :
+        center(center_), radius(radius_), color(color_), thick(thick_), lt(lt_), shift(shift_)
+    {
+    }
+
+    Circle() = default;
+
+    /*@{*/
+    cv::Point  center; //!< The center of the circle
+    int        radius; //!< The radius of the circle
+    cv::Scalar color;  //!< The color of the  circle
+    int        thick;  //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
+    int        lt;     //!< The Type of the circle boundary. See #LineTypes
+    int        shift;  //!< The Number of fractional bits in the coordinates of the center and in the radius value
+    /*@{*/
+};
+
+/**
+ * @brief This structure represents a line to draw.
+ *
+ * Parameters match cv::line().
+ */
+struct Line
+{
+    /**
+     * @brief Line constructor
+     *
+     * @param  pt1_    The first point of the line segment
+     * @param  pt2_    The second point of the line segment
+     * @param  color_  The line color
+     * @param  thick_  The thickness of line
+     * @param  lt_     The Type of the line. See #LineTypes
+     * @param  shift_  The number of fractional bits in the point coordinates
+    */
+    Line(const cv::Point& pt1_,
+         const cv::Point& pt2_,
+         const cv::Scalar& color_,
+         int thick_ = 1,
+         int lt_ = 8,
+         int shift_ = 0) :
+        pt1(pt1_), pt2(pt2_), color(color_), thick(thick_), lt(lt_), shift(shift_)
+    {
+    }
+
+    Line() = default;
+
+    /*@{*/
+    cv::Point  pt1;    //!< The first point of the line segment
+    cv::Point  pt2;    //!< The second point of the line segment
+    cv::Scalar color;  //!< The line color
+    int        thick;  //!< The thickness of line
+    int        lt;     //!< The Type of the line. See #LineTypes
+    int        shift;  //!< The number of fractional bits in the point coordinates
+    /*@{*/
+};
+
+/**
+ * @brief This structure represents a mosaicing operation.
+ *
+ * Mosaicing is a very basic method to obfuscate regions in the image.
+ */
+struct Mosaic
+{
+    /**
+     * @brief Mosaic constructor
+     *
+     * @param mos_    Coordinates of the mosaic
+     * @param cellSz_ Cell size (same for X, Y)
+     * @param decim_  Decimation (0 stands for no decimation)
+    */
+    Mosaic(const cv::Rect& mos_,
+           int cellSz_,
+           int decim_) :
+        mos(mos_), cellSz(cellSz_), decim(decim_)
+    {
+    }
+
+    Mosaic() = default;
+
+    /*@{*/
+    cv::Rect   mos;    //!< Coordinates of the mosaic
+    int        cellSz; //!< Cell size (same for X, Y)
+    int        decim;  //!< Decimation (0 stands for no decimation)
+    /*@{*/
+};
+
+/**
+ * @brief This structure represents an image to draw.
+ *
+ * Image is blended on a frame using the specified mask.
+ */
+struct Image
+{
+    /**
+     * @brief Mosaic constructor
+     *
+     * @param  org_   The bottom-left corner of the image
+     * @param  img_   Image to draw
+     * @param  alpha_ Alpha channel for image to draw (same size and number of channels)
+    */
+    Image(const cv::Point& org_,
+          const cv::Mat& img_,
+          const cv::Mat& alpha_) :
+        org(org_), img(img_), alpha(alpha_)
+    {
+    }
+
+    Image() = default;
+
+    /*@{*/
+    cv::Point org;   //!< The bottom-left corner of the image
+    cv::Mat   img;   //!< Image to draw
+    cv::Mat   alpha; //!< Alpha channel for image to draw (same size and number of channels)
+    /*@{*/
+};
+
+/**
+ * @brief This structure represents a polygon to draw.
+ */
+struct Poly
+{
+    /**
+     * @brief Mosaic constructor
+     *
+     * @param points_ Points to connect
+     * @param color_  The line color
+     * @param thick_  The thickness of line
+     * @param lt_     The Type of the line. See #LineTypes
+     * @param shift_  The number of fractional bits in the point coordinate
+    */
+    Poly(const std::vector<cv::Point>& points_,
+         const cv::Scalar& color_,
+         int thick_ = 1,
+         int lt_ = 8,
+         int shift_ = 0) :
+        points(points_), color(color_), thick(thick_), lt(lt_), shift(shift_)
+    {
+    }
+
+    Poly() = default;
+
+    /*@{*/
+    std::vector<cv::Point> points;  //!< Points to connect
+    cv::Scalar             color;   //!< The line color
+    int                    thick;   //!< The thickness of line
+    int                    lt;      //!< The Type of the line. See #LineTypes
+    int                    shift;   //!< The number of fractional bits in the point coordinate
+    /*@{*/
+};
+
+using Prim  = util::variant
+    < Text
+    , FText
+    , Rect
+    , Circle
+    , Line
+    , Mosaic
+    , Image
+    , Poly
+    >;
+
+using Prims     = std::vector<Prim>;
+//! @} gapi_draw_prims
+
+} // namespace draw
+} // namespace wip
+} // namespace gapi
+} // namespace cv
+
+#endif // OPENCV_GAPI_RENDER_TYPES_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/rmat.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/rmat.hpp
new file mode 100644 (file)
index 0000000..2fbdf03
--- /dev/null
@@ -0,0 +1,124 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_RMAT_HPP
+#define OPENCV_GAPI_RMAT_HPP
+
+#include <opencv2/gapi/gmat.hpp>
+
+namespace cv {
+
+// "Remote Mat", a general class which provides an abstraction layer over the data
+// storage and placement (host, remote device etc) and allows to access this data.
+//
+// The device specific implementation is hidden in the RMat::Adapter class
+//
+// The basic flow is the following:
+// * Backend which is aware of the remote device:
+//   - Implements own AdapterT class which is derived from RMat::Adapter
+//   - Wraps device memory into RMat via make_rmat utility function:
+//         cv::RMat rmat = cv::make_rmat<AdapterT>(args);
+//
+// * End user:
+//   - Writes the code which works with RMats without any knowledge of the remote device:
+//     void func(const cv::RMat& in_rmat, cv::RMat& out_rmat) {
+//         // Fetch input data from the device, get mapped memory for output
+//         cv::RMat::View  in_view =  in_rmat.access(Access::R);
+//         cv::RMat::View out_view = out_rmat.access(Access::W);
+//         performCalculations(in_view, out_view);
+//         // data from out_view is transferred to the device when out_view is destroyed
+//     }
+class RMat
+{
+public:
+    // A lightweight wrapper on image data:
+    // - Doesn't own the memory;
+    // - Doesn't implement copy semantics (it's assumed that a view is created each time
+    // wrapped data is being accessed);
+    // - Has an optional callback which is called when the view is destroyed.
+    class View
+    {
+    public:
+        using DestroyCallback = std::function<void()>;
+
+        View() = default;
+        View(const GMatDesc& desc, uchar* data, size_t step = 0u, DestroyCallback&& cb = nullptr)
+            : m_desc(desc), m_data(data), m_step(step == 0u ? elemSize()*cols() : step), m_cb(cb)
+        {}
+
+        View(const View&) = delete;
+        View(View&&) = default;
+        View& operator=(const View&) = delete;
+        View& operator=(View&&) = default;
+        ~View() { if (m_cb) m_cb(); }
+
+        cv::Size size() const { return m_desc.size; }
+        const std::vector<int>& dims() const { return m_desc.dims; }
+        int cols() const { return m_desc.size.width; }
+        int rows() const { return m_desc.size.height; }
+        int type() const { return CV_MAKE_TYPE(depth(), chan()); }
+        int depth() const { return m_desc.depth; }
+        int chan() const { return m_desc.chan; }
+        size_t elemSize() const { return CV_ELEM_SIZE(type()); }
+
+        template<typename T = uchar> T* ptr(int y = 0, int x = 0) {
+            return reinterpret_cast<T*>(m_data + m_step*y + x*CV_ELEM_SIZE(type()));
+        }
+        template<typename T = uchar> const T* ptr(int y = 0, int x = 0) const {
+            return reinterpret_cast<const T*>(m_data + m_step*y + x*CV_ELEM_SIZE(type()));
+        }
+        size_t step() const { return m_step; }
+
+    private:
+        GMatDesc m_desc;
+        uchar* m_data = nullptr;
+        size_t m_step = 0u;
+        DestroyCallback m_cb = nullptr;
+    };
+
+    enum class Access { R, W };
+    class Adapter
+    {
+    public:
+        virtual ~Adapter() = default;
+        virtual GMatDesc desc() const = 0;
+        // Implementation is responsible for setting the appropriate callback to
+        // the view when accessed for writing, to ensure that the data from the view
+        // is transferred to the device when the view is destroyed
+        virtual View access(Access) const = 0;
+    };
+    using AdapterP = std::shared_ptr<Adapter>;
+
+    RMat() = default;
+    RMat(AdapterP&& a) : m_adapter(std::move(a)) {}
+    GMatDesc desc() const { return m_adapter->desc(); }
+
+    // Note: When accessed for write there is no guarantee that returned view
+    // will contain actual snapshot of the mapped device memory
+    // (no guarantee that fetch from a device is performed). The only
+    // guaranty is that when the view is destroyed, its data will be
+    // transferred to the device
+    View access(Access a) const { return m_adapter->access(a); }
+
+    // Cast underlying RMat adapter to the particular adapter type,
+    // return nullptr if underlying type is different
+    template<typename T> T* get() const
+    {
+        static_assert(std::is_base_of<Adapter, T>::value, "T is not derived from Adapter!");
+        GAPI_Assert(m_adapter != nullptr);
+        return dynamic_cast<T*>(m_adapter.get());
+    }
+
+private:
+    AdapterP m_adapter = nullptr;
+};
+
+template<typename T, typename... Ts>
+RMat make_rmat(Ts&&... args) { return { std::make_shared<T>(std::forward<Ts>(args)...) }; }
+
+} //namespace cv
+
+#endif /* OPENCV_GAPI_RMAT_HPP */
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n.hpp
new file mode 100644 (file)
index 0000000..c669b73
--- /dev/null
@@ -0,0 +1,58 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_S11N_HPP
+#define OPENCV_GAPI_S11N_HPP
+
+#include <vector>
+#include <opencv2/gapi/gcomputation.hpp>
+
+namespace cv {
+namespace gapi {
+
+namespace detail {
+    GAPI_EXPORTS cv::GComputation getGraph(const std::vector<char> &p);
+} // namespace detail
+
+namespace detail {
+    GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector<char> &p);
+} // namespace detail
+
+namespace detail {
+    GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector<char> &p);
+} // namespace detail
+
+GAPI_EXPORTS std::vector<char> serialize(const cv::GComputation &c);
+//namespace{
+
+template<typename T> static inline
+T deserialize(const std::vector<char> &p);
+
+//} //ananymous namespace
+
+GAPI_EXPORTS std::vector<char> serialize(const cv::GMetaArgs&);
+GAPI_EXPORTS std::vector<char> serialize(const cv::GRunArgs&);
+
+template<> inline
+cv::GComputation deserialize(const std::vector<char> &p) {
+    return detail::getGraph(p);
+}
+
+template<> inline
+cv::GMetaArgs deserialize(const std::vector<char> &p) {
+    return detail::getMetaArgs(p);
+}
+
+template<> inline
+cv::GRunArgs deserialize(const std::vector<char> &p) {
+    return detail::getRunArgs(p);
+}
+
+
+} // namespace gapi
+} // namespace cv
+
+#endif // OPENCV_GAPI_S11N_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/type_traits.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/type_traits.hpp
new file mode 100644 (file)
index 0000000..637f184
--- /dev/null
@@ -0,0 +1,31 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_UTIL_TYPE_TRAITS_HPP
+#define OPENCV_GAPI_UTIL_TYPE_TRAITS_HPP
+
+#include <type_traits>
+
+namespace cv
+{
+namespace util
+{
+    //these are C++14 parts of type_traits :
+    template< bool B, class T = void >
+    using enable_if_t = typename std::enable_if<B,T>::type;
+
+    template<typename T>
+    using decay_t = typename std::decay<T>::type;
+
+    //this is not part of C++14 but still, of pretty common usage
+    template<class T, class U, class V = void>
+    using are_different_t = enable_if_t< !std::is_same<decay_t<T>, decay_t<U>>::value, V>;
+
+} // namespace cv
+} // namespace util
+
+#endif // OPENCV_GAPI_UTIL_TYPE_TRAITS_HPP
index ee0590b..71a06d2 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <opencv2/gapi/util/throw.hpp>
 #include <opencv2/gapi/util/util.hpp> // max_of_t
+#include <opencv2/gapi/util/type_traits.hpp>
 
 // A poor man's `variant` implementation, incompletely modeled against C++17 spec.
 namespace cv
@@ -35,12 +36,6 @@ namespace util
             static_assert(std::is_same<Target, First>::value, "Type not found");
             static const constexpr std::size_t value = I;
         };
-
-
-        template<class T, class U, class V> using are_different =
-            std::enable_if<!std::is_same<typename std::decay<T>::type,
-                                         typename std::decay<U>::type>::value,
-                           V>;
     }
 
     template<typename Target, typename... Types>
@@ -79,18 +74,20 @@ namespace util
             }
         };
 
-        template<typename T> struct vctr_h {
-            static void help(Memory memory, const void* pval) {
-                new (memory) T(*reinterpret_cast<const T*>(pval));
-            }
-        };
-
         template<typename T> struct mctr_h {
             static void help(Memory memory, void *pval) {
                 new (memory) T(std::move(*reinterpret_cast<T*>(pval)));
             }
         };
 
+        //FIXME: unify with cctr_h and mctr_h
+        template<typename T> struct cnvrt_ctor_h {
+            static void help(Memory memory, void* from) {
+                using util::decay_t;
+                new (memory) decay_t<T>(std::forward<T>(*reinterpret_cast<decay_t<T>*>(from)));
+            }
+        };
+
         template<typename T> struct copy_h {
             static void help(Memory to, const Memory from) {
                 *reinterpret_cast<T*>(to) = *reinterpret_cast<const T*>(from);
@@ -98,8 +95,16 @@ namespace util
         };
 
         template<typename T> struct move_h {
-            static void help(Memory to, const Memory from) {
-                *reinterpret_cast<T*>(to) = std::move(*reinterpret_cast<const T*>(from));
+            static void help(Memory to, Memory from) {
+                *reinterpret_cast<T*>(to) = std::move(*reinterpret_cast<T*>(from));
+            }
+        };
+
+        //FIXME: unify with copy_h and move_h
+        template<typename T> struct cnvrt_assign_h {
+            static void help(Memory to, void* from) {
+                using util::decay_t;
+                *reinterpret_cast<decay_t<T>*>(to) = std::forward<T>(*reinterpret_cast<decay_t<T>*>(from));
             }
         };
 
@@ -125,28 +130,50 @@ namespace util
         };
 
         typedef void (*CCtr) (Memory, const Memory);  // Copy c-tor (variant)
-        typedef void (*VCtr) (Memory, const void*);   // Copy c-tor (value)
         typedef void (*MCtr) (Memory, void*);         // Generic move c-tor
         typedef void (*Copy) (Memory, const Memory);  // Copy assignment
-        typedef void (*Move) (Memory, const Memory);  // Move assignment
+        typedef void (*Move) (Memory, Memory);        // Move assignment
+
         typedef void (*Swap) (Memory, Memory);        // Swap
         typedef void (*Dtor) (Memory);                // Destructor
 
+        using  cnvrt_assgn_t   = void (*) (Memory, void*);  // Converting assignment (via std::forward)
+        using  cnvrt_ctor_t    = void (*) (Memory, void*);  // Converting constructor (via std::forward)
+
         typedef bool (*Equal)(const Memory, const Memory); // Equality test (external)
 
         static constexpr std::array<CCtr, sizeof...(Ts)> cctrs(){ return {{(&cctr_h<Ts>::help)...}};}
-        static constexpr std::array<VCtr, sizeof...(Ts)> vctrs(){ return {{(&vctr_h<Ts>::help)...}};}
         static constexpr std::array<MCtr, sizeof...(Ts)> mctrs(){ return {{(&mctr_h<Ts>::help)...}};}
         static constexpr std::array<Copy, sizeof...(Ts)> cpyrs(){ return {{(&copy_h<Ts>::help)...}};}
         static constexpr std::array<Move, sizeof...(Ts)> mvers(){ return {{(&move_h<Ts>::help)...}};}
         static constexpr std::array<Swap, sizeof...(Ts)> swprs(){ return {{(&swap_h<Ts>::help)...}};}
         static constexpr std::array<Dtor, sizeof...(Ts)> dtors(){ return {{(&dtor_h<Ts>::help)...}};}
 
+        template<bool cond, typename T>
+        struct conditional_ref : std::conditional<cond, typename std::remove_reference<T>::type&, typename std::remove_reference<T>::type > {};
+
+        template<bool cond, typename T>
+        using conditional_ref_t = typename conditional_ref<cond, T>::type;
+
+
+        template<bool is_lvalue_arg>
+        static constexpr std::array<cnvrt_assgn_t, sizeof...(Ts)> cnvrt_assgnrs(){
+            return {{(&cnvrt_assign_h<conditional_ref_t<is_lvalue_arg,Ts>>::help)...}};
+        }
+
+        template<bool is_lvalue_arg>
+        static constexpr std::array<cnvrt_ctor_t, sizeof...(Ts)> cnvrt_ctors(){
+            return {{(&cnvrt_ctor_h<conditional_ref_t<is_lvalue_arg,Ts>>::help)...}};
+        }
+
         std::size_t m_index = 0;
 
     protected:
         template<typename T, typename... Us> friend T& get(variant<Us...> &v);
         template<typename T, typename... Us> friend const T& get(const variant<Us...> &v);
+        template<typename T, typename... Us> friend T* get_if(variant<Us...> *v) noexcept;
+        template<typename T, typename... Us> friend const T* get_if(const variant<Us...> *v) noexcept;
+
         template<typename... Us> friend bool operator==(const variant<Us...> &lhs,
                                                         const variant<Us...> &rhs);
         Memory memory;
@@ -156,11 +183,14 @@ namespace util
         variant() noexcept;
         variant(const variant& other);
         variant(variant&& other) noexcept;
-        template<typename T> explicit variant(const T& t);
-        // are_different is a SFINAE trick to avoid variant(T &&t) with T=variant
+        // are_different_t is a SFINAE trick to avoid variant(T &&t) with T=variant
         // for some reason, this version is called instead of variant(variant&& o) when
-        // variant is used in STL containers (examples: vector assignment)
-        template<typename T> explicit variant(T&& t, typename detail::are_different<variant, T, int>::type = 0);
+        // variant is used in STL containers (examples: vector assignment).
+        template<
+            typename T,
+            typename = util::are_different_t<variant, T>
+        >
+        explicit variant(T&& t);
         // template<class T, class... Args> explicit variant(Args&&... args);
         // FIXME: other constructors
 
@@ -172,9 +202,11 @@ namespace util
         variant& operator=(variant &&rhs) noexcept;
 
         // SFINAE trick to avoid operator=(T&&) with T=variant<>, see comment above
-        template<class T>
-        typename detail::are_different<variant, T, variant&>
-        ::type operator=(T&& t) noexcept;
+        template<
+            typename T,
+            typename = util::are_different_t<variant, T>
+        >
+        variant& operator=(T&& t) noexcept;
 
         // Observers
         std::size_t index() const noexcept;
@@ -189,6 +221,11 @@ namespace util
     };
 
     // FIMXE: visit
+    template<typename T, typename... Types>
+    T* get_if(util::variant<Types...>* v) noexcept;
+
+    template<typename T, typename... Types>
+    const T* get_if(const util::variant<Types...>* v) noexcept;
 
     template<typename T, typename... Types>
     T& get(util::variant<Types...> &v);
@@ -224,19 +261,12 @@ namespace util
     }
 
     template<typename... Ts>
-    template<class T>
-    variant<Ts...>::variant(const T& t)
-        : m_index(util::type_list_index<T, Ts...>::value)
+    template<class T, typename>
+    variant<Ts...>::variant(T&& t)
+        : m_index(util::type_list_index<util::decay_t<T>, Ts...>::value)
     {
-        (vctrs()[m_index])(memory, &t);
-    }
-
-    template<typename... Ts>
-    template<class T>
-    variant<Ts...>::variant(T&& t, typename detail::are_different<variant, T, int>::type)
-        : m_index(util::type_list_index<typename std::remove_reference<T>::type, Ts...>::value)
-    {
-        (mctrs()[m_index])(memory, &t);
+        const constexpr bool is_lvalue_arg =  std::is_lvalue_reference<T>::value;
+        (cnvrt_ctors<is_lvalue_arg>()[m_index])(memory, const_cast<util::decay_t<T> *>(&t));
     }
 
     template<typename... Ts>
@@ -278,20 +308,28 @@ namespace util
     }
 
     template<typename... Ts>
-    template<class T> typename detail::are_different<variant<Ts...>, T, variant<Ts...>&>
-    ::type variant<Ts...>::operator=(T&& t) noexcept
+    template<typename T, typename>
+    variant<Ts...>& variant<Ts...>::operator=(T&& t) noexcept
     {
-        using decayed_t = typename std::decay<T>::type;
+        using decayed_t = util::decay_t<T>;
         // FIXME: No version with implicit type conversion available!
-        static const constexpr std::size_t t_index =
+        const constexpr std::size_t t_index =
             util::type_list_index<decayed_t, Ts...>::value;
 
-        if (t_index == m_index)
+        const constexpr bool is_lvalue_arg =  std::is_lvalue_reference<T>::value;
+
+        if (t_index != m_index)
         {
-            util::get<decayed_t>(*this) = std::move(t);
-            return *this;
+            (dtors()[m_index])(memory);
+            (cnvrt_ctors<is_lvalue_arg>()[t_index])(memory, &t);
+            m_index = t_index;
         }
-        else return (*this = variant(std::move(t)));
+        else
+        {
+            (cnvrt_assgnrs<is_lvalue_arg>()[m_index])(memory, &t);
+        }
+        return *this;
+
     }
 
     template<typename... Ts>
@@ -323,27 +361,43 @@ namespace util
     }
 
     template<typename T, typename... Types>
-    T& get(util::variant<Types...> &v)
+    T* get_if(util::variant<Types...>* v) noexcept
     {
         const constexpr std::size_t t_index =
             util::type_list_index<T, Types...>::value;
 
-        if (v.index() == t_index)
-            return *(T*)(&v.memory);  // workaround for ICC 2019
+        if (v && v->index() == t_index)
+            return (T*)(&v->memory);  // workaround for ICC 2019
             // original code: return reinterpret_cast<T&>(v.memory);
-        else
-            throw_error(bad_variant_access());
+        return nullptr;
     }
 
     template<typename T, typename... Types>
-    const T& get(const util::variant<Types...> &v)
+    const T* get_if(const util::variant<Types...>* v) noexcept
     {
         const constexpr std::size_t t_index =
             util::type_list_index<T, Types...>::value;
 
-        if (v.index() == t_index)
-            return *(const T*)(&v.memory);  // workaround for ICC 2019
+        if (v && v->index() == t_index)
+            return (const T*)(&v->memory);  // workaround for ICC 2019
             // original code: return reinterpret_cast<const T&>(v.memory);
+        return nullptr;
+    }
+
+    template<typename T, typename... Types>
+    T& get(util::variant<Types...> &v)
+    {
+        if (auto* p = get_if<T>(&v))
+            return *p;
+        else
+            throw_error(bad_variant_access());
+    }
+
+    template<typename T, typename... Types>
+    const T& get(const util::variant<Types...> &v)
+    {
+        if (auto* p = get_if<T>(&v))
+            return *p;
         else
             throw_error(bad_variant_access());
     }
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/video.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/video.hpp
new file mode 100644 (file)
index 0000000..7f90134
--- /dev/null
@@ -0,0 +1,176 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_VIDEO_HPP
+#define OPENCV_GAPI_VIDEO_HPP
+
+#include <utility> // std::tuple
+
+#include <opencv2/gapi/gkernel.hpp>
+
+
+/** \defgroup gapi_video G-API Video processing functionality
+ */
+
+namespace cv { namespace gapi {
+namespace  video
+{
+using GBuildPyrOutput  = std::tuple<GArray<GMat>, GScalar>;
+
+using GOptFlowLKOutput = std::tuple<cv::GArray<cv::Point2f>,
+                                    cv::GArray<uchar>,
+                                    cv::GArray<float>>;
+
+G_TYPED_KERNEL(GBuildOptFlowPyramid, <GBuildPyrOutput(GMat,Size,GScalar,bool,int,int,bool)>,
+               "org.opencv.video.buildOpticalFlowPyramid")
+{
+    static std::tuple<GArrayDesc,GScalarDesc>
+            outMeta(GMatDesc,const Size&,GScalarDesc,bool,int,int,bool)
+    {
+        return std::make_tuple(empty_array_desc(), empty_scalar_desc());
+    }
+};
+
+G_TYPED_KERNEL(GCalcOptFlowLK,
+               <GOptFlowLKOutput(GMat,GMat,cv::GArray<cv::Point2f>,cv::GArray<cv::Point2f>,Size,
+                                 GScalar,TermCriteria,int,double)>,
+               "org.opencv.video.calcOpticalFlowPyrLK")
+{
+    static std::tuple<GArrayDesc,GArrayDesc,GArrayDesc> outMeta(GMatDesc,GMatDesc,GArrayDesc,
+                                                                GArrayDesc,const Size&,GScalarDesc,
+                                                                const TermCriteria&,int,double)
+    {
+        return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc());
+    }
+
+};
+
+G_TYPED_KERNEL(GCalcOptFlowLKForPyr,
+               <GOptFlowLKOutput(cv::GArray<cv::GMat>,cv::GArray<cv::GMat>,
+                                 cv::GArray<cv::Point2f>,cv::GArray<cv::Point2f>,Size,GScalar,
+                                 TermCriteria,int,double)>,
+               "org.opencv.video.calcOpticalFlowPyrLKForPyr")
+{
+    static std::tuple<GArrayDesc,GArrayDesc,GArrayDesc> outMeta(GArrayDesc,GArrayDesc,
+                                                                GArrayDesc,GArrayDesc,
+                                                                const Size&,GScalarDesc,
+                                                                const TermCriteria&,int,double)
+    {
+        return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc());
+    }
+};
+} //namespace video
+
+//! @addtogroup gapi_video
+//! @{
+/** @brief Constructs the image pyramid which can be passed to calcOpticalFlowPyrLK.
+
+@note Function textual ID is "org.opencv.video.buildOpticalFlowPyramid"
+
+@param img                8-bit input image.
+@param winSize            window size of optical flow algorithm. Must be not less than winSize
+                          argument of calcOpticalFlowPyrLK. It is needed to calculate required
+                          padding for pyramid levels.
+@param maxLevel           0-based maximal pyramid level number.
+@param withDerivatives    set to precompute gradients for the every pyramid level. If pyramid is
+                          constructed without the gradients then calcOpticalFlowPyrLK will calculate
+                          them internally.
+@param pyrBorder          the border mode for pyramid layers.
+@param derivBorder        the border mode for gradients.
+@param tryReuseInputImage put ROI of input image into the pyramid if possible. You can pass false
+                          to force data copying.
+
+@return output pyramid.
+@return number of levels in constructed pyramid. Can be less than maxLevel.
+ */
+GAPI_EXPORTS std::tuple<GArray<GMat>, GScalar>
+buildOpticalFlowPyramid(const GMat     &img,
+                        const Size     &winSize,
+                        const GScalar  &maxLevel,
+                              bool      withDerivatives    = true,
+                              int       pyrBorder          = BORDER_REFLECT_101,
+                              int       derivBorder        = BORDER_CONSTANT,
+                              bool      tryReuseInputImage = true);
+
+/** @brief Calculates an optical flow for a sparse feature set using the iterative Lucas-Kanade
+method with pyramids.
+
+See @cite Bouguet00 .
+
+@note Function textual ID is "org.opencv.video.calcOpticalFlowPyrLK"
+
+@param prevImg first 8-bit input image (GMat) or pyramid (GArray<GMat>) constructed by
+buildOpticalFlowPyramid.
+@param nextImg second input image (GMat) or pyramid (GArray<GMat>) of the same size and the same
+type as prevImg.
+@param prevPts GArray of 2D points for which the flow needs to be found; point coordinates must be
+single-precision floating-point numbers.
+@param predPts GArray of 2D points initial for the flow search; make sense only when
+OPTFLOW_USE_INITIAL_FLOW flag is passed; in that case the vector must have the same size as in
+the input.
+@param winSize size of the search window at each pyramid level.
+@param maxLevel 0-based maximal pyramid level number; if set to 0, pyramids are not used (single
+level), if set to 1, two levels are used, and so on; if pyramids are passed to input then
+algorithm will use as many levels as pyramids have but no more than maxLevel.
+@param criteria parameter, specifying the termination criteria of the iterative search algorithm
+(after the specified maximum number of iterations criteria.maxCount or when the search window
+moves by less than criteria.epsilon).
+@param flags operation flags:
+ -   **OPTFLOW_USE_INITIAL_FLOW** uses initial estimations, stored in nextPts; if the flag is
+     not set, then prevPts is copied to nextPts and is considered the initial estimate.
+ -   **OPTFLOW_LK_GET_MIN_EIGENVALS** use minimum eigen values as an error measure (see
+     minEigThreshold description); if the flag is not set, then L1 distance between patches
+     around the original and a moved point, divided by number of pixels in a window, is used as a
+     error measure.
+@param minEigThresh the algorithm calculates the minimum eigen value of a 2x2 normal matrix of
+optical flow equations (this matrix is called a spatial gradient matrix in @cite Bouguet00), divided
+by number of pixels in a window; if this value is less than minEigThreshold, then a corresponding
+feature is filtered out and its flow is not processed, so it allows to remove bad points and get a
+performance boost.
+
+@return GArray of 2D points (with single-precision floating-point coordinates)
+containing the calculated new positions of input features in the second image.
+@return status GArray (of unsigned chars); each element of the vector is set to 1 if
+the flow for the corresponding features has been found, otherwise, it is set to 0.
+@return GArray of errors (doubles); each element of the vector is set to an error for the
+corresponding feature, type of the error measure can be set in flags parameter; if the flow wasn't
+found then the error is not defined (use the status parameter to find such cases).
+ */
+GAPI_EXPORTS std::tuple<GArray<Point2f>, GArray<uchar>, GArray<float>>
+calcOpticalFlowPyrLK(const GMat            &prevImg,
+                     const GMat            &nextImg,
+                     const GArray<Point2f> &prevPts,
+                     const GArray<Point2f> &predPts,
+                     const Size            &winSize      = Size(21, 21),
+                     const GScalar         &maxLevel     = 3,
+                     const TermCriteria    &criteria     = TermCriteria(TermCriteria::COUNT |
+                                                                        TermCriteria::EPS,
+                                                                        30, 0.01),
+                           int              flags        = 0,
+                           double           minEigThresh = 1e-4);
+
+/**
+@overload
+@note Function textual ID is "org.opencv.video.calcOpticalFlowPyrLKForPyr"
+*/
+GAPI_EXPORTS std::tuple<GArray<Point2f>, GArray<uchar>, GArray<float>>
+calcOpticalFlowPyrLK(const GArray<GMat>    &prevPyr,
+                     const GArray<GMat>    &nextPyr,
+                     const GArray<Point2f> &prevPts,
+                     const GArray<Point2f> &predPts,
+                     const Size            &winSize      = Size(21, 21),
+                     const GScalar         &maxLevel     = 3,
+                     const TermCriteria    &criteria     = TermCriteria(TermCriteria::COUNT |
+                                                                        TermCriteria::EPS,
+                                                                        30, 0.01),
+                           int              flags        = 0,
+                           double           minEigThresh = 1e-4);
+
+//! @} gapi_video
+} //namespace gapi
+} //namespace cv
+
+#endif // OPENCV_GAPI_VIDEO_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/misc/python/pyopencv_gapi.hpp b/inference-engine/thirdparty/fluid/modules/gapi/misc/python/pyopencv_gapi.hpp
new file mode 100644 (file)
index 0000000..7ef4cac
--- /dev/null
@@ -0,0 +1,45 @@
+using gapi_GKernelPackage = cv::gapi::GKernelPackage;
+
+template<>
+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 <typename T>
+static PyObject* extract_proto_args(PyObject* py_args, PyObject* kw)
+{
+    using namespace cv;
+
+    GProtoArgs args;
+    Py_ssize_t size = PyTuple_Size(py_args);
+    for (int i = 0; i < size; ++i) {
+        PyObject* item = PyTuple_GetItem(py_args, i);
+        if (PyObject_TypeCheck(item, reinterpret_cast<PyTypeObject*>(pyopencv_GScalar_TypePtr))) {
+            args.emplace_back(reinterpret_cast<pyopencv_GScalar_t*>(item)->v);
+        } else if (PyObject_TypeCheck(item, reinterpret_cast<PyTypeObject*>(pyopencv_GMat_TypePtr))) {
+            args.emplace_back(reinterpret_cast<pyopencv_GMat_t*>(item)->v);
+        } else {
+            PyErr_SetString(PyExc_TypeError, "cv.GIn() supports only cv.GMat and cv.GScalar");
+            return NULL;
+        }
+    }
+
+    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);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/misc/python/shadow_gapi.hpp b/inference-engine/thirdparty/fluid/modules/gapi/misc/python/shadow_gapi.hpp
new file mode 100644 (file)
index 0000000..2150b86
--- /dev/null
@@ -0,0 +1,13 @@
+#error This is a shadow header file, which is not intended for processing by any compiler. \
+       Only bindings parser should handle this file.
+
+namespace cv
+{
+   GAPI_EXPORTS_W GCompileArgs compile_args(gapi::GKernelPackage pkg);
+   class GAPI_EXPORTS_W_SIMPLE GProtoArg { };
+   class GAPI_EXPORTS_W_SIMPLE GProtoInputArgs { };
+   class GAPI_EXPORTS_W_SIMPLE GProtoOutputArgs { };
+
+   using GProtoInputArgs  = GIOProtoArgs<In_Tag>;
+   using GProtoOutputArgs = GIOProtoArgs<Out_Tag>;
+} // namespace cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/misc/python/test/test_gapi_core.py b/inference-engine/thirdparty/fluid/modules/gapi/misc/python/test/test_gapi_core.py
new file mode 100644 (file)
index 0000000..7720dbc
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+
+import numpy as np
+import cv2 as cv
+
+from tests_common import NewOpenCVTests
+
+
+# Plaidml is an optional backend
+pkgs = [
+         cv.gapi.core.ocl.kernels(),
+         cv.gapi.core.cpu.kernels(),
+         cv.gapi.core.fluid.kernels()
+         # cv.gapi.core.plaidml.kernels()
+       ]
+
+
+class gapi_core_test(NewOpenCVTests):
+
+    def test_add(self):
+        # TODO: Extend to use any type and size here
+        sz = (1280, 720)
+        in1 = np.random.randint(0, 100, sz).astype(np.uint8)
+        in2 = np.random.randint(0, 100, sz).astype(np.uint8)
+
+        # OpenCV
+        expected = in1 + in2
+
+        # G-API
+        g_in1 = cv.GMat()
+        g_in2 = cv.GMat()
+        g_out = cv.gapi.add(g_in1, g_in2)
+        comp = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
+
+        for pkg in pkgs:
+            actual = comp.apply(in1, in2, args=cv.compile_args(pkg))
+            # Comparison
+            self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
+
+
+    def test_mean(self):
+        sz = (1280, 720, 3)
+        in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
+
+        # OpenCV
+        expected = cv.mean(in_mat)
+
+        # G-API
+        g_in = cv.GMat()
+        g_out = cv.gapi.mean(g_in)
+        comp = cv.GComputation(g_in, g_out)
+
+        for pkg in pkgs:
+            actual = comp.apply(in_mat, args=cv.compile_args(pkg))
+            # Comparison
+            self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
+
+
+if __name__ == '__main__':
+    NewOpenCVTests.bootstrap()
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/misc/python/test/test_gapi_sample_pipelines.py b/inference-engine/thirdparty/fluid/modules/gapi/misc/python/test/test_gapi_sample_pipelines.py
new file mode 100644 (file)
index 0000000..1f672f4
--- /dev/null
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+
+import numpy as np
+import cv2 as cv
+
+from tests_common import NewOpenCVTests
+
+
+# Plaidml is an optional backend
+pkgs = [
+         cv.gapi.core.ocl.kernels(),
+         cv.gapi.core.cpu.kernels(),
+         cv.gapi.core.fluid.kernels()
+         # cv.gapi.core.plaidml.kernels()
+       ]
+
+
+class gapi_sample_pipelines(NewOpenCVTests):
+
+    # NB: This test check multiple outputs for operation
+    def test_mean_over_r(self):
+        sz = (100, 100, 3)
+        in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
+
+        # # OpenCV
+        _, _, r_ch = cv.split(in_mat)
+        expected = cv.mean(r_ch)
+
+        # G-API
+        g_in = cv.GMat()
+        b, g, r = cv.gapi.split3(g_in)
+        g_out = cv.gapi.mean(r)
+        comp = cv.GComputation(g_in, g_out)
+
+        for pkg in pkgs:
+            actual = comp.apply(in_mat, args=cv.compile_args(pkg))
+            # Comparison
+            self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
+
+
+if __name__ == '__main__':
+    NewOpenCVTests.bootstrap()
index ab6555a..ac7182c 100644 (file)
@@ -10,6 +10,7 @@
 
 
 #include "../../test/common/gapi_tests_common.hpp"
+#include "../../test/common/gapi_parsers_tests_common.hpp"
 #include <opencv2/gapi/core.hpp>
 
 namespace opencv_test
@@ -42,8 +43,8 @@ namespace opencv_test
     class Polar2CartPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
     class Cart2PolarPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
     class CmpPerfTest : public TestPerfParams<tuple<CmpTypes, cv::Size, MatType, cv::GCompileArgs>> {};
-    class CmpWithScalarPerfTest : public TestPerfParams<tuple<CmpTypes, cv::Size, MatType, cv::GCompileArgs>> {};
-    class BitwisePerfTest : public TestPerfParams<tuple<bitwiseOp, cv::Size, MatType, cv::GCompileArgs>> {};
+    class CmpWithScalarPerfTest : public TestPerfParams<tuple<compare_f, CmpTypes, cv::Size, MatType, cv::GCompileArgs>> {};
+    class BitwisePerfTest : public TestPerfParams<tuple<bitwiseOp, bool, cv::Size, MatType, cv::GCompileArgs>> {};
     class BitwiseNotPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
     class SelectPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
     class MinPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
@@ -70,8 +71,13 @@ namespace opencv_test
     class ConcatVertPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
     class ConcatVertVecPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
     class LUTPerfTest : public TestPerfParams<tuple<MatType, MatType, cv::Size, cv::GCompileArgs>> {};
-    class ConvertToPerfTest : public TestPerfParams<tuple<MatType, int, cv::Size, cv::GCompileArgs>> {};
+    class ConvertToPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, double, double, cv::GCompileArgs>> {};
     class ResizePerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, cv::Size, cv::GCompileArgs>> {};
     class ResizeFxFyPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, double, double, cv::GCompileArgs>> {};
+    class ParseSSDBLPerfTest : public TestPerfParams<tuple<cv::Size, float, int, cv::GCompileArgs>>, public ParserSSDTest {};
+    class ParseSSDPerfTest   : public TestPerfParams<tuple<cv::Size, float, bool, bool, cv::GCompileArgs>>, public ParserSSDTest {};
+    class ParseYoloPerfTest  : public TestPerfParams<tuple<cv::Size, float, float, int, cv::GCompileArgs>>, public ParserYoloTest {};
+    class SizePerfTest       : public TestPerfParams<tuple<MatType, cv::Size, cv::GCompileArgs>> {};
+    class SizeRPerfTest      : public TestPerfParams<tuple<cv::Size, cv::GCompileArgs>> {};
 }
 #endif // OPENCV_GAPI_CORE_PERF_TESTS_HPP
index 6ec27ed..9ad1d04 100644 (file)
@@ -402,10 +402,6 @@ PERF_TEST_P_(DivRCPerfTest, TestPerformance)
     // FIXIT Unstable input data for divide
     initMatsRandU(type, sz, dtype, false);
 
-    // FIXIT Unstable input data for divide, don't process zeros
-    sc += Scalar::all(1);
-    in_mat1 += 1;
-
     // OpenCV code ///////////////////////////////////////////////////////////
     cv::divide(sc, in_mat1, out_mat_ocv, 1.0, dtype);
 
@@ -426,7 +422,7 @@ PERF_TEST_P_(DivRCPerfTest, TestPerformance)
     }
 
     // Comparison ////////////////////////////////////////////////////////////
-    EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+    // FIXIT unrealiable check: EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
     EXPECT_EQ(out_mat_gapi.size(), sz);
 
     SANITY_CHECK_NOTHING();
@@ -630,10 +626,12 @@ PERF_TEST_P_(CmpPerfTest, TestPerformance)
 
 PERF_TEST_P_(CmpWithScalarPerfTest, TestPerformance)
 {
-    CmpTypes opType = get<0>(GetParam());
-    cv::Size sz = get<1>(GetParam());
-    MatType type = get<2>(GetParam());
-    cv::GCompileArgs compile_args = get<3>(GetParam());
+    MatType type    = -1;
+    CmpTypes opType = CMP_EQ;
+    cv::Size sz;
+    compare_f cmpF;
+    cv::GCompileArgs compile_args;
+    std::tie(cmpF, opType, sz, type, compile_args) = GetParam();
 
     initMatsRandU(type, sz, CV_8U, false);
 
@@ -666,8 +664,8 @@ PERF_TEST_P_(CmpWithScalarPerfTest, TestPerformance)
     }
 
     // Comparison ////////////////////////////////////////////////////////////
-    EXPECT_EQ(0, cvtest::norm(out_mat_gapi, out_mat_ocv, NORM_INF));
     EXPECT_EQ(out_mat_gapi.size(), sz);
+    EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
 
     SANITY_CHECK_NOTHING();
 }
@@ -676,50 +674,76 @@ PERF_TEST_P_(CmpWithScalarPerfTest, TestPerformance)
 
 PERF_TEST_P_(BitwisePerfTest, TestPerformance)
 {
-    bitwiseOp opType = get<0>(GetParam());
-    cv::Size sz = get<1>(GetParam());
-    MatType type = get<2>(GetParam());
-    cv::GCompileArgs compile_args = get<3>(GetParam());
+    MatType   type           = -1;
+    bitwiseOp opType         = AND;
+    bool      testWithScalar = false;
+    cv::Size sz;
+    cv::GCompileArgs compile_args;
+
+    std::tie(opType, testWithScalar, sz, type, compile_args) = GetParam();
 
     initMatsRandU(type, sz, type, false);
 
     // G-API code & corresponding OpenCV code ////////////////////////////////
     cv::GMat in1, in2, out;
-    switch (opType)
-    {
-    case AND:
-    {
-        out = cv::gapi::bitwise_and(in1, in2);
-        cv::bitwise_and(in_mat1, in_mat2, out_mat_ocv);
-        break;
-    }
-    case OR:
+    if( testWithScalar )
     {
-        out = cv::gapi::bitwise_or(in1, in2);
-        cv::bitwise_or(in_mat1, in_mat2, out_mat_ocv);
-        break;
+        cv::GScalar sc1;
+        switch (opType)
+        {
+        case AND:
+            out = cv::gapi::bitwise_and(in1, sc1);
+            cv::bitwise_and(in_mat1, sc, out_mat_ocv);
+            break;
+        case OR:
+            out = cv::gapi::bitwise_or(in1, sc1);
+            cv::bitwise_or(in_mat1, sc, out_mat_ocv);
+            break;
+        case XOR:
+            out = cv::gapi::bitwise_xor(in1, sc1);
+            cv::bitwise_xor(in_mat1, sc, out_mat_ocv);
+            break;
+        default:
+            FAIL() << "no such bitwise operation type!";
+        }
+        cv::GComputation c(GIn(in1, sc1), GOut(out));
+
+        // Warm-up graph engine:
+        c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+        TEST_CYCLE()
+        {
+            c.apply(gin(in_mat1, sc), gout(out_mat_gapi));
+        }
     }
-    case XOR:
+    else
     {
-        out = cv::gapi::bitwise_xor(in1, in2);
-        cv::bitwise_xor(in_mat1, in_mat2, out_mat_ocv);
-        break;
-    }
-    default:
-    {
-        FAIL() << "no such bitwise operation type!";
-    }
-    }
-    cv::GComputation c(GIn(in1, in2), GOut(out));
-
-    // Warm-up graph engine:
-    auto cc = c.compile(descr_of(gin(in_mat1, in_mat2)),
-                        std::move(compile_args));
-    cc(gin(in_mat1, in_mat2), gout(out_mat_gapi));
-
-    TEST_CYCLE()
-    {
-        cc(gin(in_mat1, in_mat2), gout(out_mat_gapi));
+        switch (opType)
+        {
+        case AND:
+            out = cv::gapi::bitwise_and(in1, in2);
+            cv::bitwise_and(in_mat1, in_mat2, out_mat_ocv);
+            break;
+        case OR:
+            out = cv::gapi::bitwise_or(in1, in2);
+            cv::bitwise_or(in_mat1, in_mat2, out_mat_ocv);
+            break;
+        case XOR:
+            out = cv::gapi::bitwise_xor(in1, in2);
+            cv::bitwise_xor(in_mat1, in_mat2, out_mat_ocv);
+            break;
+        default:
+            FAIL() << "no such bitwise operation type!";
+        }
+        cv::GComputation c(GIn(in1, in2), GOut(out));
+
+        // Warm-up graph engine:
+        c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+        TEST_CYCLE()
+        {
+            c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi));
+        }
     }
 
     // Comparison ////////////////////////////////////////////////////////////
@@ -1805,20 +1829,23 @@ PERF_TEST_P_(LUTPerfTest, TestPerformance)
 
 PERF_TEST_P_(ConvertToPerfTest, TestPerformance)
 {
-    MatType type_mat = get<0>(GetParam());
-    int depth_to = get<1>(GetParam());
-    cv::Size sz_in = get<2>(GetParam());
-    cv::GCompileArgs compile_args = get<3>(GetParam());
+    int depth_to     = -1;
+    MatType type_mat = -1;
+    double alpha = 0., beta = 0.;
+    cv::Size sz_in;
+    compare_f cmpF;
+    cv::GCompileArgs compile_args;
+    std::tie(cmpF, type_mat, depth_to, sz_in, alpha, beta, compile_args) = GetParam();
     MatType type_out = CV_MAKETYPE(depth_to, CV_MAT_CN(type_mat));
 
     initMatrixRandU(type_mat, sz_in, type_out);
 
     // OpenCV code ///////////////////////////////////////////////////////////
-    in_mat1.convertTo(out_mat_ocv, depth_to);
+    in_mat1.convertTo(out_mat_ocv, depth_to, alpha, beta);
 
     // G-API code //////////////////////////////////////////////////////////////
     cv::GMat in;
-    auto out = cv::gapi::convertTo(in, depth_to);
+    auto out = cv::gapi::convertTo(in, depth_to, alpha, beta);
     cv::GComputation c(in, out);
 
     // Warm-up graph engine:
@@ -1832,7 +1859,7 @@ PERF_TEST_P_(ConvertToPerfTest, TestPerformance)
     }
 
     // Comparison ////////////////////////////////////////////////////////////
-    // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+    EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
     EXPECT_EQ(out_mat_gapi.size(), sz_in);
 
     SANITY_CHECK_NOTHING();
@@ -1930,5 +1957,187 @@ PERF_TEST_P_(ResizeFxFyPerfTest, TestPerformance)
 
 //------------------------------------------------------------------------------
 
+PERF_TEST_P_(ParseSSDBLPerfTest, TestPerformance)
+{
+    cv::Size sz;
+    float confidence_threshold = 0.0f;
+    int filter_label = 0;
+    cv::GCompileArgs compile_args;
+    std::tie(sz, confidence_threshold, filter_label, compile_args) = GetParam();
+    cv::Mat in_mat = generateSSDoutput(sz);
+    std::vector<cv::Rect> boxes_gapi, boxes_ref;
+    std::vector<int> labels_gapi, labels_ref;
+
+    // Reference code //////////////////////////////////////////////////////////
+    parseSSDBLref(in_mat, sz, confidence_threshold, filter_label, boxes_ref, labels_ref);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    cv::GOpaque<cv::Size> op_sz;
+    auto out = cv::gapi::parseSSD(in, op_sz, confidence_threshold, filter_label);
+    cv::GComputation c(cv::GIn(in, op_sz), cv::GOut(std::get<0>(out), std::get<1>(out)));
+
+    // Warm-up graph engine:
+    auto cc = c.compile(descr_of(in_mat), descr_of(sz), std::move(compile_args));
+    cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi));
+
+    TEST_CYCLE()
+    {
+        cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi));
+    }
+
+    // Comparison ////////////////////////////////////////////////////////////
+    {
+        EXPECT_TRUE(boxes_gapi == boxes_ref);
+        EXPECT_TRUE(labels_gapi == labels_ref);
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ParseSSDPerfTest, TestPerformance)
+{
+    cv::Size sz;
+    float confidence_threshold = 0;
+    bool alignment_to_square = false, filter_out_of_bounds = false;
+    cv::GCompileArgs compile_args;
+    std::tie(sz, confidence_threshold, alignment_to_square, filter_out_of_bounds, compile_args) = GetParam();
+    cv::Mat in_mat = generateSSDoutput(sz);
+    std::vector<cv::Rect> boxes_gapi, boxes_ref;
+
+    // Reference code //////////////////////////////////////////////////////////
+    parseSSDref(in_mat, sz, confidence_threshold, alignment_to_square, filter_out_of_bounds, boxes_ref);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    cv::GOpaque<cv::Size> op_sz;
+    auto out = cv::gapi::parseSSD(in, op_sz, confidence_threshold, alignment_to_square, filter_out_of_bounds);
+    cv::GComputation c(cv::GIn(in, op_sz), cv::GOut(out));
+
+    // Warm-up graph engine:
+    auto cc = c.compile(descr_of(in_mat), descr_of(sz), std::move(compile_args));
+    cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi));
+
+    TEST_CYCLE()
+    {
+        cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi));
+    }
+
+    // Comparison ////////////////////////////////////////////////////////////
+    {
+        EXPECT_TRUE(boxes_gapi == boxes_ref);
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ParseYoloPerfTest, TestPerformance)
+{
+    cv::Size sz;
+    float confidence_threshold = 0.0f, nms_threshold = 0.0f;
+    int num_classes = 0;
+    cv::GCompileArgs compile_args;
+    std::tie(sz, confidence_threshold, nms_threshold, num_classes, compile_args) = GetParam();
+    cv::Mat in_mat = generateYoloOutput(num_classes);
+    auto anchors = cv::gapi::nn::parsers::GParseYolo::defaultAnchors();
+    std::vector<cv::Rect> boxes_gapi, boxes_ref;
+    std::vector<int> labels_gapi, labels_ref;
+
+    // Reference code //////////////////////////////////////////////////////////
+    parseYoloRef(in_mat, sz, confidence_threshold, nms_threshold, num_classes, anchors, boxes_ref, labels_ref);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    cv::GOpaque<cv::Size> op_sz;
+    auto out = cv::gapi::parseYolo(in, op_sz, confidence_threshold, nms_threshold, anchors);
+    cv::GComputation c(cv::GIn(in, op_sz), cv::GOut(std::get<0>(out), std::get<1>(out)));
+
+    // Warm-up graph engine:
+    auto cc = c.compile(descr_of(in_mat), descr_of(sz), std::move(compile_args));
+    cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi));
+
+    TEST_CYCLE()
+    {
+        cc(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi));
+    }
+
+    // Comparison ////////////////////////////////////////////////////////////
+    {
+        EXPECT_TRUE(boxes_gapi == boxes_ref);
+        EXPECT_TRUE(labels_gapi == labels_ref);
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(SizePerfTest, TestPerformance)
+{
+    MatType type;
+    cv::Size sz;
+    cv::GCompileArgs compile_args;
+    std::tie(type, sz, compile_args) = GetParam();
+    in_mat1 = cv::Mat(sz, type);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    auto out = cv::gapi::size(in);
+    cv::GComputation c(cv::GIn(in), cv::GOut(out));
+    cv::Size out_sz;
+
+    // Warm-up graph engine:
+    auto cc = c.compile(descr_of(in_mat1), std::move(compile_args));
+    cc(cv::gin(in_mat1), cv::gout(out_sz));
+
+    TEST_CYCLE()
+    {
+        cc(cv::gin(in_mat1), cv::gout(out_sz));
+    }
+
+    // Comparison ////////////////////////////////////////////////////////////
+    {
+        EXPECT_EQ(out_sz, sz);
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(SizeRPerfTest, TestPerformance)
+{
+    cv::Size sz;
+    cv::GCompileArgs compile_args;
+    std::tie(sz, compile_args) = GetParam();
+    cv::Rect rect(cv::Point(0,0), sz);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GOpaque<cv::Rect> op_rect;
+    auto out = cv::gapi::size(op_rect);
+    cv::GComputation c(cv::GIn(op_rect), cv::GOut(out));
+    cv::Size out_sz;
+
+    // Warm-up graph engine:
+    auto cc = c.compile(descr_of(rect), std::move(compile_args));
+    cc(cv::gin(rect), cv::gout(out_sz));
+
+    TEST_CYCLE()
+    {
+        cc(cv::gin(rect), cv::gout(out_sz));
+    }
+
+    // Comparison ////////////////////////////////////////////////////////////
+    {
+        EXPECT_EQ(out_sz, sz);
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
 }
 #endif // OPENCV_GAPI_CORE_PERF_TESTS_INL_HPP
index c4e5bc6..b259190 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_IMGPROC_PERF_TESTS_HPP
@@ -20,31 +20,40 @@ namespace opencv_test
 
   //------------------------------------------------------------------------------
 
-class SepFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, int, cv::GCompileArgs>> {};
-class Filter2DPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
-class BoxFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
-class BlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
-class GaussianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, cv::GCompileArgs>> {};
-class MedianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size, cv::GCompileArgs>> {};
-class ErodePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
-class Erode3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType, cv::Size, int, cv::GCompileArgs>> {};
-class DilatePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
-class Dilate3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
-class SobelPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int,int, cv::GCompileArgs>> {};
-class SobelXYPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
-class CannyPerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,double,double,int,bool, cv::GCompileArgs>> {};
-class EqHistPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
-class RGB2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
-class BGR2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
-class RGB2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
-class YUV2RGBPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
-class RGB2LabPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
-class BGR2LUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
-class LUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
-class BGR2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
-class YUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
-class RGB2HSVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class SepFilterPerfTest       : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
+class Filter2DPerfTest        : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
+class BoxFilterPerfTest       : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
+class BlurPerfTest            : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
+class GaussianBlurPerfTest    : public TestPerfParams<tuple<compare_f, MatType,int, cv::Size, cv::GCompileArgs>> {};
+class MedianBlurPerfTest      : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size, cv::GCompileArgs>> {};
+class ErodePerfTest           : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
+class Erode3x3PerfTest        : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
+class DilatePerfTest          : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
+class Dilate3x3PerfTest       : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
+class SobelPerfTest           : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int,int, cv::GCompileArgs>> {};
+class SobelXYPerfTest         : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
+class LaplacianPerfTest       : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,
+                                                            cv::GCompileArgs>> {};
+class BilateralFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, double,double,
+                                                            cv::GCompileArgs>> {};
+class CannyPerfTest           : public TestPerfParams<tuple<compare_f, MatType,cv::Size,double,double,int,bool,
+                                                            cv::GCompileArgs>> {};
+class GoodFeaturesPerfTest    : public TestPerfParams<tuple<compare_vector_f<cv::Point2f>, std::string,
+                                                            int,int,double,double,int,bool,
+                                                            cv::GCompileArgs>> {};
+class EqHistPerfTest      : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class RGB2GrayPerfTest    : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class BGR2GrayPerfTest    : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class RGB2YUVPerfTest     : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class YUV2RGBPerfTest     : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class RGB2LabPerfTest     : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class BGR2LUVPerfTest     : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class LUV2BGRPerfTest     : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class BGR2YUVPerfTest     : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class YUV2BGRPerfTest     : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class RGB2HSVPerfTest     : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
 class BayerGR2RGBPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
 class RGB2YUV422PerfTest  : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
-}
+} // opencv_test
+
 #endif //OPENCV_GAPI_IMGPROC_PERF_TESTS_HPP
index 3fea552..f71e435 100644 (file)
@@ -2,15 +2,13 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018-2019 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_IMGPROC_PERF_TESTS_INL_HPP
 #define OPENCV_GAPI_IMGPROC_PERF_TESTS_INL_HPP
 
 
-#include <iostream>
-
 #include "gapi_imgproc_perf_tests.hpp"
 
 namespace opencv_test
@@ -579,6 +577,89 @@ PERF_TEST_P_(SobelXYPerfTest, TestPerformance)
 
 //------------------------------------------------------------------------------
 
+PERF_TEST_P_(LaplacianPerfTest, TestPerformance)
+{
+    compare_f cmpF;
+    MatType type = 0;
+    int kernSize = 0, dtype = 0;
+    cv::Size sz;
+    cv::GCompileArgs compile_args;
+    std::tie(cmpF, type, kernSize, sz, dtype, compile_args) = GetParam();
+
+    initMatrixRandN(type, sz, dtype, false);
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::Laplacian(in_mat1, out_mat_ocv, dtype, kernSize);
+    }
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    auto out = cv::gapi::Laplacian(in, dtype, kernSize);
+    cv::GComputation c(in, out);
+
+    // Warm-up graph engine:
+    c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+    TEST_CYCLE()
+    {
+        c.apply(in_mat1, out_mat_gapi);
+    }
+
+    // Comparison //////////////////////////////////////////////////////////////
+    {
+        EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+        EXPECT_EQ(out_mat_gapi.size(), sz);
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(BilateralFilterPerfTest, TestPerformance)
+{
+    compare_f cmpF;
+    MatType type = 0;
+    int dtype = 0, d = 0, borderType = BORDER_DEFAULT;
+    double sigmaColor = 0, sigmaSpace = 0;
+    cv::Size sz;
+    cv::GCompileArgs compile_args;
+    std::tie(cmpF, type, dtype, sz, d, sigmaColor, sigmaSpace,
+             compile_args) = GetParam();
+
+    initMatrixRandN(type, sz, dtype, false);
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::bilateralFilter(in_mat1, out_mat_ocv, d, sigmaColor, sigmaSpace, borderType);
+    }
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    auto out = cv::gapi::bilateralFilter(in, d, sigmaColor, sigmaSpace, borderType);
+    cv::GComputation c(in, out);
+
+    // Warm-up graph engine:
+    c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+    TEST_CYCLE()
+    {
+        c.apply(in_mat1, out_mat_gapi);
+    }
+
+    // Comparison //////////////////////////////////////////////////////////////
+    {
+        EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+        EXPECT_EQ(out_mat_gapi.size(), sz);
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+
 PERF_TEST_P_(CannyPerfTest, TestPerformance)
 {
     compare_f cmpF;
@@ -622,6 +703,53 @@ PERF_TEST_P_(CannyPerfTest, TestPerformance)
 
 //------------------------------------------------------------------------------
 
+PERF_TEST_P_(GoodFeaturesPerfTest, TestPerformance)
+{
+    double k = 0.04;
+
+    compare_vector_f<cv::Point2f> cmpF;
+    std::string fileName = "";
+    int type = -1, maxCorners = -1, blockSize = -1;
+    double qualityLevel = 0.0, minDistance = 0.0;
+    bool useHarrisDetector = false;
+    cv::GCompileArgs compileArgs;
+    std::tie(cmpF, fileName, type, maxCorners, qualityLevel,
+             minDistance, blockSize, useHarrisDetector, compileArgs) = GetParam();
+
+    initMatFromImage(type, fileName);
+    std::vector<cv::Point2f> outVecOCV, outVecGAPI;
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::goodFeaturesToTrack(in_mat1, outVecOCV, maxCorners, qualityLevel, minDistance,
+                                cv::noArray(), blockSize, useHarrisDetector, k);
+    }
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    auto out = cv::gapi::goodFeaturesToTrack(in, maxCorners, qualityLevel, minDistance, cv::Mat(),
+                                             blockSize, useHarrisDetector, k);
+    cv::GComputation c(cv::GIn(in), cv::GOut(out));
+
+    // Warm-up graph engine:
+    c.apply(cv::gin(in_mat1), cv::gout(outVecGAPI), std::move(compileArgs));
+
+    TEST_CYCLE()
+    {
+        c.apply(cv::gin(in_mat1), cv::gout(outVecGAPI));
+    }
+
+    // Comparison //////////////////////////////////////////////////////////////
+    {
+        EXPECT_TRUE(cmpF(outVecGAPI, outVecOCV));
+    }
+
+    SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
 PERF_TEST_P_(EqHistPerfTest, TestPerformance)
 {
     compare_f cmpF = get<0>(GetParam());
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_render_perf_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_render_perf_tests.cpp
new file mode 100644 (file)
index 0000000..339a7bc
--- /dev/null
@@ -0,0 +1,9 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+#include "gapi_render_perf_tests_inl.hpp"
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_render_perf_tests.hpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_render_perf_tests.hpp
new file mode 100644 (file)
index 0000000..df14422
--- /dev/null
@@ -0,0 +1,43 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_RENDER_PERF_TESTS_HPP
+#define OPENCV_GAPI_RENDER_PERF_TESTS_HPP
+
+
+#include "../../test/common/gapi_tests_common.hpp"
+#include <opencv2/gapi/render/render.hpp>
+
+namespace opencv_test
+{
+
+using namespace perf;
+
+class RenderTestFTexts : public TestPerfParams<tuple<std::wstring, cv::Size, cv::Point,
+                                                     int, cv::Scalar, cv::GCompileArgs>> {};
+class RenderTestTexts : public TestPerfParams<tuple<std::string, cv::Size, cv::Point,
+                                                    int, cv::Scalar, int, int,
+                                                    bool, cv::GCompileArgs>> {};
+class RenderTestRects : public TestPerfParams<tuple<cv::Size, cv::Rect, cv::Scalar,
+                                                    int, int, int, cv::GCompileArgs>> {};
+class RenderTestCircles : public TestPerfParams<tuple<cv::Size, cv::Point, int,
+                                                      cv::Scalar, int, int, int,
+                                                      cv::GCompileArgs>> {};
+class RenderTestLines : public TestPerfParams<tuple<cv::Size, cv::Point, cv::Point,
+                                                    cv::Scalar, int, int, int,
+                                                    cv::GCompileArgs>> {};
+class RenderTestMosaics : public TestPerfParams<tuple<cv::Size, cv::Rect, int, int,
+                                                      cv::GCompileArgs>> {};
+class RenderTestImages : public TestPerfParams<tuple<cv::Size, cv::Rect, cv::Scalar, double,
+                                                     cv::GCompileArgs>> {};
+class RenderTestPolylines : public TestPerfParams<tuple<cv::Size, std::vector<cv::Point>,
+                                                        cv::Scalar, int, int, int,
+                                                        cv::GCompileArgs>> {};
+class RenderTestPolyItems : public TestPerfParams<tuple<cv::Size, int, int, int, cv::GCompileArgs>> {};
+
+}
+#endif //OPENCV_GAPI_RENDER_PERF_TESTS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_render_perf_tests_inl.hpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_render_perf_tests_inl.hpp
new file mode 100644 (file)
index 0000000..66e8c37
--- /dev/null
@@ -0,0 +1,827 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "gapi_render_perf_tests.hpp"
+
+namespace opencv_test
+{
+
+namespace {
+void create_rand_mats(const cv::Size &size, MatType type, cv::Mat &ref_mat, cv::Mat &gapi_mat)
+{
+    ref_mat.create(size, type);
+    cv::randu(ref_mat, cv::Scalar::all(0), cv::Scalar::all(255));
+    ref_mat.copyTo(gapi_mat);
+};
+
+} // namespace
+
+PERF_TEST_P_(RenderTestFTexts, RenderFTextsPerformanceBGROCVTest)
+{
+    std::wstring text;
+    cv::Size sz;
+    cv::Point org;
+    int fh = 0;
+    cv::Scalar color;
+    cv::GCompileArgs comp_args;
+    std::tie(text ,sz ,org ,fh ,color, comp_args) = GetParam();
+
+    MatType type =  CV_8UC3;
+    cv::Mat gapi_mat, ref_mat;
+    create_rand_mats(sz, type, ref_mat, gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::FText{text, org, fh, color});
+
+    cv::GMat in;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+
+    cv::GComputation comp(cv::GIn(in, arr),
+                          cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
+
+    // Warm-up graph engine:
+    comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestFTexts, RenderFTextsPerformanceNV12OCVTest)
+{
+    std::wstring text;
+    cv::Size sz;
+    cv::Point org;
+    int fh = 0;
+    cv::Scalar color;
+    cv::GCompileArgs comp_args;
+    std::tie(text ,sz ,org ,fh ,color, comp_args) = GetParam();
+
+    cv::Mat y_ref_mat, uv_ref_mat;
+
+    cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
+            y_out_gapi_mat, uv_out_gapi_mat;
+
+    create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
+    create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::FText{text, org, fh, color});
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    // Warm-up graph engine:
+    comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+               cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+                   cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestTexts, RenderTextsPerformanceBGROCVTest)
+{
+    cv::Point org;
+    int ff = 0;
+    int thick = 0;
+    int lt = 0;
+    double fs = 2.0;
+    cv::Scalar color;
+    bool blo = false;
+    std::string text;
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(text, sz, org, ff, color, thick, lt, blo, comp_args) = GetParam();
+
+    MatType type =  CV_8UC3;
+    cv::Mat gapi_mat, ref_mat;
+    create_rand_mats(sz, type, ref_mat, gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Text{text, org, ff, fs, color, thick, lt, blo});
+
+    cv::GMat in;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+
+    cv::GComputation comp(cv::GIn(in, arr),
+                          cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
+
+    // Warm-up graph engine:
+    comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestTexts, RenderTextsPerformanceNV12OCVTest)
+{
+    cv::Point org;
+    int ff = 0;
+    int thick = 0;
+    int lt = 0;
+    double fs = 2.0;
+    cv::Scalar color;
+    bool blo = false;
+    std::string text;
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(text, sz, org, ff, color, thick, lt, blo, comp_args) = GetParam();
+
+    cv::Mat y_ref_mat, uv_ref_mat;
+
+    cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
+            y_out_gapi_mat, uv_out_gapi_mat;
+
+    create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
+    create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Text{text, org, ff, fs, color, thick, lt, blo});
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    // Warm-up graph engine:
+    comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+               cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+                   cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestRects, RenderRectsPerformanceBGROCVTest)
+{
+    cv::Rect rect;
+    cv::Scalar color;
+    int thick = 0;
+    int lt = 0;
+    int shift = 0;
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, rect, color, thick, lt, shift, comp_args) = GetParam();
+
+    MatType type =  CV_8UC3;
+    cv::Mat gapi_mat, ref_mat;
+    create_rand_mats(sz, type, ref_mat, gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Rect{rect, color, thick, lt, shift});
+
+    cv::GMat in;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+
+    cv::GComputation comp(cv::GIn(in, arr),
+                          cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
+
+    // Warm-up graph engine:
+    comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestRects, RenderRectsPerformanceNV12OCVTest)
+{
+    cv::Rect rect;
+    cv::Scalar color;
+    int thick = 0;
+    int lt = 0;
+    int shift = 0;
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, rect, color, thick, lt, shift, comp_args) = GetParam();
+
+    cv::Mat y_ref_mat, uv_ref_mat;
+
+    cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
+            y_out_gapi_mat, uv_out_gapi_mat;
+
+    create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
+    create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Rect{rect, color, thick, lt, shift});
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    // Warm-up graph engine:
+    comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+               cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+                   cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestCircles, RenderCirclesPerformanceBGROCVTest)
+{
+    cv::Point center;
+    int radius;
+    cv::Scalar color;
+    int thick = 0;
+    int lt = 0;
+    int shift = 0;
+
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, center, radius, color, thick, lt, shift, comp_args) = GetParam();
+
+    MatType type =  CV_8UC3;
+    cv::Mat gapi_mat, ref_mat;
+    create_rand_mats(sz, type, ref_mat, gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Circle{center, radius, color, thick, lt, shift});
+
+    cv::GMat in;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+
+    cv::GComputation comp(cv::GIn(in, arr),
+                          cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
+
+    // Warm-up graph engine:
+    comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestCircles, RenderCirclesPerformanceNV12OCVTest)
+{
+    cv::Point center;
+    int radius;
+    cv::Scalar color;
+    int thick = 0;
+    int lt = 0;
+    int shift = 0;
+
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, center, radius, color, thick, lt, shift, comp_args) = GetParam();
+
+    cv::Mat y_ref_mat, uv_ref_mat;
+
+    cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
+            y_out_gapi_mat, uv_out_gapi_mat;
+
+    create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
+    create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Circle{center, radius, color, thick, lt, shift});
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    // Warm-up graph engine:
+    comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+               cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+                   cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestLines, RenderLinesPerformanceBGROCVTest)
+{
+    cv::Point pt1;
+    cv::Point pt2;
+    cv::Scalar color;
+    int thick = 0;
+    int lt = 0;
+    int shift = 0;
+
+    compare_f cmpF;
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, pt1, pt2, color, thick, lt, shift, comp_args) = GetParam();
+
+    MatType type =  CV_8UC3;
+    cv::Mat gapi_mat, ref_mat;
+    create_rand_mats(sz, type, ref_mat, gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Line{pt1, pt2, color, thick, lt, shift});
+
+    cv::GMat in;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+
+    cv::GComputation comp(cv::GIn(in, arr),
+                          cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
+
+    // Warm-up graph engine:
+    comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestLines, RenderLinesPerformanceNV12OCVTest)
+{
+    cv::Point pt1;
+    cv::Point pt2;
+    cv::Scalar color;
+    int thick = 0;
+    int lt = 0;
+    int shift = 0;
+
+    compare_f cmpF;
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, pt1, pt2, color, thick, lt, shift, comp_args) = GetParam();
+
+    cv::Mat y_ref_mat, uv_ref_mat;
+
+    cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
+            y_out_gapi_mat, uv_out_gapi_mat;
+
+    create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
+    create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Line{pt1, pt2, color, thick, lt, shift});
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    // Warm-up graph engine:
+    comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+               cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+                   cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestMosaics, RenderMosaicsPerformanceBGROCVTest)
+{
+    cv::Rect mos;
+    int cellsz = 0;
+    int decim = 0;
+
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, mos, cellsz, decim, comp_args) = GetParam();
+
+    MatType type =  CV_8UC3;
+    cv::Mat gapi_mat, ref_mat;
+    create_rand_mats(sz, type, ref_mat, gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Mosaic{mos, cellsz, decim});
+
+    cv::GMat in;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+
+    cv::GComputation comp(cv::GIn(in, arr),
+                          cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
+
+    // Warm-up graph engine:
+    comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+
+PERF_TEST_P_(RenderTestMosaics, RenderMosaicsPerformanceNV12OCVTest)
+{
+    cv::Rect mos;
+    int cellsz = 0;
+    int decim = 0;
+
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, mos, cellsz, decim, comp_args) = GetParam();
+
+    cv::Mat y_ref_mat, uv_ref_mat;
+
+    cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
+            y_out_gapi_mat, uv_out_gapi_mat;
+
+    create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
+    create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Mosaic{mos, cellsz, decim});
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    // Warm-up graph engine:
+    comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+               cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+                   cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestImages, RenderImagesPerformanceBGROCVTest)
+{
+    cv::Rect rect;
+    cv::Scalar color;
+    double transparency = 0.0;
+
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, rect, color, transparency, comp_args) = GetParam();
+
+    MatType type =  CV_8UC3;
+    cv::Mat gapi_mat, ref_mat;
+    create_rand_mats(sz, type, ref_mat, gapi_mat);
+
+    cv::Mat img(rect.size(), CV_8UC3, color);
+    cv::Mat alpha(rect.size(), CV_32FC1, transparency);
+    auto tl = rect.tl();
+    cv::Point org = {tl.x, tl.y + rect.size().height};
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Image{org, img, alpha});
+    cv::gapi::wip::draw::render(gapi_mat, prims);
+
+    cv::GMat in;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+
+    cv::GComputation comp(cv::GIn(in, arr),
+                          cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
+
+    // Warm-up graph engine:
+    comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestImages, RenderImagesPerformanceNV12OCVTest)
+{
+    cv::Rect rect;
+    cv::Scalar color;
+    double transparency = 0.0;
+
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, rect, color, transparency, comp_args) = GetParam();
+
+    cv::Mat y_ref_mat, uv_ref_mat;
+
+    cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
+            y_out_gapi_mat, uv_out_gapi_mat;
+
+    create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
+    create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
+
+    cv::Mat img(rect.size(), CV_8UC3, color);
+    cv::Mat alpha(rect.size(), CV_32FC1, transparency);
+    auto tl = rect.tl();
+    cv::Point org = {tl.x, tl.y + rect.size().height};
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Image{org, img, alpha});
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    // Warm-up graph engine:
+    comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+               cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+                   cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestPolylines, RenderPolylinesPerformanceBGROCVTest)
+{
+    std::vector<cv::Point> points;
+    cv::Scalar color;
+    int thick = 0;
+    int lt = 0;
+    int shift = 0;
+
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, points, color, thick, lt, shift, comp_args) = GetParam();
+
+    MatType type =  CV_8UC3;
+    cv::Mat gapi_mat, ref_mat;
+    create_rand_mats(sz, type, ref_mat, gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Poly{points, color, thick, lt, shift});
+
+    cv::GMat in;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+
+    cv::GComputation comp(cv::GIn(in, arr),
+                          cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
+
+    // Warm-up graph engine:
+    comp.apply(gin(gapi_mat, prims), gout(gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(gin(gapi_mat, prims), gout(gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestPolylines, RenderPolylinesPerformanceNV12OCVTest)
+{
+    std::vector<cv::Point> points;
+    cv::Scalar color;
+    int thick = 0;
+    int lt = 0;
+    int shift = 0;
+
+    cv::Size sz;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, points, color, thick, lt, shift, comp_args) = GetParam();
+
+    cv::Mat y_ref_mat, uv_ref_mat;
+
+    cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
+            y_out_gapi_mat, uv_out_gapi_mat;
+
+    create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
+    create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+    prims.emplace_back(cv::gapi::wip::draw::Poly{points, color, thick, lt, shift});
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    // Warm-up graph engine:
+    comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+               cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+                   cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestPolyItems, RenderPolyItemsPerformanceBGROCVTest)
+{
+    cv::Size sz;
+    int rects_num = 0;
+    int text_num = 0;
+    int image_num = 0;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, rects_num, text_num, image_num, comp_args) = GetParam();
+
+    int thick = 2;
+    int lt = LINE_8;
+    cv::Scalar color(100, 50, 150);
+
+    MatType type = CV_8UC3;
+    cv::Mat gapi_mat, ref_mat;
+    create_rand_mats(sz, type, ref_mat, gapi_mat);
+    cv::Mat gapi_out_mat(sz, type);
+    gapi_mat.copyTo(gapi_out_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+
+    // Rects
+    int shift = 0;
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect rect(200 + i, 200 + i, 200, 200);
+        prims.emplace_back(cv::gapi::wip::draw::Rect(rect, color, thick, lt, shift));
+    }
+
+    // Mosaic
+    int cellsz = 25;
+    int decim = 0;
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect mos(200 + i, 200 + i, 200, 200);
+        prims.emplace_back(cv::gapi::wip::draw::Mosaic(mos, cellsz, decim));
+    }
+
+    // Text
+    std::string text = "Some text";
+    int ff = FONT_HERSHEY_SIMPLEX;
+    double fs = 2.0;
+    bool blo = false;
+    for (int i = 0; i < text_num; ++i) {
+        cv::Point org(200 + i, 200 + i);
+        prims.emplace_back(cv::gapi::wip::draw::Text(text, org, ff, fs, color, thick, lt, blo));
+    }
+
+    // Image
+    double transparency = 1.0;
+    cv::Rect rect_img(0 ,0 , 50, 50);
+    cv::Mat img(rect_img.size(), CV_8UC3, color);
+    cv::Mat alpha(rect_img.size(), CV_32FC1, transparency);
+    auto tl = rect_img.tl();
+    for (int i = 0; i < image_num; ++i) {
+        cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
+
+        prims.emplace_back(cv::gapi::wip::draw::Image({org_img, img, alpha}));
+    }
+
+    cv::GMat in;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+
+    cv::GComputation comp(cv::GIn(in, arr),
+                          cv::GOut(cv::gapi::wip::draw::render3ch(in, arr)));
+
+    // Warm-up graph engine:
+    comp.apply(gin(gapi_mat, prims), gout(gapi_out_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(gin(gapi_mat, prims), gout(gapi_out_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(RenderTestPolyItems, RenderPolyItemsPerformanceNV12OCVTest)
+{
+    cv::Size sz;
+    int rects_num = 0;
+    int text_num = 0;
+    int image_num = 0;
+    cv::GCompileArgs comp_args;
+    std::tie(sz, rects_num, text_num, image_num, comp_args) = GetParam();
+
+    int thick = 2;
+    int lt = LINE_8;
+    cv::Scalar color(100, 50, 150);
+
+    cv::Mat y_ref_mat, uv_ref_mat;
+
+    cv::Mat y_in_gapi_mat, uv_in_gapi_mat,
+            y_out_gapi_mat, uv_out_gapi_mat;
+
+    create_rand_mats(sz, CV_8UC1, y_ref_mat, y_in_gapi_mat);
+    create_rand_mats(sz / 2, CV_8UC2, uv_ref_mat, uv_in_gapi_mat);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+
+    // Rects
+    int shift = 0;
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect rect(200 + i, 200 + i, 200, 200);
+        prims.emplace_back(cv::gapi::wip::draw::Rect(rect, color, thick, lt, shift));
+    }
+
+    // Mosaic
+    int cellsz = 25;
+    int decim = 0;
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect mos(200 + i, 200 + i, 200, 200);
+        prims.emplace_back(cv::gapi::wip::draw::Mosaic(mos, cellsz, decim));
+    }
+
+    // Text
+    std::string text = "Some text";
+    int ff = FONT_HERSHEY_SIMPLEX;
+    double fs = 2.0;
+    bool blo = false;
+    for (int i = 0; i < text_num; ++i) {
+        cv::Point org(200 + i, 200 + i);
+        prims.emplace_back(cv::gapi::wip::draw::Text(text, org, ff, fs, color, thick, lt, blo));
+    }
+
+    // Image
+    double transparency = 1.0;
+    cv::Rect rect_img(0 ,0 , 50, 50);
+    cv::Mat img(rect_img.size(), CV_8UC3, color);
+    cv::Mat alpha(rect_img.size(), CV_32FC1, transparency);
+    auto tl = rect_img.tl();
+    for (int i = 0; i < image_num; ++i) {
+        cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
+
+        prims.emplace_back(cv::gapi::wip::draw::Image({org_img, img, alpha}));
+    }
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    // Warm-up graph engine:
+    comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+               cv::gout(y_out_gapi_mat, uv_out_gapi_mat), std::move(comp_args));
+
+    TEST_CYCLE()
+    {
+        comp.apply(cv::gin(y_in_gapi_mat, uv_in_gapi_mat, prims),
+                   cv::gout(y_out_gapi_mat, uv_out_gapi_mat));
+    }
+
+    SANITY_CHECK_NOTHING();
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_video_perf_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_video_perf_tests.cpp
new file mode 100644 (file)
index 0000000..efa1765
--- /dev/null
@@ -0,0 +1,9 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+#include "gapi_video_perf_tests_inl.hpp"
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_video_perf_tests.hpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_video_perf_tests.hpp
new file mode 100644 (file)
index 0000000..b59d6b7
--- /dev/null
@@ -0,0 +1,31 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_VIDEO_PERF_TESTS_HPP
+#define OPENCV_GAPI_VIDEO_PERF_TESTS_HPP
+
+#include "../../test/common/gapi_video_tests_common.hpp"
+
+namespace opencv_test
+{
+
+using namespace perf;
+
+//------------------------------------------------------------------------------
+
+class BuildOptFlowPyramidPerfTest : public TestPerfParams<tuple<std::string,int,int,bool,int,int,
+                                                                bool,GCompileArgs>> {};
+class OptFlowLKPerfTest : public TestPerfParams<tuple<std::string,int,tuple<int,int>,int,
+                                                      cv::TermCriteria,cv::GCompileArgs>> {};
+class OptFlowLKForPyrPerfTest : public TestPerfParams<tuple<std::string,int,tuple<int,int>,int,
+                                                            cv::TermCriteria,bool,
+                                                            cv::GCompileArgs>> {};
+class BuildPyr_CalcOptFlow_PipelinePerfTest : public TestPerfParams<tuple<std::string,int,int,bool,
+                                                                          cv::GCompileArgs>> {};
+
+} // opencv_test
+
+#endif // OPENCV_GAPI_VIDEO_PERF_TESTS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_video_perf_tests_inl.hpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_video_perf_tests_inl.hpp
new file mode 100644 (file)
index 0000000..d1c81a9
--- /dev/null
@@ -0,0 +1,159 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_VIDEO_PERF_TESTS_INL_HPP
+#define OPENCV_GAPI_VIDEO_PERF_TESTS_INL_HPP
+
+#include <iostream>
+
+#include "gapi_video_perf_tests.hpp"
+
+namespace opencv_test
+{
+
+  using namespace perf;
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(BuildOptFlowPyramidPerfTest, TestPerformance)
+{
+    std::vector<Mat> outPyrOCV,          outPyrGAPI;
+    int              outMaxLevelOCV = 0, outMaxLevelGAPI = 0;
+    Scalar           outMaxLevelSc;
+
+    BuildOpticalFlowPyramidTestParams params;
+    std::tie(params.fileName, params.winSize,
+             params.maxLevel, params.withDerivatives,
+             params.pyrBorder, params.derivBorder,
+             params.tryReuseInputImage, params.compileArgs) = GetParam();
+
+    BuildOpticalFlowPyramidTestOutput outOCV  { outPyrOCV,  outMaxLevelOCV };
+    BuildOpticalFlowPyramidTestOutput outGAPI { outPyrGAPI, outMaxLevelGAPI };
+
+    GComputation c = runOCVnGAPIBuildOptFlowPyramid(*this, params, outOCV, outGAPI);
+
+    declare.in(in_mat1).out(outPyrGAPI);
+
+    TEST_CYCLE()
+    {
+        c.apply(cv::gin(in_mat1), cv::gout(outPyrGAPI, outMaxLevelSc));
+    }
+    outMaxLevelGAPI = static_cast<int>(outMaxLevelSc[0]);
+
+    // Comparison //////////////////////////////////////////////////////////////
+    compareOutputPyramids(outOCV, outGAPI);
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(OptFlowLKPerfTest, TestPerformance)
+{
+    std::vector<cv::Point2f> outPtsOCV,    outPtsGAPI,    inPts;
+    std::vector<uchar>       outStatusOCV, outStatusGAPI;
+    std::vector<float>       outErrOCV,    outErrGAPI;
+
+    OptFlowLKTestParams params;
+    std::tie(params.fileNamePattern, params.channels,
+             params.pointsNum, params.winSize, params.criteria,
+             params.compileArgs) = GetParam();
+
+    OptFlowLKTestOutput outOCV  { outPtsOCV,  outStatusOCV,  outErrOCV };
+    OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
+
+    cv::GComputation c = runOCVnGAPIOptFlowLK(*this, inPts, params, outOCV, outGAPI);
+
+    declare.in(in_mat1, in_mat2, inPts).out(outPtsGAPI, outStatusGAPI, outErrGAPI);
+
+    TEST_CYCLE()
+    {
+        c.apply(cv::gin(in_mat1, in_mat2, inPts, std::vector<cv::Point2f>{ }),
+                cv::gout(outPtsGAPI, outStatusGAPI, outErrGAPI));
+    }
+
+    // Comparison //////////////////////////////////////////////////////////////
+    compareOutputsOptFlow(outOCV, outGAPI);
+
+    SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(OptFlowLKForPyrPerfTest, TestPerformance)
+{
+    std::vector<cv::Mat>     inPyr1, inPyr2;
+    std::vector<cv::Point2f> outPtsOCV,    outPtsGAPI,    inPts;
+    std::vector<uchar>       outStatusOCV, outStatusGAPI;
+    std::vector<float>       outErrOCV,    outErrGAPI;
+
+    bool withDeriv = false;
+    OptFlowLKTestParams params;
+    std::tie(params.fileNamePattern, params.channels,
+             params.pointsNum, params.winSize, params.criteria,
+             withDeriv, params.compileArgs) = GetParam();
+
+    OptFlowLKTestInput<std::vector<cv::Mat>> in { inPyr1, inPyr2, inPts };
+    OptFlowLKTestOutput outOCV  { outPtsOCV,  outStatusOCV,  outErrOCV };
+    OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
+
+    cv::GComputation c = runOCVnGAPIOptFlowLKForPyr(*this, in, params, withDeriv, outOCV, outGAPI);
+
+    declare.in(inPyr1, inPyr2, inPts).out(outPtsGAPI, outStatusGAPI, outErrGAPI);
+
+    TEST_CYCLE()
+    {
+        c.apply(cv::gin(inPyr1, inPyr2, inPts, std::vector<cv::Point2f>{ }),
+                cv::gout(outPtsGAPI, outStatusGAPI, outErrGAPI));
+    }
+
+    // Comparison //////////////////////////////////////////////////////////////
+    compareOutputsOptFlow(outOCV, outGAPI);
+
+    SANITY_CHECK_NOTHING();
+}
+
+PERF_TEST_P_(BuildPyr_CalcOptFlow_PipelinePerfTest, TestPerformance)
+{
+    std::vector<Point2f> outPtsOCV,    outPtsGAPI,    inPts;
+    std::vector<uchar>   outStatusOCV, outStatusGAPI;
+    std::vector<float>   outErrOCV,    outErrGAPI;
+
+    BuildOpticalFlowPyramidTestParams params;
+    params.pyrBorder          = BORDER_DEFAULT;
+    params.derivBorder        = BORDER_DEFAULT;
+    params.tryReuseInputImage = true;
+    std::tie(params.fileName, params.winSize,
+             params.maxLevel, params.withDerivatives,
+             params.compileArgs) = GetParam();
+
+    auto customKernel  = gapi::kernels<GCPUMinScalar>();
+    auto kernels       = gapi::combine(customKernel,
+                                       params.compileArgs[0].get<gapi::GKernelPackage>());
+    params.compileArgs = compile_args(kernels);
+
+    OptFlowLKTestOutput outOCV  { outPtsOCV,  outStatusOCV,  outErrOCV };
+    OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
+
+    cv::GComputation c = runOCVnGAPIOptFlowPipeline(*this, params, outOCV, outGAPI, inPts);
+
+    declare.in(in_mat1, in_mat2, inPts).out(outPtsGAPI, outStatusGAPI, outErrGAPI);
+
+    TEST_CYCLE()
+    {
+        c.apply(cv::gin(in_mat1, in_mat2, inPts, std::vector<cv::Point2f>{ }),
+                cv::gout(outPtsGAPI, outStatusGAPI, outErrGAPI));
+    }
+
+    // Comparison //////////////////////////////////////////////////////////////
+    compareOutputsOptFlow(outOCV, outGAPI);
+
+    SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+} // opencv_test
+
+#endif // OPENCV_GAPI_VIDEO_PERF_TESTS_INL_HPP
index 9f90d73..d4319f2 100644 (file)
@@ -110,16 +110,18 @@ INSTANTIATE_TEST_CASE_P(CmpPerfTestCPU, CmpPerfTest,
         Values(cv::compile_args(CORE_CPU))));
 
 INSTANTIATE_TEST_CASE_P(CmpWithScalarPerfTestCPU, CmpWithScalarPerfTest,
-    Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
-        Values(szSmall128, szVGA, sz720p, sz1080p),
-        Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
-        Values(cv::compile_args(CORE_CPU))));
+    Combine(Values(AbsExact().to_compare_f()),
+            Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+            Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+            Values(cv::compile_args(CORE_CPU))));
 
 INSTANTIATE_TEST_CASE_P(BitwisePerfTestCPU, BitwisePerfTest,
     Combine(Values(AND, OR, XOR),
-        Values(szSmall128, szVGA, sz720p, sz1080p),
-        Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
-        Values(cv::compile_args(CORE_CPU))));
+            testing::Bool(),
+            Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+            Values(cv::compile_args(CORE_CPU))));
 
 INSTANTIATE_TEST_CASE_P(BitwiseNotPerfTestCPU, BitwiseNotPerfTest,
     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
@@ -266,10 +268,13 @@ INSTANTIATE_TEST_CASE_P(LUTPerfTestCustomCPU, LUTPerfTest,
 
 
 INSTANTIATE_TEST_CASE_P(ConvertToPerfTestCPU, ConvertToPerfTest,
-    Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
-        Values(CV_8U, CV_16U, CV_16S, CV_32F),
-        Values(szSmall128, szVGA, sz720p, sz1080p),
-        Values(cv::compile_args(CORE_CPU))));
+    Combine(Values(AbsExact().to_compare_f()),
+            Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
+            Values(CV_8U, CV_16U, CV_16S, CV_32F),
+            Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(2.5, 1.0),
+            Values(0.0),
+            Values(cv::compile_args(CORE_CPU))));
 
 INSTANTIATE_TEST_CASE_P(ResizePerfTestCPU, ResizePerfTest,
     Combine(Values(AbsExact().to_compare_f()),
@@ -288,4 +293,33 @@ INSTANTIATE_TEST_CASE_P(ResizeFxFyPerfTestCPU, ResizeFxFyPerfTest,
         Values(0.5, 0.1),
         Values(0.5, 0.1),
         Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ParseSSDBLPerfTestCPU, ParseSSDBLPerfTest,
+                        Combine(Values(sz720p, sz1080p),
+                                Values(0.3f, 0.7f),
+                                Values(0, 1),
+                                Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ParseSSDPerfTestCPU, ParseSSDPerfTest,
+                        Combine(Values(sz720p, sz1080p),
+                                Values(0.3f, 0.7f),
+                                testing::Bool(),
+                                testing::Bool(),
+                                Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ParseYoloPerfTestCPU, ParseYoloPerfTest,
+                        Combine(Values(sz720p, sz1080p),
+                                Values(0.3f, 0.7f),
+                                Values(0.5),
+                                Values(7, 80),
+                                Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SizePerfTestCPU, SizePerfTest,
+                        Combine(Values(CV_8UC1, CV_8UC3, CV_32FC1),
+                                Values(szSmall128, szVGA, sz720p, sz1080p),
+                                Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SizeRPerfTestCPU, SizeRPerfTest,
+                        Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+                                Values(cv::compile_args(CORE_CPU))));
 } // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_core_perf_tests_fluid.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_core_perf_tests_fluid.cpp
new file mode 100644 (file)
index 0000000..2234353
--- /dev/null
@@ -0,0 +1,299 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+#include "../common/gapi_core_perf_tests.hpp"
+
+#define CORE_FLUID cv::gapi::core::fluid::kernels()
+
+namespace opencv_test
+{
+INSTANTIATE_TEST_CASE_P(AddPerfTestFluid, AddPerfTest,
+    Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16SC1, CV_32FC1),
+            Values(-1, CV_8U, CV_32F),
+            Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(AddCPerfTestFluid, AddCPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(-1, CV_8U, CV_16U, CV_32F),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(SubPerfTestFluid, SubPerfTest,
+    Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16SC1, CV_32FC1),
+            Values(-1, CV_8U, CV_32F),
+            Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(SubCPerfTestFluid, SubCPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(-1, CV_8U, CV_16U, CV_32F),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(SubRCPerfTestFluid, SubRCPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(-1, CV_8U, CV_16U, CV_32F),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(MulPerfTestFluid, MulPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(-1, CV_8U, CV_16U, CV_32F),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(MulDoublePerfTestFluid, MulDoublePerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(-1, CV_8U, CV_16U, CV_32F),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(MulCPerfTestFluid, MulCPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(-1, CV_8U, CV_16U, CV_32F),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(DivPerfTestFluid, DivPerfTest,
+//     Combine(Values(AbsExact().to_compare_f()),
+//         Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(-1, CV_8U, CV_16U, CV_32F),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(DivCPerfTestFluid, DivCPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(-1, CV_8U, CV_16U, CV_32F),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(DivRCPerfTestFluid, DivRCPerfTest,
+//     Combine(Values(AbsExact().to_compare_f()),
+//         Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(-1, CV_8U, CV_16U, CV_32F),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(MaskPerfTestFluid, MaskPerfTest,
+    Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_16UC1, CV_16SC1),
+            Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(MeanPerfTestFluid, MeanPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(Polar2CartPerfTestFluid, Polar2CartPerfTest,
+//     Combine(Values(AbsExact().to_compare_f()),
+//         Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(Cart2PolarPerfTestFluid, Cart2PolarPerfTest,
+//     Combine(Values(AbsExact().to_compare_f()),
+//         Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(CmpPerfTestFluid, CmpPerfTest,
+//     Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+//         Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(CmpWithScalarPerfTestFluid, CmpWithScalarPerfTest,
+    Combine(Values(AbsSimilarPoints(1, 0.01).to_compare_f()),
+            Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+            Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16SC1, CV_32FC1),
+            Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(BitwisePerfTestFluid, BitwisePerfTest,
+    Combine(Values(AND, OR, XOR),
+            testing::Bool(),
+            Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+            Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotPerfTestFluid, BitwiseNotPerfTest,
+    Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+            Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(SelectPerfTestFluid, SelectPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(MinPerfTestFluid, MinPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(MaxPerfTestFluid, MaxPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffPerfTestFluid, AbsDiffPerfTest,
+    Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+            Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffCPerfTestFluid, AbsDiffCPerfTest,
+    Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+            Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(SumPerfTestFluid, SumPerfTest,
+//     Combine(Values(AbsToleranceScalar(0.0).to_compare_f()),
+//         Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         //Values(0.0),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(AddWeightedPerfTestFluid, AddWeightedPerfTest,
+    Combine(Values(Tolerance_FloatRel_IntAbs(1e-6, 1).to_compare_f()),
+            Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+            Values(-1, CV_8U, CV_32F),
+            Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(AddWeightedPerfTestFluid_short, AddWeightedPerfTest,
+    Combine(Values(Tolerance_FloatRel_IntAbs(1e-6, 1).to_compare_f()),
+            Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(CV_16UC1, CV_16SC1),
+            Values(-1),
+            Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(NormPerfTestFluid, NormPerfTest,
+//     Combine(Values(AbsToleranceScalar(0.0).to_compare_f()),
+//         Values(NORM_INF, NORM_L1, NORM_L2),
+//         Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(IntegralPerfTestFluid, IntegralPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(ThresholdPerfTestFluid, ThresholdPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::THRESH_BINARY, cv::THRESH_BINARY_INV, cv::THRESH_TRUNC, cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(ThresholdPerfTestFluid, ThresholdOTPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1),
+//         Values(cv::THRESH_OTSU, cv::THRESH_TRIANGLE),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(InRangePerfTestFluid, InRangePerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(Split3PerfTestFluid, Split3PerfTest,
+    Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(Split4PerfTestFluid, Split4PerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(Merge3PerfTestFluid, Merge3PerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(Merge4PerfTestFluid, Merge4PerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(RemapPerfTestFluid, RemapPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(FlipPerfTestFluid, FlipPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(0, 1, -1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(CropPerfTestFluid, CropPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50)),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(CopyPerfTestFluid, CopyPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(ConcatHorPerfTestFluid, ConcatHorPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(ConcatHorVecPerfTestFluid, ConcatHorVecPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(ConcatVertPerfTestFluid, ConcatVertPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(ConcatVertVecPerfTestFluid, ConcatVertVecPerfTest,
+//     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(LUTPerfTestFluid, LUTPerfTest,
+//     Combine(Values(CV_8UC1, CV_8UC3),
+//         Values(CV_8UC1),
+//         Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+// INSTANTIATE_TEST_CASE_P(LUTPerfTestCustomFluid, LUTPerfTest,
+//     Combine(Values(CV_8UC3),
+//         Values(CV_8UC3),
+//         Values(szSmall128, szVGA, sz720p, sz1080p),
+//         Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(ConvertToPerfTestFluid, ConvertToPerfTest,
+    Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_f()),
+            Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
+            Values(CV_8U, CV_16U, CV_16S, CV_32F),
+            Values(szSmall128, szVGA, sz720p, sz1080p),
+            Values(2.5, 1.0),
+            Values(0.0),
+            Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(ResizePerfTestFluid, ResizePerfTest,
+    Combine(Values(AbsExact().to_compare_f()),
+        Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
+        Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
+        Values(szSmall128, szVGA, sz720p, sz1080p),
+        Values(cv::Size(64, 64),
+               cv::Size(30, 30)),
+        Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(ResizeFxFyPerfTestFluid, ResizeFxFyPerfTest,
+    Combine(Values(AbsExact().to_compare_f()),
+        Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
+        Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
+        Values(szSmall128, szVGA, sz720p, sz1080p),
+        Values(0.5, 0.1),
+        Values(0.5, 0.1),
+        Values(cv::compile_args(CORE_FLUID))));
+} // opencv_test
index b2e5b3d..4de1b18 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "../perf_precomp.hpp"
@@ -124,6 +124,24 @@ INSTANTIATE_TEST_CASE_P(SobelPerfTestCPU32F, SobelPerfTest,
         Values(1, 2),
         Values(cv::compile_args(IMGPROC_CPU))));
 
+INSTANTIATE_TEST_CASE_P(LaplacianPerfTestCPU, LaplacianPerfTest,
+                        Combine(Values(AbsExact().to_compare_f()),
+                                Values(CV_8UC1, CV_8UC3),
+                                Values(3),
+                                Values(szVGA, sz720p, sz1080p),
+                                Values(-1),
+                                Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BilateralFilterPerfTestCPU, BilateralFilterPerfTest,
+                        Combine(Values(AbsExact().to_compare_f()),
+                                Values(CV_32FC1, CV_32FC3),
+                                Values(-1),
+                                Values(szVGA, sz720p, sz1080p),
+                                Values(3),
+                                Values(20),
+                                Values(10),
+                                Values(cv::compile_args(IMGPROC_CPU))));
+
 INSTANTIATE_TEST_CASE_P(CannyPerfTestCPU, CannyPerfTest,
     Combine(Values(AbsExact().to_compare_f()),
         Values(CV_8UC1, CV_8UC3),
@@ -134,6 +152,28 @@ INSTANTIATE_TEST_CASE_P(CannyPerfTestCPU, CannyPerfTest,
         Values(true, false),
         Values(cv::compile_args(IMGPROC_CPU))));
 
+INSTANTIATE_TEST_CASE_P(GoodFeaturesPerfTestCPU, GoodFeaturesPerfTest,
+    Combine(Values(AbsExactVector<cv::Point2f>().to_compare_f()),
+            Values("cv/shared/pic5.png", "stitching/a1.png"),
+            Values(CV_32FC1, CV_8UC1),
+            Values(100, 500),
+            Values(0.1, 0.01),
+            Values(1.0),
+            Values(3, 5),
+            Values(true, false),
+            Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(GoodFeaturesInternalPerfTestCPU, GoodFeaturesPerfTest,
+    Combine(Values(AbsExactVector<cv::Point2f>().to_compare_f()),
+            Values("cv/cascadeandhog/images/audrybt1.png"),
+            Values(CV_32FC1, CV_8UC1),
+            Values(100),
+            Values(0.0000001),
+            Values(5.0),
+            Values(3),
+            Values(true),
+            Values(cv::compile_args(IMGPROC_CPU))));
+
 INSTANTIATE_TEST_CASE_P(EqHistPerfTestCPU, EqHistPerfTest,
     Combine(Values(AbsExact().to_compare_f()),
         Values(szVGA, sz720p, sz1080p),
@@ -198,4 +238,4 @@ INSTANTIATE_TEST_CASE_P(RGB2YUV422PerfTestCPU, RGB2YUV422PerfTest,
         Combine(Values(ToleranceColor(1e-3).to_compare_f()),
             Values(szVGA, sz720p, sz1080p),
             Values(cv::compile_args(IMGPROC_CPU))));
-}
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_video_perf_tests_cpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_video_perf_tests_cpu.cpp
new file mode 100644 (file)
index 0000000..4ad7163
--- /dev/null
@@ -0,0 +1,103 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+
+#include "../common/gapi_video_perf_tests.hpp"
+#include <opencv2/gapi/cpu/video.hpp>
+
+namespace
+{
+#define VIDEO_CPU cv::gapi::video::cpu::kernels()
+
+#ifdef HAVE_OPENCV_VIDEO
+#define WITH_VIDEO(X) X
+#else
+#define WITH_VIDEO(X) DISABLED_##X
+#endif // HAVE_OPENCV_VIDEO
+
+#define INSTANTIATE_TEST_CASE_MACRO_P(prefix, test_case_name, generator, ...) \
+    INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, __VA_ARGS__)
+} // namespace
+
+
+namespace opencv_test
+{
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidPerfTestCPU),
+                              BuildOptFlowPyramidPerfTest,
+                              Combine(Values("cv/optflow/rock_1.bmp",
+                                             "cv/optflow/frames/1080p_01.png"),
+                                      Values(7, 11),
+                                      Values(1000),
+                                      testing::Bool(),
+                                      Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
+                                      Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
+                                      testing::Bool(),
+                                      Values(cv::compile_args(VIDEO_CPU))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidInternalPerfTestCPU),
+                              BuildOptFlowPyramidPerfTest,
+                              Combine(Values("cv/optflow/rock_1.bmp"),
+                                      Values(15),
+                                      Values(3),
+                                      Values(true),
+                                      Values(BORDER_REFLECT_101),
+                                      Values(BORDER_CONSTANT),
+                                      Values(true),
+                                      Values(cv::compile_args(VIDEO_CPU))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKPerfTestCPU), OptFlowLKPerfTest,
+                              Combine(Values("cv/optflow/rock_%01d.bmp",
+                                             "cv/optflow/frames/1080p_%02d.png"),
+                                      Values(1, 3, 4),
+                                      Values(std::make_tuple(9, 9), std::make_tuple(15, 15)),
+                                      Values(7, 11),
+                                      Values(cv::TermCriteria(cv::TermCriteria::COUNT |
+                                                              cv::TermCriteria::EPS,
+                                                              30, 0.01)),
+                                      Values(cv::compile_args(VIDEO_CPU))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKForPyrPerfTestCPU), OptFlowLKForPyrPerfTest,
+                              Combine(Values("cv/optflow/rock_%01d.bmp",
+                                             "cv/optflow/frames/1080p_%02d.png"),
+                                      Values(1, 3, 4),
+                                      Values(std::make_tuple(9, 9), std::make_tuple(15, 15)),
+                                      Values(7, 11),
+                                      Values(cv::TermCriteria(cv::TermCriteria::COUNT |
+                                                              cv::TermCriteria::EPS,
+                                                              30, 0.01)),
+                                      Values(true, false),
+                                      Values(cv::compile_args(VIDEO_CPU))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKInternalPerfTestCPU),
+                              OptFlowLKForPyrPerfTest,
+                              Combine(Values("cv/optflow/rock_%01d.bmp"),
+                                      Values(1),
+                                      Values(std::make_tuple(10, 10)),
+                                      Values(15),
+                                      Values(cv::TermCriteria(cv::TermCriteria::COUNT |
+                                                              cv::TermCriteria::EPS,
+                                                              21, 0.05)),
+                                      Values(true),
+                                      Values(cv::compile_args(VIDEO_CPU))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelinePerfTestCPU),
+                              BuildPyr_CalcOptFlow_PipelinePerfTest,
+                              Combine(Values("cv/optflow/frames/1080p_%02d.png"),
+                                      Values(7, 11),
+                                      Values(1000),
+                                      Values(true, false),
+                                      Values(cv::compile_args(VIDEO_CPU))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelineInternalTestPerfCPU),
+                              BuildPyr_CalcOptFlow_PipelinePerfTest,
+                              Combine(Values("cv/optflow/rock_%01d.bmp"),
+                                      Values(15),
+                                      Values(3),
+                                      Values(true),
+                                      Values(cv::compile_args(VIDEO_CPU))));
+} // opencv_test
index 9c6b25c..0c5ff9e 100644 (file)
@@ -81,12 +81,10 @@ INSTANTIATE_TEST_CASE_P(DivRCPerfTestGPU, DivRCPerfTest,
                                 Values( -1, CV_8U, CV_16U, CV_32F ),
                                 Values(cv::compile_args(CORE_GPU))));
 //TODO: mask test doesn't work
-#if 0
-INSTANTIATE_TEST_CASE_P(MaskPerfTestGPU, MaskPerfTest,
+INSTANTIATE_TEST_CASE_P(DISABLED_MaskPerfTestGPU, MaskPerfTest,
                         Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
                                 Values( CV_8UC1, CV_16UC1, CV_16SC1),
                                 Values(cv::compile_args(CORE_GPU))));
-#endif
 
 INSTANTIATE_TEST_CASE_P(MeanPerfTestGPU, MeanPerfTest,
                         Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
@@ -110,13 +108,15 @@ INSTANTIATE_TEST_CASE_P(CmpPerfTestGPU, CmpPerfTest,
                                 Values(cv::compile_args(CORE_GPU))));
 
 INSTANTIATE_TEST_CASE_P(CmpWithScalarPerfTestGPU, CmpWithScalarPerfTest,
-                        Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+                        Combine(Values(AbsExact().to_compare_f()),
+                                Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
                                 Values( szSmall128, szVGA, sz720p, sz1080p ),
                                 Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
                                 Values(cv::compile_args(CORE_GPU))));
 
 INSTANTIATE_TEST_CASE_P(BitwisePerfTestGPU, BitwisePerfTest,
                         Combine(Values(AND, OR, XOR),
+                                testing::Bool(),
                                 Values( szSmall128, szVGA, sz720p, sz1080p ),
                                 Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
                                 Values(cv::compile_args(CORE_GPU))));
@@ -242,18 +242,16 @@ INSTANTIATE_TEST_CASE_P(ConcatVertPerfTestGPU, ConcatVertPerfTest,
                                 Values(cv::compile_args(CORE_GPU))));
 
 //TODO: fix this backend to allow ConcatVertVec ConcatHorVec
-#if 0
-INSTANTIATE_TEST_CASE_P(ConcatHorVecPerfTestGPU, ConcatHorVecPerfTest,
+INSTANTIATE_TEST_CASE_P(DISABLED_ConcatHorVecPerfTestGPU, ConcatHorVecPerfTest,
     Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
         Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
         Values(cv::compile_args(CORE_GPU))));
 
 
-INSTANTIATE_TEST_CASE_P(ConcatVertVecPerfTestGPU, ConcatVertVecPerfTest,
+INSTANTIATE_TEST_CASE_P(DISABLED_ConcatVertVecPerfTestGPU, ConcatVertVecPerfTest,
                         Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
                                 Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
                                 Values(cv::compile_args(CORE_GPU))));
-#endif
 
 INSTANTIATE_TEST_CASE_P(LUTPerfTestGPU, LUTPerfTest,
                         Combine(Values(CV_8UC1, CV_8UC3),
@@ -269,9 +267,12 @@ INSTANTIATE_TEST_CASE_P(LUTPerfTestCustomGPU, LUTPerfTest,
 
 
 INSTANTIATE_TEST_CASE_P(ConvertToPerfTestGPU, ConvertToPerfTest,
-                        Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
+                        Combine(Values(AbsExact().to_compare_f()),
+                                Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
                                 Values(CV_8U, CV_16U, CV_16S, CV_32F),
                                 Values( szSmall128, szVGA, sz720p, sz1080p ),
+                                Values(2.5, 1.0),
+                                Values(0.0),
                                 Values(cv::compile_args(CORE_GPU))));
 
 INSTANTIATE_TEST_CASE_P(ResizePerfTestGPU, ResizePerfTest,
index 1f4df17..1f4f388 100644 (file)
@@ -126,6 +126,24 @@ INSTANTIATE_TEST_CASE_P(SobelPerfTestGPU32F, SobelPerfTest,
                                 Values(1, 2),
                                 Values(cv::compile_args(IMGPROC_GPU))));
 
+INSTANTIATE_TEST_CASE_P(LaplacianPerfTestGPU, LaplacianPerfTest,
+                        Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+                                Values(CV_8UC1, CV_8UC3),
+                                Values(5),
+                                Values(szVGA, sz720p, sz1080p),
+                                Values(-1),
+                                Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BilateralFilterPerfTestGPU, BilateralFilterPerfTest,
+                        Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+                                Values(CV_32FC1, CV_32FC3),
+                                Values(-1),
+                                Values(szVGA, sz720p, sz1080p),
+                                Values(5),
+                                Values(100),
+                                Values(40),
+                                Values(cv::compile_args(IMGPROC_GPU))));
+
 INSTANTIATE_TEST_CASE_P(CannyPerfTestGPU, CannyPerfTest,
                         Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
                                 Values(CV_8UC1, CV_8UC3),
index bf19532..44b9dc7 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef __OPENCV_GAPI_PERF_PRECOMP_HPP__
@@ -14,6 +14,7 @@
 #include <opencv2/ts.hpp>
 #include <opencv2/gapi.hpp>
 #include <opencv2/gapi/imgproc.hpp>
+#include <opencv2/gapi/video.hpp>
 #include <opencv2/gapi/core.hpp>
 #include <opencv2/gapi/cpu/gcpukernel.hpp>
 #include <opencv2/gapi/gpu/ggpukernel.hpp>
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/render/gapi_render_perf_tests_ocv.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/render/gapi_render_perf_tests_ocv.cpp
new file mode 100644 (file)
index 0000000..2b51c08
--- /dev/null
@@ -0,0 +1,95 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+#include "../common/gapi_render_perf_tests.hpp"
+
+#define RENDER_OCV cv::gapi::render::ocv::kernels()
+
+namespace opencv_test
+{
+
+#ifdef HAVE_FREETYPE
+INSTANTIATE_TEST_CASE_P(RenderTestFTexts, RenderTestFTexts,
+                        Combine(Values(L"\xe4\xbd\xa0\xe5\xa5\xbd"),
+                                Values(szVGA, sz720p, sz1080p),
+                                Values(cv::Point(50, 50)),
+                                Values(60),
+                                Values(cv::Scalar(200, 100, 25)),
+                                Values(cv::compile_args(RENDER_OCV))));
+#endif // HAVE_FREETYPE
+
+INSTANTIATE_TEST_CASE_P(RenderTestTexts, RenderTestTexts,
+                        Combine(Values(std::string("Some text")),
+                                Values(szVGA, sz720p, sz1080p),
+                                Values(cv::Point(200, 200)),
+                                Values(FONT_HERSHEY_SIMPLEX),
+                                Values(cv::Scalar(0, 255, 0)),
+                                Values(2),
+                                Values(LINE_8),
+                                Values(false),
+                                Values(cv::compile_args(RENDER_OCV))));
+
+INSTANTIATE_TEST_CASE_P(RenderTestRects, RenderTestRects,
+                        Combine(Values(szVGA, sz720p, sz1080p),
+                                Values(cv::Rect(100, 100, 200, 200)),
+                                Values(cv::Scalar(100, 50, 150)),
+                                Values(2),
+                                Values(LINE_8),
+                                Values(0),
+                                Values(cv::compile_args(RENDER_OCV))));
+
+INSTANTIATE_TEST_CASE_P(RenderTestCircles, RenderTestCircles,
+                        Combine(Values(szVGA, sz720p, sz1080p),
+                                Values(cv::Point(100, 100)),
+                                Values(10),
+                                Values(cv::Scalar(100, 50, 150)),
+                                Values(2),
+                                Values(LINE_8),
+                                Values(0),
+                                Values(cv::compile_args(RENDER_OCV))));
+
+INSTANTIATE_TEST_CASE_P(RenderTestLines, RenderTestLines,
+                        Combine(Values(szVGA, sz720p, sz1080p),
+                                Values(cv::Point(100, 100)),
+                                Values(cv::Point(200, 200)),
+                                Values(cv::Scalar(100, 50, 150)),
+                                Values(2),
+                                Values(LINE_8),
+                                Values(0),
+                                Values(cv::compile_args(RENDER_OCV))));
+
+INSTANTIATE_TEST_CASE_P(RenderTestMosaics, RenderTestMosaics,
+                        Combine(Values(szVGA, sz720p, sz1080p),
+                                Values(cv::Rect(100, 100, 200, 200)),
+                                Values(25),
+                                Values(0),
+                                Values(cv::compile_args(RENDER_OCV))));
+
+INSTANTIATE_TEST_CASE_P(RenderTestImages, RenderTestImages,
+                        Combine(Values(szVGA, sz720p, sz1080p),
+                                Values(cv::Rect(50, 50, 100, 100)),
+                                Values(cv::Scalar(100, 150, 60)),
+                                Values(1.0),
+                                Values(cv::compile_args(RENDER_OCV))));
+
+INSTANTIATE_TEST_CASE_P(RenderTestPolylines, RenderTestPolylines,
+                        Combine(Values(szVGA, sz720p, sz1080p),
+                                Values(std::vector<cv::Point>{{100, 100}, {200, 200}, {150, 300}, {400, 150}}),
+                                Values(cv::Scalar(100, 150, 60)),
+                                Values(2),
+                                Values(LINE_8),
+                                Values(0),
+                                Values(cv::compile_args(RENDER_OCV))));
+
+INSTANTIATE_TEST_CASE_P(RenderTestPolyItems, RenderTestPolyItems,
+                        Combine(Values(szVGA, sz720p, sz1080p),
+                                Values(50),
+                                Values(50),
+                                Values(50),
+                                Values(cv::compile_args(RENDER_OCV))));
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/samples/dynamic_graph.cpp b/inference-engine/thirdparty/fluid/modules/gapi/samples/dynamic_graph.cpp
new file mode 100644 (file)
index 0000000..cb8022c
--- /dev/null
@@ -0,0 +1,68 @@
+#include <opencv2/gapi.hpp>
+#include <opencv2/gapi/core.hpp>
+#include <opencv2/gapi/cpu/core.hpp>
+
+int main(int argc, char *argv[])
+{
+    (void) argc;
+    (void) argv;
+
+    bool need_first_conversion  = true;
+    bool need_second_conversion = false;
+
+    cv::Size szOut(4, 4);
+    cv::GComputation cc([&](){
+// ! [GIOProtoArgs usage]
+        auto ins = cv::GIn();
+        cv::GMat in1;
+        if (need_first_conversion)
+            ins += cv::GIn(in1);
+
+        cv::GMat in2;
+        if (need_second_conversion)
+            ins += cv::GIn(in2);
+
+        auto outs = cv::GOut();
+        cv::GMat out1 = cv::gapi::resize(in1, szOut);
+        if (need_first_conversion)
+            outs += cv::GOut(out1);
+
+        cv::GMat out2 = cv::gapi::resize(in2, szOut);
+        if (need_second_conversion)
+            outs += cv::GOut(out2);
+// ! [GIOProtoArgs usage]
+        return cv::GComputation(std::move(ins), std::move(outs));
+    });
+
+// ! [GRunArgs usage]
+    auto in_vector = cv::gin();
+
+    cv::Mat in_mat1( 8,  8, CV_8UC3);
+    cv::Mat in_mat2(16, 16, CV_8UC3);
+    cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+    cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+
+    if (need_first_conversion)
+        in_vector += cv::gin(in_mat1);
+    if (need_second_conversion)
+        in_vector += cv::gin(in_mat2);
+// ! [GRunArgs usage]
+
+// ! [GRunArgsP usage]
+    auto out_vector = cv::gout();
+    cv::Mat out_mat1, out_mat2;
+    if (need_first_conversion)
+        out_vector += cv::gout(out_mat1);
+    if (need_second_conversion)
+        out_vector += cv::gout(out_mat2);
+// ! [GRunArgsP usage]
+
+    auto stream = cc.compileStreaming(cv::compile_args(cv::gapi::core::cpu::kernels()));
+    stream.setSource(std::move(in_vector));
+
+    stream.start();
+    stream.pull(std::move(out_vector));
+    stream.stop();
+
+    return 0;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/samples/gaze_estimation.cpp b/inference-engine/thirdparty/fluid/modules/gapi/samples/gaze_estimation.cpp
new file mode 100644 (file)
index 0000000..6396d50
--- /dev/null
@@ -0,0 +1,432 @@
+#include <algorithm>
+#include <iostream>
+#include <cctype>
+
+#include <opencv2/gapi.hpp>
+#include <opencv2/gapi/core.hpp>
+#include <opencv2/gapi/infer.hpp>
+#include <opencv2/gapi/infer/ie.hpp>
+#include <opencv2/gapi/streaming/cap.hpp>
+#include <opencv2/gapi/cpu/gcpukernel.hpp>
+#include <opencv2/highgui.hpp> // CommandLineParser
+
+const std::string about =
+    "This is an OpenCV-based version of Gaze Estimation example";
+const std::string keys =
+    "{ h help |                                    | Print this help message }"
+    "{ input  |                                    | Path to the input video file }"
+    "{ facem  | face-detection-retail-0005.xml     | Path to OpenVINO face detection model (.xml) }"
+    "{ faced  | CPU                                | Target device for the face detection (e.g. CPU, GPU, VPU, ...) }"
+    "{ landm  | facial-landmarks-35-adas-0002.xml  | Path to OpenVINO landmarks detector model (.xml) }"
+    "{ landd  | CPU                                | Target device for the landmarks detector (e.g. CPU, GPU, VPU, ...) }"
+    "{ headm  | head-pose-estimation-adas-0001.xml | Path to OpenVINO head pose estimation model (.xml) }"
+    "{ headd  | CPU                                | Target device for the head pose estimation inference (e.g. CPU, GPU, VPU, ...) }"
+    "{ gazem  | gaze-estimation-adas-0002.xml      | Path to OpenVINO gaze vector estimaiton model (.xml) }"
+    "{ gazed  | CPU                                | Target device for the gaze vector estimation inference (e.g. CPU, GPU, VPU, ...) }"
+    ;
+
+namespace {
+std::string weights_path(const std::string &model_path) {
+    const auto EXT_LEN = 4u;
+    const auto sz = model_path.size();
+    CV_Assert(sz > EXT_LEN);
+
+    auto ext   = model_path.substr(sz - EXT_LEN);
+    auto lower = [](unsigned char c) {
+        return static_cast<unsigned char>(std::tolower(c));
+    };
+    std::transform(ext.begin(), ext.end(), ext.begin(), lower);
+    CV_Assert(ext == ".xml");
+    return model_path.substr(0u, sz - EXT_LEN) + ".bin";
+}
+} // anonymous namespace
+
+namespace custom {
+namespace {
+using GMat3  = std::tuple<cv::GMat,cv::GMat,cv::GMat>;
+using GMats  = cv::GArray<cv::GMat>;
+using GRects = cv::GArray<cv::Rect>;
+using GSize  = cv::GOpaque<cv::Size>;
+G_API_NET(Faces,     <cv::GMat(cv::GMat)>, "face-detector"   );
+G_API_NET(Landmarks, <cv::GMat(cv::GMat)>, "facial-landmarks");
+G_API_NET(HeadPose,  <   GMat3(cv::GMat)>, "head-pose");
+G_API_NET(Gaze,      <cv::GMat(cv::GMat,cv::GMat,cv::GMat)>, "gaze-vector");
+
+G_API_OP(Size, <GSize(cv::GMat)>, "custom.gapi.size") {
+    static cv::GOpaqueDesc outMeta(const cv::GMatDesc &) {
+        return cv::empty_gopaque_desc();
+    }
+};
+
+G_API_OP(ParseSSD,
+         <GRects(cv::GMat, GSize, bool)>,
+         "custom.gaze_estimation.parseSSD") {
+    static cv::GArrayDesc outMeta( const cv::GMatDesc &
+                                 , const cv::GOpaqueDesc &
+                                 , bool) {
+        return cv::empty_array_desc();
+    }
+};
+
+// Left/Right eye per every face
+G_API_OP(ParseEyes,
+         <std::tuple<GRects, GRects>(GMats, GRects, GSize)>,
+         "custom.gaze_estimation.parseEyes") {
+    static std::tuple<cv::GArrayDesc, cv::GArrayDesc>
+        outMeta(  const cv::GArrayDesc &
+                , const cv::GArrayDesc &
+                , const cv::GOpaqueDesc &) {
+        return std::make_tuple(cv::empty_array_desc(), cv::empty_array_desc());
+    }
+};
+
+// Combine three scalars into a 1x3 vector (per every face)
+G_API_OP(ProcessPoses,
+         <GMats(GMats, GMats, GMats)>,
+         "custom.gaze_estimation.processPoses") {
+    static cv::GArrayDesc outMeta(  const cv::GArrayDesc &
+                                  , const cv::GArrayDesc &
+                                  , const cv::GArrayDesc &) {
+        return cv::empty_array_desc();
+    }
+};
+
+void adjustBoundingBox(cv::Rect& boundingBox) {
+    auto w = boundingBox.width;
+    auto h = boundingBox.height;
+
+    boundingBox.x -= static_cast<int>(0.067 * w);
+    boundingBox.y -= static_cast<int>(0.028 * h);
+
+    boundingBox.width += static_cast<int>(0.15 * w);
+    boundingBox.height += static_cast<int>(0.13 * h);
+
+    if (boundingBox.width < boundingBox.height) {
+        auto dx = (boundingBox.height - boundingBox.width);
+        boundingBox.x -= dx / 2;
+        boundingBox.width += dx;
+    } else {
+        auto dy = (boundingBox.width - boundingBox.height);
+        boundingBox.y -= dy / 2;
+        boundingBox.height += dy;
+    }
+}
+
+void gazeVectorToGazeAngles(const cv::Point3f& gazeVector,
+                                  cv::Point2f& gazeAngles) {
+    auto r = cv::norm(gazeVector);
+
+    double v0 = static_cast<double>(gazeVector.x);
+    double v1 = static_cast<double>(gazeVector.y);
+    double v2 = static_cast<double>(gazeVector.z);
+
+    gazeAngles.x = static_cast<float>(180.0 / M_PI * (M_PI_2 + std::atan2(v2, v0)));
+    gazeAngles.y = static_cast<float>(180.0 / M_PI * (M_PI_2 - std::acos(v1 / r)));
+}
+
+GAPI_OCV_KERNEL(OCVSize, Size) {
+    static void run(const cv::Mat &in, cv::Size &out) {
+        out = in.size();
+    }
+};
+
+GAPI_OCV_KERNEL(OCVParseSSD, ParseSSD) {
+    static void run(const cv::Mat &in_ssd_result,
+                    const cv::Size &upscale,
+                    const bool filter_out_of_bounds,
+                    std::vector<cv::Rect> &out_objects) {
+        const auto &in_ssd_dims = in_ssd_result.size;
+        CV_Assert(in_ssd_dims.dims() == 4u);
+
+        const int MAX_PROPOSALS = in_ssd_dims[2];
+        const int OBJECT_SIZE   = in_ssd_dims[3];
+        CV_Assert(OBJECT_SIZE  == 7); // fixed SSD object size
+
+        const cv::Rect surface({0,0}, upscale);
+        out_objects.clear();
+
+        const float *data = in_ssd_result.ptr<float>();
+        for (int i = 0; i < MAX_PROPOSALS; i++) {
+            const float image_id   = data[i * OBJECT_SIZE + 0];
+            const float label      = data[i * OBJECT_SIZE + 1];
+            const float confidence = data[i * OBJECT_SIZE + 2];
+            const float rc_left    = data[i * OBJECT_SIZE + 3];
+            const float rc_top     = data[i * OBJECT_SIZE + 4];
+            const float rc_right   = data[i * OBJECT_SIZE + 5];
+            const float rc_bottom  = data[i * OBJECT_SIZE + 6];
+            (void) label;
+            if (image_id < 0.f) {
+                break;    // marks end-of-detections
+            }
+            if (confidence < 0.5f) {
+                continue; // skip objects with low confidence
+            }
+            cv::Rect rc;  // map relative coordinates to the original image scale
+            rc.x      = static_cast<int>(rc_left   * upscale.width);
+            rc.y      = static_cast<int>(rc_top    * upscale.height);
+            rc.width  = static_cast<int>(rc_right  * upscale.width)  - rc.x;
+            rc.height = static_cast<int>(rc_bottom * upscale.height) - rc.y;
+            adjustBoundingBox(rc);                // TODO: new option?
+
+            const auto clipped_rc = rc & surface; // TODO: new option?
+            if (filter_out_of_bounds) {
+                if (clipped_rc.area() != rc.area()) {
+                    continue;
+                }
+            }
+            out_objects.emplace_back(clipped_rc);
+        }
+    }
+};
+
+cv::Rect eyeBox(const cv::Rect &face_rc,
+                float p1_x, float p1_y, float p2_x, float p2_y,
+                float scale = 1.8f) {
+    const auto &up = face_rc.size();
+    const cv::Point p1 = {
+        static_cast<int>(p1_x*up.width),
+        static_cast<int>(p1_y*up.height)
+    };
+    const cv::Point p2 = {
+        static_cast<int>(p2_x*up.width),
+        static_cast<int>(p2_y*up.height)
+    };
+    cv::Rect result;
+
+    const auto size     = static_cast<float>(cv::norm(p1 - p2));
+    const auto midpoint = (p1 + p2) / 2;
+
+    result.width = static_cast<int>(scale * size);
+    result.height = result.width;
+    result.x = face_rc.x + midpoint.x - (result.width / 2);
+    result.y = face_rc.y + midpoint.y - (result.height / 2);
+    // Shift result to the original frame's absolute coordinates
+    return result;
+}
+
+GAPI_OCV_KERNEL(OCVParseEyes, ParseEyes) {
+    static void run(const std::vector<cv::Mat> &in_landmarks_per_face,
+                    const std::vector<cv::Rect> &in_face_rcs,
+                    const cv::Size &frame_size,
+                    std::vector<cv::Rect> &out_left_eyes,
+                    std::vector<cv::Rect> &out_right_eyes) {
+        const size_t numFaces = in_landmarks_per_face.size();
+        const cv::Rect surface(cv::Point(0,0), frame_size);
+        GAPI_Assert(numFaces == in_face_rcs.size());
+        out_left_eyes.clear();
+        out_right_eyes.clear();
+        out_left_eyes.reserve(numFaces);
+        out_right_eyes.reserve(numFaces);
+
+        for (std::size_t i = 0u; i < numFaces; i++) {
+            const auto &lm = in_landmarks_per_face[i];
+            const auto &rc = in_face_rcs[i];
+            // Left eye is defined by points 0/1 (x2),
+            // Right eye is defined by points 2/3 (x2)
+            const float *data = lm.ptr<float>();
+            out_left_eyes .push_back(surface & eyeBox(rc, data[0], data[1], data[2], data[3]));
+            out_right_eyes.push_back(surface & eyeBox(rc, data[4], data[5], data[6], data[7]));
+        }
+    }
+};
+
+GAPI_OCV_KERNEL(OCVProcessPoses, ProcessPoses) {
+    static void run(const std::vector<cv::Mat> &in_ys,
+                    const std::vector<cv::Mat> &in_ps,
+                    const std::vector<cv::Mat> &in_rs,
+                    std::vector<cv::Mat> &out_poses) {
+        const std::size_t sz = in_ys.size();
+        GAPI_Assert(sz == in_ps.size() && sz == in_rs.size());
+        out_poses.clear();
+        for (std::size_t idx = 0u; idx < sz; idx++) {
+            cv::Mat pose(1, 3, CV_32FC1);
+            float *ptr = pose.ptr<float>();
+            ptr[0] = in_ys[idx].ptr<float>()[0];
+            ptr[1] = in_ps[idx].ptr<float>()[0];
+            ptr[2] = in_rs[idx].ptr<float>()[0];
+            out_poses.push_back(std::move(pose));
+        }
+    }
+};
+} // anonymous namespace
+} // namespace custom
+
+namespace vis {
+namespace {
+cv::Point2f midp(const cv::Rect &rc) {
+    return (rc.tl() + rc.br()) / 2;
+};
+void bbox(cv::Mat &m, const cv::Rect &rc) {
+    cv::rectangle(m, rc, cv::Scalar{0,255,0}, 2, cv::LINE_8, 0);
+};
+void pose(cv::Mat &m, const cv::Mat &p, const cv::Rect &face_rc) {
+    const auto *posePtr = p.ptr<float>();
+    const auto yaw   = static_cast<double>(posePtr[0]);
+    const auto pitch = static_cast<double>(posePtr[1]);
+    const auto roll  = static_cast<double>(posePtr[2]);
+
+    const auto sinY = std::sin(yaw   * M_PI / 180.0);
+    const auto sinP = std::sin(pitch * M_PI / 180.0);
+    const auto sinR = std::sin(roll  * M_PI / 180.0);
+
+    const auto cosY = std::cos(yaw   * M_PI / 180.0);
+    const auto cosP = std::cos(pitch * M_PI / 180.0);
+    const auto cosR = std::cos(roll  * M_PI / 180.0);
+
+    const auto axisLength = 0.4 * face_rc.width;
+    const auto xCenter = face_rc.x + face_rc.width  / 2;
+    const auto yCenter = face_rc.y + face_rc.height / 2;
+
+    const auto center = cv::Point{xCenter, yCenter};
+    const auto axisln = cv::Point2d{axisLength, axisLength};
+    const auto ctr    = cv::Matx<double,2,2>(cosR*cosY, sinY*sinP*sinR, 0.f,  cosP*sinR);
+    const auto ctt    = cv::Matx<double,2,2>(cosR*sinY*sinP, cosY*sinR, 0.f, -cosP*cosR);
+    const auto ctf    = cv::Matx<double,2,2>(sinY*cosP, 0.f, 0.f, sinP);
+
+    // center to right
+    cv::line(m, center, center + static_cast<cv::Point>(ctr*axisln), cv::Scalar(0, 0, 255), 2);
+    // center to top
+    cv::line(m, center, center + static_cast<cv::Point>(ctt*axisln), cv::Scalar(0, 255, 0), 2);
+    // center to forward
+    cv::line(m, center, center + static_cast<cv::Point>(ctf*axisln), cv::Scalar(255, 0, 255), 2);
+}
+void vvec(cv::Mat &m, const cv::Mat &v, const cv::Rect &face_rc,
+          const cv::Rect &left_rc, const cv::Rect &right_rc) {
+    const auto scale =  0.002 * face_rc.width;
+
+    cv::Point3f gazeVector;
+    const auto *gazePtr = v.ptr<float>();
+    gazeVector.x = gazePtr[0];
+    gazeVector.y = gazePtr[1];
+    gazeVector.z = gazePtr[2];
+    gazeVector = gazeVector / cv::norm(gazeVector);
+
+    const double arrowLength = 0.4 * face_rc.width;
+    const auto left_mid = midp(left_rc);
+    const auto right_mid = midp(right_rc);
+
+    cv::Point2f gazeArrow;
+    gazeArrow.x =  gazeVector.x;
+    gazeArrow.y = -gazeVector.y;
+    gazeArrow  *= arrowLength;
+
+    cv::arrowedLine(m, left_mid,  left_mid  + gazeArrow, cv::Scalar(255, 0, 0), 2);
+    cv::arrowedLine(m, right_mid, right_mid + gazeArrow, cv::Scalar(255, 0, 0), 2);
+
+    cv::Point2f gazeAngles;
+    custom::gazeVectorToGazeAngles(gazeVector, gazeAngles);
+
+    cv::putText(m,
+                cv::format("gaze angles: (h=%0.0f, v=%0.0f)",
+                           static_cast<double>(std::round(gazeAngles.x)),
+                           static_cast<double>(std::round(gazeAngles.y))),
+                cv::Point(static_cast<int>(face_rc.tl().x),
+                          static_cast<int>(face_rc.br().y + 12. * face_rc.width / 100.)),
+                cv::FONT_HERSHEY_PLAIN, scale * 2, cv::Scalar::all(255), 1);
+};
+} // anonymous namespace
+} // namespace vis
+
+int main(int argc, char *argv[])
+{
+    cv::CommandLineParser cmd(argc, argv, keys);
+    cmd.about(about);
+    if (cmd.has("help")) {
+        cmd.printMessage();
+        return 0;
+    }
+
+    cv::GMat in;
+    cv::GMat faces = cv::gapi::infer<custom::Faces>(in);
+    cv::GOpaque<cv::Size> sz = custom::Size::on(in); // FIXME
+    cv::GArray<cv::Rect> faces_rc = custom::ParseSSD::on(faces, sz, true);
+    cv::GArray<cv::GMat> angles_y, angles_p, angles_r;
+    std::tie(angles_y, angles_p, angles_r) = cv::gapi::infer<custom::HeadPose>(faces_rc, in);
+    cv::GArray<cv::GMat> heads_pos = custom::ProcessPoses::on(angles_y, angles_p, angles_r);
+    cv::GArray<cv::GMat> landmarks = cv::gapi::infer<custom::Landmarks>(faces_rc, in);
+    cv::GArray<cv::Rect> left_eyes, right_eyes;
+    std::tie(left_eyes, right_eyes) = custom::ParseEyes::on(landmarks, faces_rc, sz);
+    cv::GArray<cv::GMat> gaze_vectors = cv::gapi::infer2<custom::Gaze>( in
+                                                                      , left_eyes
+                                                                      , right_eyes
+                                                                      , heads_pos);
+    cv::GComputation graph(cv::GIn(in),
+                           cv::GOut( cv::gapi::copy(in)
+                                   , faces_rc
+                                   , left_eyes
+                                   , right_eyes
+                                   , heads_pos
+                                   , gaze_vectors));
+
+    const auto input_file_name = cmd.get<std::string>("input");
+    const auto face_model_path = cmd.get<std::string>("facem");
+    const auto head_model_path = cmd.get<std::string>("headm");
+    const auto lmrk_model_path = cmd.get<std::string>("landm");
+    const auto gaze_model_path = cmd.get<std::string>("gazem");
+
+    auto face_net = cv::gapi::ie::Params<custom::Faces> {
+        face_model_path,                // path to topology IR
+        weights_path(face_model_path),  // path to weights
+        cmd.get<std::string>("faced"),  /// device specifier
+    };
+    auto head_net = cv::gapi::ie::Params<custom::HeadPose> {
+        head_model_path,                // path to topology IR
+        weights_path(head_model_path),  // path to weights
+        cmd.get<std::string>("headd"),  // device specifier
+    }.cfgOutputLayers({"angle_y_fc", "angle_p_fc", "angle_r_fc"});
+    auto landmarks_net = cv::gapi::ie::Params<custom::Landmarks> {
+        lmrk_model_path,                // path to topology IR
+        weights_path(lmrk_model_path),  // path to weights
+        cmd.get<std::string>("landd"),  // device specifier
+    };
+    auto gaze_net = cv::gapi::ie::Params<custom::Gaze> {
+        gaze_model_path,                // path to topology IR
+        weights_path(gaze_model_path),  // path to weights
+        cmd.get<std::string>("gazed"),  // device specifier
+    }.cfgInputLayers({"left_eye_image", "right_eye_image", "head_pose_angles"});
+
+    auto kernels = cv::gapi::kernels< custom::OCVSize
+                                    , custom::OCVParseSSD
+                                    , custom::OCVParseEyes
+                                    , custom::OCVProcessPoses>();
+    auto networks = cv::gapi::networks(face_net, head_net, landmarks_net, gaze_net);
+    auto pipeline = graph.compileStreaming(cv::compile_args(networks, kernels));
+
+    cv::TickMeter tm;
+    cv::Mat image;
+    std::vector<cv::Rect> out_faces, out_right_eyes, out_left_eyes;
+    std::vector<cv::Mat> out_poses;
+    std::vector<cv::Mat> out_gazes;
+    std::size_t frames = 0u;
+    std::cout << "Reading " << input_file_name << std::endl;
+
+    pipeline.setSource(cv::gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(input_file_name));
+    pipeline.start();
+    tm.start();
+    while (pipeline.pull(cv::gout( image
+                                 , out_faces
+                                 , out_left_eyes
+                                 , out_right_eyes
+                                 , out_poses
+                                 , out_gazes))) {
+        frames++;
+        // Visualize results on the frame
+        for (auto &&rc : out_faces) vis::bbox(image, rc);
+        for (auto &&rc : out_left_eyes) vis::bbox(image, rc);
+        for (auto &&rc : out_right_eyes) vis::bbox(image, rc);
+        for (std::size_t i = 0u; i < out_faces.size(); i++) {
+            vis::pose(image, out_poses[i], out_faces[i]);
+            vis::vvec(image, out_gazes[i], out_faces[i], out_left_eyes[i], out_right_eyes[i]);
+        }
+        tm.stop();
+        const auto fps_str = std::to_string(frames / tm.getTimeSec()) + " FPS";
+        cv::putText(image, fps_str, {0,32}, cv::FONT_HERSHEY_SIMPLEX, 1.0, {0,255,0}, 2);
+        cv::imshow("Out", image);
+        cv::waitKey(1);
+        tm.start();
+    }
+    tm.stop();
+    std::cout << "Processed " << frames << " frames"
+              << " (" << frames / tm.getTimeSec() << " FPS)" << std::endl;
+    return 0;
+}
index d16a1b9..6e8411c 100644 (file)
@@ -21,7 +21,7 @@ const std::string keys =
     "{ input  |                                                  | Path to the input video file }"
     "{ platm  | vehicle-license-plate-detection-barrier-0106.xml | Path to OpenVINO IE vehicle/plate detection model (.xml) }"
     "{ platd  | CPU                                              | Target device for vehicle/plate detection model (e.g. CPU, GPU, VPU, ...) }"
-    "{ facem  | face-detection-adas-0001.xml                     | Path to OpenVINO IE face detection model (.xml) }"
+    "{ facem  | face-detection-retail-0005.xml                   | Path to OpenVINO IE face detection model (.xml) }"
     "{ faced  | CPU                                              | Target device for face detection model (e.g. CPU, GPU, VPU, ...) }"
     "{ trad   | false                                            | Run processing in a traditional (non-pipelined) way }"
     "{ noshow | false                                            | Don't display UI (improves performance) }";
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/scripts/measure_privacy_masking.py b/inference-engine/thirdparty/fluid/modules/gapi/scripts/measure_privacy_masking.py
new file mode 100755 (executable)
index 0000000..fdb5691
--- /dev/null
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+
+import sys
+import subprocess
+import re
+from enum import Enum
+
+## Helper functions ##################################################
+##
+def fmt_bool(x):
+    return ("true" if x else "false")
+
+def fmt_bin(base, prec, model):
+    return "%s/%s/%s/%s.xml" % (base, model, prec, model)
+
+## The script itself #################################################
+##
+if len(sys.argv) != 3:
+    print("Usage: %s /path/to/input/video /path/to/models" % sys.argv[0])
+    exit(1)
+
+input_file_path   = sys.argv[1]
+intel_models_path = sys.argv[2]
+
+app             = "bin/example_gapi_privacy_masking_camera"
+intel_fd_model  = "face-detection-retail-0005"
+intel_lpd_model = "vehicle-license-plate-detection-barrier-0106"
+output_file     = "out_results.csv"
+
+tgts = [ ("CPU", "INT8")
+       , ("CPU", "FP32")
+       , ("GPU", "FP16")
+       ]
+
+class Policy(Enum):
+    Traditional = 1
+    Streaming   = 2
+
+# From mode to cmd arg
+mods = [ (Policy.Traditional, True)
+       , (Policy.Streaming,  False)
+       ]
+
+class UI(Enum):
+    With    = 1
+    Without = 2
+
+# From mode to cmd arg
+ui = [ (UI.With,   False)
+     , (UI.Without, True)
+     ]
+
+fd_fmt_bin  = lambda prec : fmt_bin(intel_models_path, prec, intel_fd_model)
+lpd_fmt_bin = lambda prec : fmt_bin(intel_models_path, prec, intel_lpd_model)
+
+# Performance comparison table
+table={}
+
+# Collect the performance data
+for m in mods:              # Execution mode (trad/stream)
+    for u in ui:            # UI mode (on/off)
+        for f in tgts:      # FD model
+            for p in tgts:  # LPD model
+                cmd = [ app
+                      , ("--input=%s"  % input_file_path)   # input file
+                      , ("--faced=%s"  % f[0])              # FD device target
+                      , ("--facem=%s"  % fd_fmt_bin(f[1]))  # FD model @ precision
+                      , ("--platd=%s"  % p[0])              # LPD device target
+                      , ("--platm=%s"  % lpd_fmt_bin(p[1])) # LPD model @ precision
+                      , ("--trad=%s"   % fmt_bool(m[1]))    # Execution policy
+                      , ("--noshow=%s" % fmt_bool(u[1]))    # UI mode (show/no show)
+                      ]
+                out = str(subprocess.check_output(cmd))
+                match = re.search('Processed [0-9]+ frames \(([0-9]+\.[0-9]+) FPS\)', out)
+                fps = float(match.group(1))
+                print(cmd, fps, "FPS")
+                table[m[0],u[0],f,p] = fps
+
+# Write the performance summary
+# Columns: all other components (mode, ui)
+with open(output_file, 'w') as csv:
+    # CSV header
+    csv.write("FD,LPD,Serial(UI),Serial(no-UI),Streaming(UI),Streaming(no-UI),Effect(UI),Effect(no-UI)\n")
+
+    for f in tgts:      # FD model
+        for p in tgts:  # LPD model
+            row = "%s/%s,%s/%s" % (f[0], f[1], p[0], p[1])                # FD precision, LPD precision
+            row += ",%f"    % table[Policy.Traditional,UI.With,   f,p]    # Serial/UI
+            row += ",%f"    % table[Policy.Traditional,UI.Without,f,p]    # Serial/no UI
+            row += ",%f"    % table[Policy.Streaming,  UI.With,   f,p]    # Streaming/UI
+            row += ",%f"    % table[Policy.Streaming,  UI.Without,f,p]    # Streaming/no UI
+
+            effect_ui   = table[Policy.Streaming,UI.With,   f,p] / table[Policy.Traditional,UI.With,   f,p]
+            effect_noui = table[Policy.Streaming,UI.Without,f,p] / table[Policy.Traditional,UI.Without,f,p]
+            row += ",%f,%f" % (effect_ui,effect_noui)
+            row += "\n"
+            csv.write(row)
+
+print("DONE: ", output_file)
index bdd46b9..7d3dca3 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -20,6 +20,11 @@ cv::detail::GArrayU::GArrayU(const GNode &n, std::size_t out)
 {
 }
 
+cv::detail::GArrayU::GArrayU(const detail::VectorRef& vref)
+    : m_priv(new GOrigin(GShape::GARRAY, cv::gimpl::ConstVal(vref)))
+{
+}
+
 cv::GOrigin& cv::detail::GArrayU::priv()
 {
     return *m_priv;
@@ -35,6 +40,11 @@ void cv::detail::GArrayU::setConstructFcn(ConstructVec &&cv)
     m_priv->ctor = std::move(cv);
 }
 
+void cv::detail::GArrayU::setKind(cv::detail::OpaqueKind kind)
+{
+    m_priv->kind = kind;
+}
+
 namespace cv {
 std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &)
 {
index 24281ba..cc0b1a9 100644 (file)
@@ -10,7 +10,6 @@
 #include <functional> // multiplies
 
 #include <opencv2/gapi/gkernel.hpp>
-#include <opencv2/gapi/own/convert.hpp>
 
 #include "api/gbackend_priv.hpp"
 #include "backends/common/gbackend.hpp"
@@ -114,36 +113,22 @@ void bindInArg(Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat)
     {
         switch (arg.index())
         {
-        case GRunArg::index_of<cv::gapi::own::Mat>() :
+        case GRunArg::index_of<cv::Mat>() :
             if (is_umat)
             {
 #if !defined(GAPI_STANDALONE)
                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
-                mag_umat = to_ocv(util::get<cv::gapi::own::Mat>(arg)).getUMat(ACCESS_READ);
+                mag_umat = util::get<cv::Mat>(arg).getUMat(ACCESS_READ);
 #else
                 util::throw_error(std::logic_error("UMat is not supported in standalone build"));
 #endif // !defined(GAPI_STANDALONE)
             }
             else
             {
-                auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
-                mag_mat = util::get<cv::gapi::own::Mat>(arg);
+                auto& mag_mat = mag.template slot<cv::Mat>()[rc.id];
+                mag_mat = util::get<cv::Mat>(arg);
             }
             break;
-#if !defined(GAPI_STANDALONE)
-        case GRunArg::index_of<cv::Mat>() :
-            if (is_umat)
-            {
-                auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
-                mag_umat = util::get<cv::Mat>(arg).getUMat(ACCESS_READ);
-            }
-            else
-            {
-                auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
-                mag_mat = to_own(util::get<cv::Mat>(arg));
-            }
-            break;
-#endif //  !defined(GAPI_STANDALONE)
         default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
         }
         break;
@@ -182,36 +167,22 @@ void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat)
     {
         switch (arg.index())
         {
-        case GRunArgP::index_of<cv::gapi::own::Mat*>() :
+        case GRunArgP::index_of<cv::Mat*>() :
             if (is_umat)
             {
 #if !defined(GAPI_STANDALONE)
                 auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
-                mag_umat = to_ocv(*(util::get<cv::gapi::own::Mat*>(arg))).getUMat(ACCESS_RW);
+                mag_umat = util::get<cv::Mat*>(arg)->getUMat(ACCESS_RW);
 #else
                 util::throw_error(std::logic_error("UMat is not supported in standalone build"));
 #endif // !defined(GAPI_STANDALONE)
             }
             else
             {
-                auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
-                mag_mat = *util::get<cv::gapi::own::Mat*>(arg);
+                auto& mag_mat = mag.template slot<cv::Mat>()[rc.id];
+                mag_mat = *util::get<cv::Mat*>(arg);
             }
             break;
-#if !defined(GAPI_STANDALONE)
-        case GRunArgP::index_of<cv::Mat*>() :
-            if (is_umat)
-            {
-                auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
-                mag_umat = util::get<cv::Mat*>(arg)->getUMat(ACCESS_RW);
-            }
-            else
-            {
-                auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
-                mag_mat = to_own(*util::get<cv::Mat*>(arg));
-            }
-            break;
-#endif //  !defined(GAPI_STANDALONE)
         default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
         }
         break;
@@ -277,7 +248,7 @@ cv::GRunArg getArg(const Mag& mag, const RcDesc &ref)
     // Wrap associated CPU object (either host or an internal one)
     switch (ref.shape)
     {
-    case GShape::GMAT:    return GRunArg(mag.template slot<cv::gapi::own::Mat>().at(ref.id));
+    case GShape::GMAT:    return GRunArg(mag.template slot<cv::Mat>().at(ref.id));
     case GShape::GSCALAR: return GRunArg(mag.template slot<cv::Scalar>().at(ref.id));
     // Note: .at() is intentional for GArray and GOpaque as objects MUST be already there
     //   (and constructed by either bindIn/Out or resetInternal)
@@ -303,7 +274,7 @@ cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat)
 #endif //  !defined(GAPI_STANDALONE)
         }
         else
-            return GRunArgP(&mag.template slot<cv::gapi::own::Mat>()[rc.id]);
+            return GRunArgP(&mag.template slot<cv::Mat>()[rc.id]);
     case GShape::GSCALAR: return GRunArgP(&mag.template slot<cv::Scalar>()[rc.id]);
     // Note: .at() is intentional for GArray and GOpaque as objects MUST be already there
     //   (and constructor by either bindIn/Out or resetInternal)
@@ -347,10 +318,9 @@ void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
         uchar* out_arg_data = nullptr;
         switch (g_arg.index())
         {
-            case GRunArgP::index_of<cv::gapi::own::Mat*>() : out_arg_data = util::get<cv::gapi::own::Mat*>(g_arg)->data; break;
+            case GRunArgP::index_of<cv::Mat*>() : out_arg_data = util::get<cv::Mat*>(g_arg)->data; break;
 #if !defined(GAPI_STANDALONE)
-            case GRunArgP::index_of<cv::Mat*>()            : out_arg_data = util::get<cv::Mat*>(g_arg)->data; break;
-            case GRunArgP::index_of<cv::UMat*>()           : out_arg_data = (util::get<cv::UMat*>(g_arg))->getMat(ACCESS_RW).data; break;
+            case GRunArgP::index_of<cv::UMat*>() : out_arg_data = (util::get<cv::UMat*>(g_arg))->getMat(ACCESS_RW).data; break;
 #endif //  !defined(GAPI_STANDALONE)
             default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
         }
@@ -365,7 +335,7 @@ void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
         }
         else
         {
-            auto& in_mag = mag.template slot<cv::gapi::own::Mat>().at(rc.id);
+            auto& in_mag = mag.template slot<cv::Mat>().at(rc.id);
             GAPI_Assert((out_arg_data == in_mag.data) && " data for output parameters was reallocated ?");
         }
         break;
@@ -389,24 +359,6 @@ void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
 
 } // namespace magazine
 
-void createMat(const cv::GMatDesc &desc, cv::gapi::own::Mat& mat)
-{
-    // FIXME: Refactor (probably start supporting N-Dimensional blobs natively
-    if (desc.dims.empty())
-    {
-        const auto type = desc.planar ? desc.depth : CV_MAKETYPE(desc.depth, desc.chan);
-        const auto size = desc.planar ? cv::Size{desc.size.width, desc.size.height*desc.chan}
-                                      : desc.size;
-        mat.create(size, type);
-    }
-    else
-    {
-        GAPI_Assert(!desc.planar);
-        mat.create(desc.dims, desc.depth);
-    }
-}
-
-#if !defined(GAPI_STANDALONE)
 void createMat(const cv::GMatDesc &desc, cv::Mat& mat)
 {
     // FIXME: Refactor (probably start supporting N-Dimensional blobs natively
@@ -423,7 +375,6 @@ void createMat(const cv::GMatDesc &desc, cv::Mat& mat)
         mat.create(desc.dims, desc.depth);
     }
 }
-#endif
 
 } // namespace gimpl
 } // namespace cv
index 18ca53b..60119f7 100644 (file)
@@ -56,19 +56,38 @@ cv::GComputation::GComputation(const std::vector<GMat> &ins,
                                const std::vector<GMat> &outs)
     : m_priv(new Priv())
 {
+    Priv::Expr e;
     const auto wrap = [](cv::GMat m) { return GProtoArg(m); };
-    ade::util::transform(ins,  std::back_inserter(m_priv->m_ins),  wrap);
-    ade::util::transform(outs, std::back_inserter(m_priv->m_outs), wrap);
+    ade::util::transform(ins,  std::back_inserter(e.m_ins),  wrap);
+    ade::util::transform(outs, std::back_inserter(e.m_outs), wrap);
+    m_priv->m_shape = std::move(e);
 }
 
 cv::GComputation::GComputation(cv::GProtoInputArgs &&ins,
                                cv::GProtoOutputArgs &&outs)
     : m_priv(new Priv())
 {
-    m_priv->m_ins  = std::move(ins.m_args);
-    m_priv->m_outs = std::move(outs.m_args);
+    m_priv->m_shape = Priv::Expr{
+          std::move(ins.m_args)
+        , std::move(outs.m_args)
+    };
 }
 
+cv::GComputation::GComputation(cv::gimpl::s11n::I::IStream &is)
+    : m_priv(new Priv())
+{
+    m_priv->m_shape = gimpl::s11n::deserialize(is);
+}
+
+void cv::GComputation::serialize(cv::gimpl::s11n::I::OStream &os) const
+{
+    // Build a basic GModel and write the whole thing to the stream
+    auto pG = cv::gimpl::GCompiler::makeGraph(*m_priv);
+    std::vector<ade::NodeHandle> nhs(pG->nodes().begin(), pG->nodes().end());
+    gimpl::s11n::serialize(os, *pG, nhs);
+}
+
+
 cv::GCompiled cv::GComputation::compile(GMetaArgs &&metas, GCompileArgs &&args)
 {
     // FIXME: Cache gcompiled per parameters here?
@@ -132,16 +151,16 @@ void cv::GComputation::apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&ar
     m_priv->m_lastCompiled(std::move(ins), std::move(outs));
 }
 
-void cv::GComputation::apply(const std::vector<cv::gapi::own::Mat> &ins,
-                             const std::vector<cv::gapi::own::Mat> &outs,
+void cv::GComputation::apply(const std::vector<cv::Mat> &ins,
+                             const std::vector<cv::Mat> &outs,
                              GCompileArgs &&args)
 {
     GRunArgs call_ins;
     GRunArgsP call_outs;
 
     auto tmp = outs;
-    for (const cv::gapi::own::Mat &m : ins) { call_ins.emplace_back(m);   }
-    for (      cv::gapi::own::Mat &m : tmp) { call_outs.emplace_back(&m); }
+    for (const cv::Mat &m : ins) { call_ins.emplace_back(m);   }
+    for (      cv::Mat &m : tmp) { call_outs.emplace_back(&m); }
 
     apply(std::move(call_ins), std::move(call_outs), std::move(args));
 }
index 13d1b9a..c3160b4 100644 (file)
@@ -8,20 +8,37 @@
 #ifndef OPENCV_GAPI_GCOMPUTATION_PRIV_HPP
 #define OPENCV_GAPI_GCOMPUTATION_PRIV_HPP
 
+#include <ade/graph.hpp>
+
+#include "opencv2/gapi/util/variant.hpp"
+
 #include "opencv2/gapi.hpp"
 #include "opencv2/gapi/gcall.hpp"
 
 #include "opencv2/gapi/util/variant.hpp"
 
+#include "backends/common/serialization.hpp"
+
 namespace cv {
 
 class GComputation::Priv
 {
 public:
+    struct Expr {
+        cv::GProtoArgs m_ins;
+        cv::GProtoArgs m_outs;
+    };
+
+    using Dump = cv::gimpl::s11n::GSerialized;
+
+    using Shape = cv::util::variant
+        < Expr    // An expression-based graph
+        , Dump    // A deserialized graph
+        >;
+
     GCompiled   m_lastCompiled;
     GMetaArgs   m_lastMetas; // TODO: make GCompiled remember its metas?
-    GProtoArgs  m_ins;
-    GProtoArgs  m_outs;
+    Shape       m_shape;
 };
 
 }
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gframe.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gframe.cpp
new file mode 100644 (file)
index 0000000..405924b
--- /dev/null
@@ -0,0 +1,41 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <opencv2/gapi/gframe.hpp>
+
+#include "api/gorigin.hpp"
+
+// cv::GFrame public implementation //////////////////////////////////////////////
+cv::GFrame::GFrame()
+    : m_priv(new GOrigin(GShape::GMAT, GNode::Param())) {
+    // N.B.: The shape here is still GMAT as currently cv::Mat is used
+    // as an underlying host type. Will be changed to GFRAME once
+    // GExecutor & GStreamingExecutor & selected backends will be extended
+    // to support cv::MediaFrame.
+}
+
+cv::GFrame::GFrame(const GNode &n, std::size_t out)
+    : m_priv(new GOrigin(GShape::GMAT, n, out)) {
+    // N.B.: GMAT is here for the same reason as above ^
+}
+
+cv::GOrigin& cv::GFrame::priv() {
+    return *m_priv;
+}
+
+const cv::GOrigin& cv::GFrame::priv() const {
+    return *m_priv;
+}
+
+namespace cv {
+std::ostream& operator<<(std::ostream& os, const cv::GFrameDesc &) {
+    return os;
+}
+
+} // namespace cv
index a108c51..de33c39 100644 (file)
@@ -48,7 +48,6 @@ namespace{
     }
 }
 
-
 #if !defined(GAPI_STANDALONE)
 cv::GMatDesc cv::descr_of(const cv::Mat &mat)
 {
@@ -64,16 +63,20 @@ cv::GMatDesc cv::descr_of(const cv::Mat &mat)
     }
     return GMatDesc{mat.depth(), std::move(dims)};
 }
+#endif
 
-cv::GMatDesc cv::descr_of(const cv::UMat &mat)
+cv::GMatDesc cv::gapi::own::descr_of(const Mat &mat)
 {
-    GAPI_Assert(mat.size.dims() == 2);
-    return GMatDesc{ mat.depth(), mat.channels(),{ mat.cols, mat.rows } };
+    return (mat.dims.empty())
+        ? GMatDesc{mat.depth(), mat.channels(), {mat.cols, mat.rows}}
+        : GMatDesc{mat.depth(), mat.dims};
 }
 
-cv::GMetaArgs cv::descrs_of(const std::vector<cv::Mat> &vec)
+#if !defined(GAPI_STANDALONE)
+cv::GMatDesc cv::descr_of(const cv::UMat &mat)
 {
-    return vec_descr_of(vec);
+    GAPI_Assert(mat.size.dims() == 2);
+    return GMatDesc{ mat.depth(), mat.channels(),{ mat.cols, mat.rows } };
 }
 
 cv::GMetaArgs cv::descrs_of(const std::vector<cv::UMat> &vec)
@@ -82,14 +85,12 @@ cv::GMetaArgs cv::descrs_of(const std::vector<cv::UMat> &vec)
 }
 #endif
 
-cv::GMatDesc cv::gapi::own::descr_of(const cv::gapi::own::Mat &mat)
+cv::GMetaArgs cv::descrs_of(const std::vector<cv::Mat> &vec)
 {
-    return (mat.dims.empty())
-        ? GMatDesc{mat.depth(), mat.channels(), {mat.cols, mat.rows}}
-        : GMatDesc{mat.depth(), mat.dims};
+    return vec_descr_of(vec);
 }
 
-cv::GMetaArgs cv::gapi::own::descrs_of(const std::vector<cv::gapi::own::Mat> &vec)
+cv::GMetaArgs cv::gapi::own::descrs_of(const std::vector<Mat> &vec)
 {
     return vec_descr_of(vec);
 }
@@ -126,21 +127,14 @@ std::ostream& operator<<(std::ostream& os, const cv::GMatDesc &desc)
 namespace {
 template<typename M> inline bool canDescribeHelper(const GMatDesc& desc, const M& mat)
 {
-    const auto mat_desc = desc.planar ? descr_of(mat).asPlanar(desc.chan) : descr_of(mat);
+    const auto mat_desc = desc.planar ? cv::descr_of(mat).asPlanar(desc.chan) : cv::descr_of(mat);
     return desc == mat_desc;
 }
 } // anonymous namespace
 
-bool GMatDesc::canDescribe(const cv::gapi::own::Mat& mat) const
-{
-    return canDescribeHelper(*this, mat);
-}
-
-#if !defined(GAPI_STANDALONE)
 bool GMatDesc::canDescribe(const cv::Mat& mat) const
 {
     return canDescribeHelper(*this, mat);
 }
-#endif
 
 }// namespace cv
index 9dff6e7..71bf1bc 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2019 Intel Corporation
+// Copyright (C) 2019-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -35,6 +35,11 @@ void cv::detail::GOpaqueU::setConstructFcn(ConstructOpaque &&co)
     m_priv->ctor = std::move(co);
 }
 
+void cv::detail::GOpaqueU::setKind(cv::detail::OpaqueKind kind)
+{
+    m_priv->kind = kind;
+}
+
 namespace cv {
 std::ostream& operator<<(std::ostream& os, const cv::GOpaqueDesc &)
 {
index 312d614..e7b4389 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
 cv::GOrigin::GOrigin(GShape s,
                     const cv::GNode& n,
                     std::size_t p,
-                    const cv::gimpl::HostCtor c)
-    : shape(s), node(n), port(p), ctor(c)
+                    const cv::gimpl::HostCtor c,
+                    cv::detail::OpaqueKind k)
+    : shape(s), node(n), port(p), ctor(c), kind(k)
 {
 }
 
 cv::GOrigin::GOrigin(GShape s, cv::gimpl::ConstVal v)
-    : shape(s), node(cv::GNode::Const()), value(v), port(INVALID_PORT)
+    : shape(s), node(cv::GNode::Const()), value(v), port(INVALID_PORT),
+      kind(util::holds_alternative<detail::VectorRef>(v)
+               ? util::get<detail::VectorRef>(v).getKind()
+               : cv::detail::OpaqueKind::CV_UNKNOWN)
 {
 }
 
index 7129b2f..2f01544 100644 (file)
@@ -2,8 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
-
+// Copyright (C) 2018-2020 Intel Corporation
 
 #ifndef OPENCV_GAPI_GORIGIN_HPP
 #define OPENCV_GAPI_GORIGIN_HPP
@@ -30,7 +29,8 @@ struct GOrigin
     GOrigin(GShape s,
             const GNode& n,
             std::size_t p = INVALID_PORT,
-            const gimpl::HostCtor h = {});
+            const gimpl::HostCtor h = {},
+            cv::detail::OpaqueKind kind = cv::detail::OpaqueKind::CV_UNKNOWN);
     GOrigin(GShape s, gimpl::ConstVal value);
 
     const GShape          shape;           // Shape of a produced object
@@ -38,6 +38,7 @@ struct GOrigin
     const gimpl::ConstVal value;           // Node can have initial constant value, now only scalar is supported
     const std::size_t     port;            // GNode's output number; FIXME: "= max_size" in C++14
     gimpl::HostCtor       ctor;            // FIXME: replace with an interface?
+    detail::OpaqueKind    kind;            // primary is needed for GOpaque and GArray
 };
 
 namespace detail
index d6a68d5..ef5162a 100644 (file)
@@ -28,6 +28,9 @@ const cv::GOrigin& cv::gimpl::proto::origin_of(const cv::GProtoArg &arg)
     case cv::GProtoArg::index_of<cv::GMatP>():
         return util::get<cv::GMatP>(arg).priv();
 
+    case cv::GProtoArg::index_of<cv::GFrame>():
+        return util::get<cv::GFrame>(arg).priv();
+
     case cv::GProtoArg::index_of<cv::GScalar>():
         return util::get<cv::GScalar>(arg).priv();
 
@@ -60,6 +63,7 @@ bool cv::gimpl::proto::is_dynamic(const cv::GArg& arg)
     {
     case detail::ArgKind::GMAT:
     case detail::ArgKind::GMATP:
+    case detail::ArgKind::GFRAME:
     case detail::ArgKind::GSCALAR:
     case detail::ArgKind::GARRAY:
     case detail::ArgKind::GOPAQUE:
@@ -75,6 +79,7 @@ cv::GRunArg cv::value_of(const cv::GOrigin &origin)
     switch (origin.shape)
     {
     case GShape::GSCALAR: return GRunArg(util::get<cv::Scalar>(origin.value));
+    case GShape::GARRAY:  return GRunArg(util::get<cv::detail::VectorRef>(origin.value));
     default: util::throw_error(std::logic_error("Unsupported shape for constant"));
     }
 }
@@ -87,9 +92,10 @@ cv::GProtoArg cv::gimpl::proto::rewrap(const cv::GArg &arg)
     {
     case detail::ArgKind::GMAT:    return GProtoArg(arg.get<cv::GMat>());
     case detail::ArgKind::GMATP:   return GProtoArg(arg.get<cv::GMatP>());
+    case detail::ArgKind::GFRAME:  return GProtoArg(arg.get<cv::GFrame>());
     case detail::ArgKind::GSCALAR: return GProtoArg(arg.get<cv::GScalar>());
     case detail::ArgKind::GARRAY:  return GProtoArg(arg.get<cv::detail::GArrayU>());
-    case detail::ArgKind::GOPAQUE:  return GProtoArg(arg.get<cv::detail::GOpaqueU>());
+    case detail::ArgKind::GOPAQUE: return GProtoArg(arg.get<cv::detail::GOpaqueU>());
     default: util::throw_error(std::logic_error("Unsupported GArg type"));
     }
 }
@@ -98,14 +104,8 @@ cv::GMetaArg cv::descr_of(const cv::GRunArg &arg)
 {
     switch (arg.index())
     {
-#if !defined(GAPI_STANDALONE)
         case GRunArg::index_of<cv::Mat>():
-            return cv::GMetaArg(descr_of(util::get<cv::Mat>(arg)));
-
-#endif // !defined(GAPI_STANDALONE)
-
-        case GRunArg::index_of<cv::gapi::own::Mat>():
-            return cv::GMetaArg(descr_of(util::get<cv::gapi::own::Mat>(arg)));
+            return cv::GMetaArg(cv::descr_of(util::get<cv::Mat>(arg)));
 
         case GRunArg::index_of<cv::Scalar>():
             return cv::GMetaArg(descr_of(util::get<cv::Scalar>(arg)));
@@ -135,10 +135,9 @@ cv::GMetaArg cv::descr_of(const cv::GRunArgP &argp)
     switch (argp.index())
     {
 #if !defined(GAPI_STANDALONE)
-    case GRunArgP::index_of<cv::Mat*>():               return GMetaArg(descr_of(*util::get<cv::Mat*>(argp)));
-    case GRunArgP::index_of<cv::UMat*>():              return GMetaArg(descr_of(*util::get<cv::UMat*>(argp)));
+    case GRunArgP::index_of<cv::UMat*>():              return GMetaArg(cv::descr_of(*util::get<cv::UMat*>(argp)));
 #endif //  !defined(GAPI_STANDALONE)
-    case GRunArgP::index_of<cv::gapi::own::Mat*>():    return GMetaArg(descr_of(*util::get<cv::gapi::own::Mat*>(argp)));
+    case GRunArgP::index_of<cv::Mat*>():               return GMetaArg(cv::descr_of(*util::get<cv::Mat*>(argp)));
     case GRunArgP::index_of<cv::Scalar*>():            return GMetaArg(descr_of(*util::get<cv::Scalar*>(argp)));
     case GRunArgP::index_of<cv::detail::VectorRef>():  return GMetaArg(util::get<cv::detail::VectorRef>(argp).descr_of());
     case GRunArgP::index_of<cv::detail::OpaqueRef>():  return GMetaArg(util::get<cv::detail::OpaqueRef>(argp).descr_of());
@@ -151,13 +150,11 @@ bool cv::can_describe(const GMetaArg& meta, const GRunArgP& argp)
     switch (argp.index())
     {
 #if !defined(GAPI_STANDALONE)
+    case GRunArgP::index_of<cv::UMat*>():              return meta == GMetaArg(cv::descr_of(*util::get<cv::UMat*>(argp)));
+#endif //  !defined(GAPI_STANDALONE)
     case GRunArgP::index_of<cv::Mat*>():               return util::holds_alternative<GMatDesc>(meta) &&
                                                               util::get<GMatDesc>(meta).canDescribe(*util::get<cv::Mat*>(argp));
-    case GRunArgP::index_of<cv::UMat*>():              return meta == GMetaArg(descr_of(*util::get<cv::UMat*>(argp)));
-#endif //  !defined(GAPI_STANDALONE)
-    case GRunArgP::index_of<cv::gapi::own::Mat*>():    return util::holds_alternative<GMatDesc>(meta) &&
-                                                              util::get<GMatDesc>(meta).canDescribe(*util::get<cv::gapi::own::Mat*>(argp));
-    case GRunArgP::index_of<cv::Scalar*>():            return meta == GMetaArg(descr_of(*util::get<cv::Scalar*>(argp)));
+    case GRunArgP::index_of<cv::Scalar*>():            return meta == GMetaArg(cv::descr_of(*util::get<cv::Scalar*>(argp)));
     case GRunArgP::index_of<cv::detail::VectorRef>():  return meta == GMetaArg(util::get<cv::detail::VectorRef>(argp).descr_of());
     case GRunArgP::index_of<cv::detail::OpaqueRef>():  return meta == GMetaArg(util::get<cv::detail::OpaqueRef>(argp).descr_of());
     default: util::throw_error(std::logic_error("Unsupported GRunArgP type"));
@@ -169,12 +166,10 @@ bool cv::can_describe(const GMetaArg& meta, const GRunArg& arg)
     switch (arg.index())
     {
 #if !defined(GAPI_STANDALONE)
-    case GRunArg::index_of<cv::Mat>():               return util::holds_alternative<GMatDesc>(meta) &&
-                                                            util::get<GMatDesc>(meta).canDescribe(util::get<cv::Mat>(arg));
     case GRunArg::index_of<cv::UMat>():              return meta == cv::GMetaArg(descr_of(util::get<cv::UMat>(arg)));
 #endif //  !defined(GAPI_STANDALONE)
-    case GRunArg::index_of<cv::gapi::own::Mat>():    return util::holds_alternative<GMatDesc>(meta) &&
-                                                            util::get<GMatDesc>(meta).canDescribe(util::get<cv::gapi::own::Mat>(arg));
+    case GRunArg::index_of<cv::Mat>():               return util::holds_alternative<GMatDesc>(meta) &&
+                                                            util::get<GMatDesc>(meta).canDescribe(util::get<cv::Mat>(arg));
     case GRunArg::index_of<cv::Scalar>():            return meta == cv::GMetaArg(descr_of(util::get<cv::Scalar>(arg)));
     case GRunArg::index_of<cv::detail::VectorRef>(): return meta == cv::GMetaArg(util::get<cv::detail::VectorRef>(arg).descr_of());
     case GRunArg::index_of<cv::detail::OpaqueRef>(): return meta == cv::GMetaArg(util::get<cv::detail::OpaqueRef>(arg).descr_of());
@@ -198,21 +193,16 @@ void cv::validate_input_arg(const GRunArg& arg)
     switch (arg.index())
     {
 #if !defined(GAPI_STANDALONE)
-    case GRunArg::index_of<cv::Mat>():
-    {
-        const auto desc = descr_of(util::get<cv::Mat>(arg));
-        GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of cv::Mat!"); break;
-    }
     case GRunArg::index_of<cv::UMat>():
     {
-        const auto desc = descr_of(util::get<cv::UMat>(arg));
+        const auto desc = cv::descr_of(util::get<cv::UMat>(arg));
         GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of cv::UMat!"); break;
     }
 #endif //  !defined(GAPI_STANDALONE)
-    case GRunArg::index_of<cv::gapi::own::Mat>():
+    case GRunArg::index_of<cv::Mat>():
     {
-        const auto desc = descr_of(util::get<cv::gapi::own::Mat>(arg));
-        GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of own::Mat!"); break;
+        const auto desc = cv::descr_of(util::get<cv::Mat>(arg));
+        GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of Mat!"); break;
     }
     default:
         // No extra handling
@@ -259,4 +249,25 @@ std::ostream& operator<<(std::ostream& os, const cv::GMetaArg &arg)
 
     return os;
 }
+} // namespace cv
+
+const void* cv::gimpl::proto::ptr(const GRunArgP &arg)
+{
+    switch (arg.index())
+    {
+#if !defined(GAPI_STANDALONE)
+    case GRunArgP::index_of<cv::UMat*>():
+        return static_cast<const void*>(cv::util::get<cv::UMat*>(arg));
+#endif
+    case GRunArgP::index_of<cv::Mat*>():
+        return static_cast<const void*>(cv::util::get<cv::Mat*>(arg));
+    case GRunArgP::index_of<cv::Scalar*>():
+        return static_cast<const void*>(cv::util::get<cv::Scalar*>(arg));
+    case GRunArgP::index_of<cv::detail::VectorRef>():
+        return cv::util::get<cv::detail::VectorRef>(arg).ptr();
+    case GRunArgP::index_of<cv::detail::OpaqueRef>():
+        return cv::util::get<cv::detail::OpaqueRef>(arg).ptr();
+    default:
+        util::throw_error(std::logic_error("Unknown GRunArgP type!"));
+    }
 }
index ca23ad8..b1d71df 100644 (file)
@@ -28,8 +28,14 @@ GAPI_EXPORTS const GOrigin& origin_of (const GArg      &arg);
 bool           is_dynamic(const GArg      &arg);
 GProtoArg      rewrap    (const GArg      &arg);
 
+// FIXME:: GAPI_EXPORTS because of tests only!!
+GAPI_EXPORTS const void*    ptr       (const GRunArgP  &arg);
+
 } // proto
 } // gimpl
 } // cv
 
+// FIXME: the gproto.cpp file has more functions that listed here
+// where those are declared??
+
 #endif // OPENCV_GAPI_GPROTO_PRIV_HPP
index 492d016..bd3e463 100644 (file)
@@ -8,7 +8,6 @@
 #include "precomp.hpp"
 
 #include <opencv2/gapi/gscalar.hpp>
-#include <opencv2/gapi/own/convert.hpp>
 #include "api/gorigin.hpp"
 
 // cv::GScalar public implementation ///////////////////////////////////////////
@@ -47,6 +46,8 @@ const cv::GOrigin& cv::GScalar::priv() const
     return *m_priv;
 }
 
+//N.B. if we ever need more complicated logic for desc_of(cv::(gapi::own::)Scalar)
+//dispatching should be done in the same way as for cv::(gapi::own)::Mat
 cv::GScalarDesc cv::descr_of(const cv::Scalar &)
 {
     return empty_scalar_desc();
index 13a0459..961d19c 100644 (file)
@@ -383,5 +383,15 @@ GMat warpAffine(const GMat& src, const Mat& M, const Size& dsize, int flags,
     return core::GWarpAffine::on(src, M, dsize, flags, borderMode, borderValue);
 }
 
+GOpaque<Size> size(const GMat& src)
+{
+    return core::GSize::on(src);
+}
+
+GOpaque<Size> size(const GOpaque<Rect>& r)
+{
+    return core::GSizeR::on(r);
+}
+
 } //namespace gapi
 } //namespace cv
index 8168c64..108eefc 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -87,6 +87,16 @@ std::tuple<GMat, GMat> SobelXY(const GMat& src, int ddepth, int order, int ksize
     return imgproc::GSobelXY::on(src, ddepth, order, ksize, scale, delta, borderType, bordVal);
 }
 
+GMat Laplacian(const GMat& src, int ddepth, int ksize, double scale, double delta, int borderType)
+{
+    return imgproc::GLaplacian::on(src, ddepth, ksize, scale, delta, borderType);
+}
+
+GMat bilateralFilter(const GMat& src, int d, double sigmaColor, double sigmaSpace, int borderType)
+{
+    return imgproc::GBilateralFilter::on(src, d, sigmaColor, sigmaSpace, borderType);
+}
+
 GMat equalizeHist(const GMat& src)
 {
     return imgproc::GEqHist::on(src);
@@ -97,6 +107,14 @@ GMat Canny(const GMat& src, double thr1, double thr2, int apertureSize, bool l2g
     return imgproc::GCanny::on(src, thr1, thr2, apertureSize, l2gradient);
 }
 
+cv::GArray<cv::Point2f> goodFeaturesToTrack(const GMat& image, int maxCorners, double qualityLevel,
+                                            double minDistance, const Mat& mask, int blockSize,
+                                            bool useHarrisDetector, double k)
+{
+    return imgproc::GGoodFeatures::on(image, maxCorners, qualityLevel, minDistance, mask, blockSize,
+                                      useHarrisDetector, k);
+}
+
 GMat RGB2Gray(const GMat& src)
 {
     return imgproc::GRGB2Gray::on(src);
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_nnparsers.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_nnparsers.cpp
new file mode 100644 (file)
index 0000000..bd6c70f
--- /dev/null
@@ -0,0 +1,44 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <opencv2/gapi/infer/parsers.hpp>
+
+#include <tuple>
+#include <numeric>
+
+namespace cv { namespace gapi {
+
+nn::parsers::GDetections parseSSD(const GMat& in,
+                                  const GOpaque<Size>& inSz,
+                                  const float confidenceThreshold,
+                                  const int filterLabel)
+{
+    return nn::parsers::GParseSSDBL::on(in, inSz, confidenceThreshold, filterLabel);
+}
+
+nn::parsers::GRects parseSSD(const GMat& in,
+                             const GOpaque<Size>& inSz,
+                             const float confidenceThreshold,
+                             const bool alignmentToSquare,
+                             const bool filterOutOfBounds)
+{
+    return nn::parsers::GParseSSD::on(in, inSz, confidenceThreshold, alignmentToSquare, filterOutOfBounds);
+}
+
+nn::parsers::GDetections parseYolo(const GMat& in,
+                                   const GOpaque<Size>& inSz,
+                                   const float confidenceThreshold,
+                                   const float nmsThreshold,
+                                   const std::vector<float>& anchors)
+{
+    return nn::parsers::GParseYolo::on(in, inSz, confidenceThreshold, nmsThreshold, anchors);
+}
+
+} //namespace gapi
+} //namespace cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_video.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_video.cpp
new file mode 100644 (file)
index 0000000..eff6d48
--- /dev/null
@@ -0,0 +1,56 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <opencv2/gapi/video.hpp>
+
+namespace cv { namespace gapi {
+using namespace video;
+
+GBuildPyrOutput buildOpticalFlowPyramid(const GMat    &img,
+                                        const Size    &winSize,
+                                        const GScalar &maxLevel,
+                                              bool     withDerivatives,
+                                              int      pyrBorder,
+                                              int      derivBorder,
+                                              bool     tryReuseInputImage)
+{
+    return GBuildOptFlowPyramid::on(img, winSize, maxLevel, withDerivatives, pyrBorder,
+                                    derivBorder, tryReuseInputImage);
+}
+
+GOptFlowLKOutput calcOpticalFlowPyrLK(const GMat                    &prevImg,
+                                      const GMat                    &nextImg,
+                                      const cv::GArray<cv::Point2f> &prevPts,
+                                      const cv::GArray<cv::Point2f> &predPts,
+                                      const Size                    &winSize,
+                                      const GScalar                 &maxLevel,
+                                      const TermCriteria            &criteria,
+                                            int                      flags,
+                                            double                   minEigThresh)
+{
+    return GCalcOptFlowLK::on(prevImg, nextImg, prevPts, predPts, winSize, maxLevel,
+                              criteria, flags, minEigThresh);
+}
+
+GOptFlowLKOutput calcOpticalFlowPyrLK(const cv::GArray<cv::GMat>    &prevPyr,
+                                      const cv::GArray<cv::GMat>    &nextPyr,
+                                      const cv::GArray<cv::Point2f> &prevPts,
+                                      const cv::GArray<cv::Point2f> &predPts,
+                                      const Size                    &winSize,
+                                      const GScalar                 &maxLevel,
+                                      const TermCriteria            &criteria,
+                                            int                      flags,
+                                            double                   minEigThresh)
+{
+    return GCalcOptFlowLKForPyr::on(prevPyr, nextPyr, prevPts, predPts, winSize, maxLevel,
+                                    criteria, flags, minEigThresh);
+}
+
+} //namespace gapi
+} //namespace cv
index 6097c01..44bf325 100644 (file)
@@ -12,6 +12,8 @@
 #include <opencv2/gapi/gscalar.hpp>
 #include <opencv2/gapi/operators.hpp>
 
+namespace cv
+{
 cv::GMat operator+(const cv::GMat& lhs, const cv::GMat& rhs)
 {
     return cv::gapi::add(lhs, rhs);
@@ -211,3 +213,4 @@ cv::GMat operator!=(const cv::GScalar& lhs, const cv::GMat& rhs)
 {
     return cv::gapi::cmpNE(rhs, lhs);
 }
+} // cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/s11n.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/s11n.cpp
new file mode 100644 (file)
index 0000000..b56c34f
--- /dev/null
@@ -0,0 +1,114 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include <opencv2/gapi/s11n.hpp>
+#include <opencv2/gapi/garg.hpp>
+
+#include "backends/common/serialization.hpp"
+
+std::vector<char> cv::gapi::serialize(const cv::GComputation &c) {
+    cv::gimpl::s11n::ByteMemoryOutStream os;
+    c.serialize(os);
+    return os.data();
+}
+
+cv::GComputation cv::gapi::detail::getGraph(const std::vector<char> &p) {
+    cv::gimpl::s11n::ByteMemoryInStream is(p);
+    return cv::GComputation(is);
+}
+
+cv::GMetaArgs cv::gapi::detail::getMetaArgs(const std::vector<char> &p) {
+    cv::gimpl::s11n::ByteMemoryInStream is(p);
+    return meta_args_deserialize(is);
+}
+
+cv::GRunArgs cv::gapi::detail::getRunArgs(const std::vector<char> &p) {
+    cv::gimpl::s11n::ByteMemoryInStream is(p);
+    return run_args_deserialize(is);
+}
+
+std::vector<char> cv::gapi::serialize(const cv::GMetaArgs& ma)
+{
+    cv::gimpl::s11n::ByteMemoryOutStream os;
+    serialize(os, ma);
+    return os.data();
+}
+
+std::vector<char> cv::gapi::serialize(const cv::GRunArgs& ra)
+{
+    cv::gimpl::s11n::ByteMemoryOutStream os;
+    serialize(os, ra);
+    return os.data();
+}
+
+// FIXME: This function should move from S11N to GRunArg-related entities.
+// it has nothing to do with the S11N as it is
+cv::GRunArgsP cv::gapi::bind(cv::GRunArgs &results)
+{
+    cv::GRunArgsP outputs;
+    outputs.reserve(results.size());
+    for (cv::GRunArg &res_obj : results)
+    {
+        using T = cv::GRunArg;
+        switch (res_obj.index())
+        {
+#if !defined(GAPI_STANDALONE)
+        case T::index_of<cv::UMat>() :
+            outputs.emplace_back((cv::UMat*)(&(cv::util::get<cv::UMat>(res_obj))));
+            break;
+#endif
+        case cv::GRunArg::index_of<cv::Mat>() :
+            outputs.emplace_back((cv::Mat*)(&(cv::util::get<cv::Mat>(res_obj))));
+            break;
+        case cv::GRunArg::index_of<cv::Scalar>() :
+            outputs.emplace_back((cv::Scalar*)(&(cv::util::get<cv::Scalar>(res_obj))));
+            break;
+        case T::index_of<cv::detail::VectorRef>() :
+            outputs.emplace_back(cv::util::get<cv::detail::VectorRef>(res_obj));
+            break;
+        case T::index_of<cv::detail::OpaqueRef>() :
+            outputs.emplace_back(cv::util::get<cv::detail::OpaqueRef>(res_obj));
+            break;
+        default:
+            GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode.
+            break;
+        }
+    }
+    return outputs;
+}
+
+// FIXME: move it out of s11n to api/
+// FIXME: don't we have such function already?
+cv::GRunArg cv::gapi::bind(cv::GRunArgP &out)
+{
+    using T = cv::GRunArgP;
+    switch (out.index())
+    {
+#if !defined(GAPI_STANDALONE)
+    case T::index_of<cv::UMat*>() :
+        GAPI_Assert(false && "Please implement this!");
+        break;
+#endif
+
+    case T::index_of<cv::detail::VectorRef>() :
+        return cv::GRunArg(cv::util::get<cv::detail::VectorRef>(out));
+
+    case T::index_of<cv::detail::OpaqueRef>() :
+        return cv::GRunArg(cv::util::get<cv::detail::OpaqueRef>(out));
+
+    case T::index_of<cv::Mat*>() :
+        return cv::GRunArg(*cv::util::get<cv::Mat*>(out));
+
+    case T::index_of<cv::Scalar*>() :
+        return cv::GRunArg(*cv::util::get<cv::Scalar*>(out));
+
+    default:
+        // ...maybe our types were extended
+        GAPI_Assert(false && "This value type is UNKNOWN!");
+        break;
+    }
+    return cv::GRunArg();
+}
index ee3bfa2..e9a44c4 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GBACKEND_HPP
@@ -14,7 +14,6 @@
 #include <ade/node.hpp>
 
 #include "opencv2/gapi/garg.hpp"
-#include "opencv2/gapi/own/mat.hpp"
 
 #include "opencv2/gapi/util/optional.hpp"
 
@@ -45,9 +44,9 @@ namespace magazine {
 
 } // namespace magazine
 #if !defined(GAPI_STANDALONE)
-using Mag = magazine::Class<cv::gapi::own::Mat, cv::UMat, cv::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
+using Mag = magazine::Class<cv::Mat, cv::UMat, cv::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
 #else
-using Mag = magazine::Class<cv::gapi::own::Mat, cv::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
+using Mag = magazine::Class<cv::Mat, cv::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
 #endif
 
 namespace magazine
@@ -88,20 +87,10 @@ struct GRuntimeArgs
 template<typename T>
 inline cv::util::optional<T> getCompileArg(const cv::GCompileArgs &args)
 {
-    for (auto &compile_arg : args)
-    {
-        if (compile_arg.tag == cv::detail::CompileArgTag<T>::tag())
-        {
-            return cv::util::optional<T>(compile_arg.get<T>());
-        }
-    }
-    return cv::util::optional<T>();
+    return cv::gapi::getCompileArg<T>(args);
 }
 
-void createMat(const cv::GMatDesc& desc, cv::gapi::own::Mat& mat);
-#if !defined(GAPI_STANDALONE)
 void createMat(const cv::GMatDesc& desc, cv::Mat& mat);
-#endif
 
 }} // cv::gimpl
 
index 05ed51d..8983a3a 100644 (file)
@@ -32,7 +32,11 @@ cv::detail::GCompoundContext::GCompoundContext(const cv::GArgs& in_args)
             {
                 case GShape::GMAT   : m_args[i] = GArg(GMat());    break;
                 case GShape::GSCALAR: m_args[i] = GArg(GScalar()); break;
-                case GShape::GARRAY :/* do nothing - as handled in a special way, see gcompoundkernel.hpp for details */; break;
+                case GShape::GARRAY :
+                case GShape::GOPAQUE:
+                    // do nothing - as handled in a special way, see gcompoundkernel.hpp for details
+                    // same applies to GMatP
+                    break;
                 default: GAPI_Assert(false);
             }
         }
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/serialization.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/serialization.cpp
new file mode 100644 (file)
index 0000000..ab7626d
--- /dev/null
@@ -0,0 +1,837 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include <set> // set
+#include <map> // map
+#include <ade/util/zip_range.hpp> // indexed
+
+#define NOMINMAX
+
+#ifdef _WIN32
+#include <winsock.h>      // htonl, ntohl
+#else
+#include <netinet/in.h>   // htonl, ntohl
+#endif
+
+#include <opencv2/gapi/gtype_traits.hpp>
+
+#include "backends/common/serialization.hpp"
+
+namespace cv {
+namespace gimpl {
+namespace s11n {
+namespace {
+
+void putData(GSerialized& s, const GModel::ConstGraph& cg, const ade::NodeHandle &nh) {
+    const auto gdata = cg.metadata(nh).get<gimpl::Data>();
+    const auto it = ade::util::find_if(s.m_datas, [&gdata](const cv::gimpl::Data &cd) {
+            return cd.rc == gdata.rc && cd.shape == gdata.shape;
+        });
+    if (s.m_datas.end() == it) {
+        s.m_datas.push_back(gdata);
+    }
+}
+
+void putOp(GSerialized& s, const GModel::ConstGraph& cg, const ade::NodeHandle &nh) {
+    const auto& op = cg.metadata(nh).get<gimpl::Op>();
+    for (const auto &in_nh  : nh->inNodes())  { putData(s, cg, in_nh);  }
+    for (const auto &out_nh : nh->outNodes()) { putData(s, cg, out_nh); }
+    s.m_ops.push_back(op);
+}
+
+void mkDataNode(ade::Graph& g, const cv::gimpl::Data& data) {
+    GModel::Graph gm(g);
+    auto nh = gm.createNode();
+    gm.metadata(nh).set(NodeType{NodeType::DATA});
+    gm.metadata(nh).set(data);
+}
+
+void mkOpNode(ade::Graph& g, const cv::gimpl::Op& op) {
+    GModel::Graph gm(g);
+    auto nh = gm.createNode();
+    gm.metadata(nh).set(NodeType{NodeType::OP});
+    gm.metadata(nh).set(op);
+}
+
+void linkNodes(ade::Graph& g) {
+    std::map<cv::gimpl::RcDesc, ade::NodeHandle> dataNodes;
+    GModel::Graph gm(g);
+
+    for (const auto& nh : g.nodes()) {
+        if (gm.metadata(nh).get<NodeType>().t == NodeType::DATA) {
+            const auto &d = gm.metadata(nh).get<gimpl::Data>();
+            const auto rc = cv::gimpl::RcDesc{d.rc, d.shape, d.ctor};
+            dataNodes[rc] = nh;
+        }
+    }
+
+    for (const auto& nh : g.nodes()) {
+        if (gm.metadata(nh).get<NodeType>().t == NodeType::OP) {
+            const auto& op = gm.metadata(nh).get<gimpl::Op>();
+            for (const auto& in : ade::util::indexed(op.args)) {
+                const auto& arg = ade::util::value(in);
+                if (arg.kind == cv::detail::ArgKind::GOBJREF) {
+                    const auto idx = ade::util::index(in);
+                    const auto rc  = arg.get<gimpl::RcDesc>();
+                    const auto& in_nh = dataNodes.at(rc);
+                    const auto& in_eh = g.link(in_nh, nh);
+                    gm.metadata(in_eh).set(Input{idx});
+                }
+            }
+
+            for (const auto& out : ade::util::indexed(op.outs)) {
+                const auto idx = ade::util::index(out);
+                const auto rc  = ade::util::value(out);
+                const auto& out_nh = dataNodes.at(rc);
+                const auto& out_eh = g.link(nh, out_nh);
+                gm.metadata(out_eh).set(Output{idx});
+            }
+        }
+    }
+}
+
+void relinkProto(ade::Graph& g) {
+    // identify which node handles map to the protocol
+    // input/output object in the reconstructed graph
+    using S = std::set<cv::gimpl::RcDesc>;                  // FIXME: use ...
+    using M = std::map<cv::gimpl::RcDesc, ade::NodeHandle>; // FIXME: unordered!
+
+    cv::gimpl::GModel::Graph gm(g);
+    auto &proto = gm.metadata().get<Protocol>();
+
+    const S set_in(proto.inputs.begin(), proto.inputs.end());
+    const S set_out(proto.outputs.begin(), proto.outputs.end());
+    M map_in, map_out;
+
+    // Associate the protocol node handles with their resource identifiers
+    for (auto &&nh : gm.nodes()) {
+        if (gm.metadata(nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::DATA) {
+            const auto &d = gm.metadata(nh).get<cv::gimpl::Data>();
+            const auto rc = cv::gimpl::RcDesc{d.rc, d.shape, d.ctor};
+            if (set_in.count(rc) > 0) {
+                GAPI_DbgAssert(set_out.count(rc) == 0);
+                map_in[rc] = nh;
+            } else if (set_out.count(rc) > 0) {
+                GAPI_DbgAssert(set_in.count(rc) == 0);
+                map_out[rc] = nh;
+            }
+        }
+    }
+
+    // Reconstruct the protocol vectors, ordered
+    proto.in_nhs.reserve(proto.inputs.size());
+    proto.in_nhs.clear();
+    proto.out_nhs.reserve(proto.outputs.size());
+    proto.out_nhs.clear();
+    for (auto &rc : proto.inputs)  { proto.in_nhs .push_back(map_in .at(rc)); }
+    for (auto &rc : proto.outputs) { proto.out_nhs.push_back(map_out.at(rc)); }
+}
+
+} // anonymous namespace
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// Graph dump operators
+
+// OpenCV types ////////////////////////////////////////////////////////////////
+
+I::OStream& operator<< (I::OStream& os, const cv::Point &pt) {
+    return os << pt.x << pt.y;
+}
+I::IStream& operator>> (I::IStream& is, cv::Point& pt) {
+    return is >> pt.x >> pt.y;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::Size &sz) {
+    return os << sz.width << sz.height;
+}
+I::IStream& operator>> (I::IStream& is, cv::Size& sz) {
+    return is >> sz.width >> sz.height;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::Rect &rc) {
+    return os << rc.x << rc.y << rc.width << rc.height;
+}
+I::IStream& operator>> (I::IStream& is, cv::Rect& rc) {
+    return is >> rc.x >> rc.y >> rc.width >> rc.height;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::Scalar &s) {
+    return os << s.val[0] << s.val[1] << s.val[2] << s.val[3];
+}
+I::IStream& operator>> (I::IStream& is, cv::Scalar& s) {
+    return is >> s.val[0] >> s.val[1] >> s.val[2] >> s.val[3];
+}
+
+namespace
+{
+
+#if !defined(GAPI_STANDALONE)
+template<typename T>
+    void write_plain(I::OStream &os, const T *arr, std::size_t sz) {
+        for (auto &&it : ade::util::iota(sz)) os << arr[it];
+}
+template<typename T>
+    void read_plain(I::IStream &is, T *arr, std::size_t sz) {
+        for (auto &&it : ade::util::iota(sz)) is >> arr[it];
+}
+template<typename T>
+void write_mat_data(I::OStream &os, const cv::Mat &m) {
+    // Write every row individually (handles the case when Mat is a view)
+    for (auto &&r : ade::util::iota(m.rows)) {
+        write_plain(os, m.ptr<T>(r), m.cols*m.channels());
+    }
+}
+template<typename T>
+void read_mat_data(I::IStream &is, cv::Mat &m) {
+    // Write every row individually (handles the case when Mat is aligned)
+    for (auto &&r : ade::util::iota(m.rows)) {
+        read_plain(is, m.ptr<T>(r), m.cols*m.channels());
+    }
+}
+#else
+void write_plain(I::OStream &os, const uchar *arr, std::size_t sz) {
+    for (auto &&it : ade::util::iota(sz)) os << arr[it];
+}
+void read_plain(I::IStream &is, uchar *arr, std::size_t sz) {
+    for (auto &&it : ade::util::iota(sz)) is >> arr[it];
+}
+template<typename T>
+void write_mat_data(I::OStream &os, const cv::Mat &m) {
+    // Write every row individually (handles the case when Mat is a view)
+    for (auto &&r : ade::util::iota(m.rows)) {
+        write_plain(os, m.ptr(r), m.cols*m.channels()*sizeof(T));
+    }
+}
+template<typename T>
+void read_mat_data(I::IStream &is, cv::Mat &m) {
+    // Write every row individually (handles the case when Mat is aligned)
+    for (auto &&r : ade::util::iota(m.rows)) {
+        read_plain(is, m.ptr(r), m.cols*m.channels()*sizeof(T));
+    }
+}
+#endif
+} // namespace
+
+I::OStream& operator<< (I::OStream& os, const cv::Mat &m) {
+#if !defined(GAPI_STANDALONE)
+    GAPI_Assert(m.size.dims() == 2 && "Only 2D images are supported now");
+#else
+    GAPI_Assert(m.dims.size() == 2 && "Only 2D images are supported now");
+#endif
+    os << m.rows << m.cols << m.type();
+    switch (m.depth()) {
+    case CV_8U:  write_mat_data< uint8_t>(os, m); break;
+    case CV_8S:  write_mat_data<    char>(os, m); break;
+    case CV_16U: write_mat_data<uint16_t>(os, m); break;
+    case CV_16S: write_mat_data< int16_t>(os, m); break;
+    case CV_32S: write_mat_data< int32_t>(os, m); break;
+    case CV_32F: write_mat_data<   float>(os, m); break;
+    case CV_64F: write_mat_data<  double>(os, m); break;
+    default: GAPI_Assert(false && "Unsupported Mat depth");
+    }
+    return os;
+}
+I::IStream& operator>> (I::IStream& is, cv::Mat& m) {
+    int rows = -1, cols = -1, type = 0;
+    is >> rows >> cols >> type;
+    m.create(cv::Size(cols, rows), type);
+    switch (m.depth()) {
+    case CV_8U:  read_mat_data< uint8_t>(is, m); break;
+    case CV_8S:  read_mat_data<    char>(is, m); break;
+    case CV_16U: read_mat_data<uint16_t>(is, m); break;
+    case CV_16S: read_mat_data< int16_t>(is, m); break;
+    case CV_32S: read_mat_data< int32_t>(is, m); break;
+    case CV_32F: read_mat_data<   float>(is, m); break;
+    case CV_64F: read_mat_data<  double>(is, m); break;
+    default: GAPI_Assert(false && "Unsupported Mat depth");
+    }
+    return is;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Text &t) {
+    return os << t.bottom_left_origin << t.color << t.ff << t.fs << t.lt << t.org << t.text << t.thick;
+}
+I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Text &t) {
+    return is >> t.bottom_left_origin >> t.color >> t.ff >> t.fs >> t.lt >> t.org >> t.text >> t.thick;
+}
+
+I::OStream& operator<< (I::OStream&, const cv::gapi::wip::draw::FText &) {
+    GAPI_Assert(false && "Serialization: Unsupported << for FText");
+}
+I::IStream& operator>> (I::IStream&,       cv::gapi::wip::draw::FText &) {
+    GAPI_Assert(false && "Serialization: Unsupported >> for FText");
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Circle &c) {
+    return os << c.center << c.color << c.lt << c.radius << c.shift << c.thick;
+}
+I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Circle &c) {
+    return is >> c.center >> c.color >> c.lt >> c.radius >> c.shift >> c.thick;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Rect &r) {
+    return os << r.color << r.lt << r.rect << r.shift << r.thick;
+}
+I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Rect &r) {
+    return is >> r.color >> r.lt >> r.rect >> r.shift >> r.thick;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Image &i) {
+    return os << i.org << i.alpha << i.img;
+}
+I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Image &i) {
+    return is >> i.org >> i.alpha >> i.img;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Mosaic &m) {
+    return os << m.cellSz << m.decim << m.mos;
+}
+I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Mosaic &m) {
+    return is >> m.cellSz >> m.decim >> m.mos;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Poly &p) {
+    return os << p.color << p.lt << p.points << p.shift << p.thick;
+}
+I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Poly &p) {
+    return is >> p.color >> p.lt >> p.points >> p.shift >> p.thick;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Line &l) {
+    return os << l.color << l.lt << l.pt1 << l.pt2 << l.shift << l.thick;
+}
+I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Line &l) {
+    return is >> l.color >> l.lt >> l.pt1 >> l.pt2 >> l.shift >> l.thick;
+}
+
+// G-API types /////////////////////////////////////////////////////////////////
+
+// Stubs (empty types)
+
+I::OStream& operator<< (I::OStream& os, cv::util::monostate  ) {return os;}
+I::IStream& operator>> (I::IStream& is, cv::util::monostate &) {return is;}
+
+I::OStream& operator<< (I::OStream& os, const cv::GScalarDesc &) {return os;}
+I::IStream& operator>> (I::IStream& is,       cv::GScalarDesc &) {return is;}
+
+I::OStream& operator<< (I::OStream& os, const cv::GOpaqueDesc &) {return os;}
+I::IStream& operator>> (I::IStream& is,       cv::GOpaqueDesc &) {return is;}
+
+I::OStream& operator<< (I::OStream& os, const cv::GArrayDesc &) {return os;}
+I::IStream& operator>> (I::IStream& is,       cv::GArrayDesc &) {return is;}
+
+#if !defined(GAPI_STANDALONE)
+I::OStream& operator<< (I::OStream& os, const cv::UMat &)
+{
+    GAPI_Assert(false && "Serialization: Unsupported << for UMat");
+    return os;
+}
+I::IStream& operator >> (I::IStream& is, cv::UMat &)
+{
+    GAPI_Assert(false && "Serialization: Unsupported >> for UMat");
+    return is;
+}
+#endif // !defined(GAPI_STANDALONE)
+
+I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::IStreamSource::Ptr &)
+{
+    GAPI_Assert(false && "Serialization: Unsupported << for IStreamSource::Ptr");
+    return os;
+}
+I::IStream& operator >> (I::IStream& is, cv::gapi::wip::IStreamSource::Ptr &)
+{
+    GAPI_Assert("Serialization: Unsupported >> for IStreamSource::Ptr");
+    return is;
+}
+
+namespace
+{
+template<typename Ref, typename T, typename... Ts>
+struct putToStream;
+
+template<typename Ref>
+struct putToStream<Ref, std::tuple<>>
+{
+    static void put(I::OStream&, const Ref &)
+    {
+        GAPI_Assert(false && "Unsupported type for GArray/GOpaque serialization");
+    }
+};
+
+template<typename Ref, typename T, typename... Ts>
+struct putToStream<Ref, std::tuple<T, Ts...>>
+{
+    static void put(I::OStream& os, const Ref &r)
+    {
+        if (r.getKind() == cv::detail::GOpaqueTraits<T>::kind) {
+            os << r.template rref<T>();
+        } else {
+            putToStream<Ref, std::tuple<Ts...> >::put(os, r);
+        }
+    }
+};
+
+template<typename Ref, typename T, typename... Ts>
+struct getFromStream;
+
+template<typename Ref>
+struct getFromStream<Ref, std::tuple<>>
+{
+    static void get(I::IStream&, Ref &, cv::detail::OpaqueKind)
+    {
+        GAPI_Assert(false && "Unsupported type for GArray/GOpaque deserialization");
+    }
+};
+
+template<typename Ref, typename T, typename... Ts>
+struct getFromStream<Ref, std::tuple<T, Ts...>>
+{
+    static void get(I::IStream& is, Ref &r, cv::detail::OpaqueKind kind) {
+        if (kind == cv::detail::GOpaqueTraits<T>::kind) {
+            r.template reset<T>();
+            auto& val = r.template wref<T>();
+            is >> val;
+        } else {
+            getFromStream<Ref, std::tuple<Ts...> >::get(is, r, kind);
+        }
+    }
+};
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef& ref)
+{
+    os << ref.getKind();
+    putToStream<cv::detail::VectorRef, cv::detail::GOpaqueTraitsArrayTypes>::put(os, ref);
+    return os;
+}
+I::IStream& operator >> (I::IStream& is, cv::detail::VectorRef& ref)
+{
+    cv::detail::OpaqueKind kind;
+    is >> kind;
+    getFromStream<cv::detail::VectorRef, cv::detail::GOpaqueTraitsArrayTypes>::get(is, ref, kind);
+    return is;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::detail::OpaqueRef& ref)
+{
+    os << ref.getKind();
+    putToStream<cv::detail::OpaqueRef, cv::detail::GOpaqueTraitsOpaqueTypes>::put(os, ref);
+    return os;
+}
+I::IStream& operator >> (I::IStream& is, cv::detail::OpaqueRef& ref)
+{
+    cv::detail::OpaqueKind kind;
+    is >> kind;
+    getFromStream<cv::detail::OpaqueRef, cv::detail::GOpaqueTraitsOpaqueTypes>::get(is, ref, kind);
+    return is;
+}
+// Enums and structures
+
+namespace {
+template<typename E> I::OStream& put_enum(I::OStream& os, E e) {
+    return os << static_cast<int>(e);
+}
+template<typename E> I::IStream& get_enum(I::IStream& is, E &e) {
+    int x{}; is >> x; e = static_cast<E>(x);
+    return is;
+}
+} // anonymous namespace
+
+I::OStream& operator<< (I::OStream& os, cv::GShape  sh) {
+    return put_enum(os, sh);
+}
+I::IStream& operator>> (I::IStream& is, cv::GShape &sh) {
+    return get_enum<cv::GShape>(is, sh);
+}
+I::OStream& operator<< (I::OStream& os, cv::detail::ArgKind  k) {
+    return put_enum(os, k);
+}
+I::IStream& operator>> (I::IStream& is, cv::detail::ArgKind &k) {
+    return get_enum<cv::detail::ArgKind>(is, k);
+}
+I::OStream& operator<< (I::OStream& os, cv::detail::OpaqueKind  k) {
+    return put_enum(os, k);
+}
+I::IStream& operator>> (I::IStream& is, cv::detail::OpaqueKind &k) {
+    return get_enum<cv::detail::OpaqueKind>(is, k);
+}
+I::OStream& operator<< (I::OStream& os, cv::gimpl::Data::Storage s) {
+    return put_enum(os, s);
+}
+I::IStream& operator>> (I::IStream& is, cv::gimpl::Data::Storage &s) {
+    return get_enum<cv::gimpl::Data::Storage>(is, s);
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::GArg &arg) {
+    // Only GOBJREF and OPAQUE_VAL kinds can be serialized/deserialized
+    GAPI_Assert(   arg.kind == cv::detail::ArgKind::OPAQUE_VAL
+                || arg.kind == cv::detail::ArgKind::GOBJREF);
+
+    os << arg.kind << arg.opaque_kind;
+    if (arg.kind == cv::detail::ArgKind::GOBJREF) {
+        os << arg.get<cv::gimpl::RcDesc>();
+    } else {
+        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;
+        default: GAPI_Assert(false && "GArg: Unsupported (unknown?) opaque value type");
+        }
+    }
+    return os;
+}
+
+I::IStream& operator>> (I::IStream& is, cv::GArg &arg) {
+    is >> arg.kind >> arg.opaque_kind;
+
+    // Only GOBJREF and OPAQUE_VAL kinds can be serialized/deserialized
+    GAPI_Assert(   arg.kind == cv::detail::ArgKind::OPAQUE_VAL
+                || arg.kind == cv::detail::ArgKind::GOBJREF);
+
+    if (arg.kind == cv::detail::ArgKind::GOBJREF) {
+        cv::gimpl::RcDesc rc;
+        is >> rc;
+        arg = (GArg(rc));
+    } else {
+        GAPI_Assert(arg.kind == cv::detail::ArgKind::OPAQUE_VAL);
+        GAPI_Assert(arg.opaque_kind != cv::detail::OpaqueKind::CV_UNKNOWN);
+        switch (arg.opaque_kind) {
+#define HANDLE_CASE(E,T) case cv::detail::OpaqueKind::CV_##E:           \
+            { T t{}; is >> t; arg = (cv::GArg(t)); } break
+            HANDLE_CASE(BOOL   , bool);
+            HANDLE_CASE(INT    , int);
+            HANDLE_CASE(DOUBLE , double);
+            HANDLE_CASE(POINT  , cv::Point);
+            HANDLE_CASE(SIZE   , cv::Size);
+            HANDLE_CASE(RECT   , cv::Rect);
+            HANDLE_CASE(SCALAR , cv::Scalar);
+            HANDLE_CASE(MAT    , cv::Mat);
+#undef HANDLE_CASE
+        default: GAPI_Assert(false && "GArg: Unsupported (unknown?) opaque value type");
+        }
+    }
+    return is;
+}
+
+I::OStream& operator<< (I::OStream& os, const cv::GKernel &k) {
+    return os << k.name << k.tag << k.outShapes;
+}
+I::IStream& operator>> (I::IStream& is, cv::GKernel &k) {
+    return is >> const_cast<std::string&>(k.name)
+              >> const_cast<std::string&>(k.tag)
+              >> const_cast<cv::GShapes&>(k.outShapes);
+}
+
+
+I::OStream& operator<< (I::OStream& os, const cv::GMatDesc &d) {
+    return os << d.depth << d.chan << d.size << d.planar << d.dims;
+}
+I::IStream& operator>> (I::IStream& is, cv::GMatDesc &d) {
+    return is >> d.depth >> d.chan >> d.size >> d.planar >> d.dims;
+}
+
+
+I::OStream& operator<< (I::OStream& os, const cv::gimpl::RcDesc &rc) {
+    // FIXME: HostCtor is not serialized!
+    return os << rc.id << rc.shape;
+}
+I::IStream& operator>> (I::IStream& is, cv::gimpl::RcDesc &rc) {
+    // FIXME: HostCtor is not deserialized!
+    return is >> rc.id >> rc.shape;
+}
+
+
+I::OStream& operator<< (I::OStream& os, const cv::gimpl::Op &op) {
+    return os << op.k << op.args << op.outs;
+}
+I::IStream& operator>> (I::IStream& is, cv::gimpl::Op &op) {
+    return is >> op.k >> op.args >> op.outs;
+}
+
+
+I::OStream& operator<< (I::OStream& os, const cv::gimpl::Data &d) {
+    // FIXME: HostCtor is not stored here!!
+    // FIXME: Storage may be incorrect for subgraph-to-graph process
+    return os << d.shape << d.rc << d.meta << d.storage << d.kind;
+}
+
+namespace
+{
+template<typename Ref, typename T, typename... Ts>
+struct initCtor;
+
+template<typename Ref>
+struct initCtor<Ref, std::tuple<>>
+{
+    static void init(cv::gimpl::Data&)
+    {
+        GAPI_Assert(false && "Unsupported type for GArray/GOpaque deserialization");
+    }
+};
+
+template<typename Ref, typename T, typename... Ts>
+struct initCtor<Ref, std::tuple<T, Ts...>>
+{
+    static void init(cv::gimpl::Data& d) {
+        if (d.kind == cv::detail::GOpaqueTraits<T>::kind) {
+            static std::function<void(Ref&)> ctor = [](Ref& ref){ref.template reset<T>();};
+            d.ctor = ctor;
+        } else {
+            initCtor<Ref, std::tuple<Ts...> >::init(d);
+        }
+    }
+};
+} // anonymous namespace
+
+I::IStream& operator>> (I::IStream& is, cv::gimpl::Data &d) {
+    // FIXME: HostCtor is not stored here!!
+    // FIXME: Storage may be incorrect for subgraph-to-graph process
+    is >> d.shape >> d.rc >> d.meta >> d.storage >> d.kind;
+    if (d.shape == cv::GShape::GARRAY)
+    {
+        initCtor<cv::detail::VectorRef, cv::detail::GOpaqueTraitsArrayTypes>::init(d);
+    }
+    else if (d.shape == cv::GShape::GOPAQUE)
+    {
+        initCtor<cv::detail::OpaqueRef, cv::detail::GOpaqueTraitsOpaqueTypes>::init(d);
+    }
+    return is;
+}
+
+
+I::OStream& operator<< (I::OStream& os, const cv::gimpl::DataObjectCounter &c) {
+    return os << c.m_next_data_id;
+}
+I::IStream& operator>> (I::IStream& is,       cv::gimpl::DataObjectCounter &c) {
+    return is >> c.m_next_data_id;
+}
+
+
+I::OStream& operator<< (I::OStream& os, const cv::gimpl::Protocol &p) {
+    // NB: in_nhs/out_nhs are not written!
+    return os << p.inputs << p.outputs;
+}
+I::IStream& operator>> (I::IStream& is,       cv::gimpl::Protocol &p) {
+    // NB: in_nhs/out_nhs are reconstructed at a later phase
+    return is >> p.inputs >> p.outputs;
+}
+
+
+void serialize( I::OStream& os
+              , const ade::Graph &g
+              , const std::vector<ade::NodeHandle> &nodes) {
+    cv::gimpl::GModel::ConstGraph cg(g);
+    serialize(os, g, cg.metadata().get<cv::gimpl::Protocol>(), nodes);
+}
+
+void serialize( I::OStream& os
+              , const ade::Graph &g
+              , const cv::gimpl::Protocol &p
+              , const std::vector<ade::NodeHandle> &nodes) {
+    cv::gimpl::GModel::ConstGraph cg(g);
+    GSerialized s;
+    for (auto &nh : nodes) {
+        switch (cg.metadata(nh).get<NodeType>().t)
+        {
+        case NodeType::OP:   putOp  (s, cg, nh); break;
+        case NodeType::DATA: putData(s, cg, nh); break;
+        default: util::throw_error(std::logic_error("Unknown NodeType"));
+        }
+    }
+    s.m_counter = cg.metadata().get<cv::gimpl::DataObjectCounter>();
+    s.m_proto   = p;
+    os << s.m_ops << s.m_datas << s.m_counter << s.m_proto;
+}
+
+GSerialized deserialize(I::IStream &is) {
+    GSerialized s;
+    is >> s.m_ops >> s.m_datas >> s.m_counter >> s.m_proto;
+    return s;
+}
+
+void reconstruct(const GSerialized &s, ade::Graph &g) {
+    GAPI_Assert(g.nodes().empty());
+    for (const auto& d  : s.m_datas) cv::gimpl::s11n::mkDataNode(g, d);
+    for (const auto& op : s.m_ops)   cv::gimpl::s11n::mkOpNode(g, op);
+    cv::gimpl::s11n::linkNodes(g);
+
+    cv::gimpl::GModel::Graph gm(g);
+    gm.metadata().set(s.m_counter);
+    gm.metadata().set(s.m_proto);
+    cv::gimpl::s11n::relinkProto(g);
+    gm.metadata().set(cv::gimpl::Deserialized{});
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Streams /////////////////////////////////////////////////////////////////////
+
+const std::vector<char>& ByteMemoryOutStream::data() const {
+    return m_storage;
+}
+I::OStream& ByteMemoryOutStream::operator<< (uint32_t atom) {
+    m_storage.push_back(0xFF & (atom));
+    m_storage.push_back(0xFF & (atom >> 8));
+    m_storage.push_back(0xFF & (atom >> 16));
+    m_storage.push_back(0xFF & (atom >> 24));
+    return *this;
+}
+I::OStream& ByteMemoryOutStream::operator<< (bool atom) {
+    m_storage.push_back(atom ? 1 : 0);
+    return *this;
+}
+I::OStream& ByteMemoryOutStream::operator<< (char atom) {
+    m_storage.push_back(atom);
+    return *this;
+}
+I::OStream& ByteMemoryOutStream::operator<< (unsigned char atom) {
+    return *this << static_cast<char>(atom);
+}
+I::OStream& ByteMemoryOutStream::operator<< (short atom) {
+    static_assert(sizeof(short) == 2, "Expecting sizeof(short) == 2");
+    m_storage.push_back(0xFF & (atom));
+    m_storage.push_back(0xFF & (atom >> 8));
+    return *this;
+}
+I::OStream& ByteMemoryOutStream::operator<< (unsigned short atom) {
+    return *this << static_cast<short>(atom);
+}
+I::OStream& ByteMemoryOutStream::operator<< (int atom) {
+    static_assert(sizeof(int) == 4, "Expecting sizeof(int) == 4");
+    return *this << static_cast<uint32_t>(atom);
+}
+//I::OStream& ByteMemoryOutStream::operator<< (std::size_t atom) {
+//    // NB: type truncated!
+//    return *this << static_cast<uint32_t>(atom);
+//}
+I::OStream& ByteMemoryOutStream::operator<< (float atom) {
+    static_assert(sizeof(float) == 4, "Expecting sizeof(float) == 4");
+    uint32_t tmp = 0u;
+    memcpy(&tmp, &atom, sizeof(float));
+    return *this << static_cast<uint32_t>(htonl(tmp));
+}
+I::OStream& ByteMemoryOutStream::operator<< (double atom) {
+    static_assert(sizeof(double) == 8, "Expecting sizeof(double) == 8");
+    uint32_t tmp[2] = {0u};
+    memcpy(tmp, &atom, sizeof(double));
+    *this << static_cast<uint32_t>(htonl(tmp[0]));
+    *this << static_cast<uint32_t>(htonl(tmp[1]));
+    return *this;
+}
+I::OStream& ByteMemoryOutStream::operator<< (const std::string &str) {
+    //*this << static_cast<std::size_t>(str.size()); // N.B. Put type explicitly
+    *this << static_cast<uint32_t>(str.size()); // N.B. Put type explicitly
+    for (auto c : str) *this << c;
+    return *this;
+}
+
+ByteMemoryInStream::ByteMemoryInStream(const std::vector<char> &data)
+    : m_storage(data) {
+}
+I::IStream& ByteMemoryInStream::operator>> (uint32_t &atom) {
+    check(sizeof(uint32_t));
+    uint8_t x[4];
+    x[0] = static_cast<uint8_t>(m_storage[m_idx++]);
+    x[1] = static_cast<uint8_t>(m_storage[m_idx++]);
+    x[2] = static_cast<uint8_t>(m_storage[m_idx++]);
+    x[3] = static_cast<uint8_t>(m_storage[m_idx++]);
+    atom = ((x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24));
+    return *this;
+}
+I::IStream& ByteMemoryInStream::operator>> (bool& 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>> (unsigned char &atom) {
+    char c{};
+    *this >> c;
+    atom = static_cast<unsigned char>(c);
+    return *this;
+}
+I::IStream& ByteMemoryInStream::operator>> (short &atom) {
+    static_assert(sizeof(short) == 2, "Expecting sizeof(short) == 2");
+    check(sizeof(short));
+    uint8_t x[2];
+    x[0] = static_cast<uint8_t>(m_storage[m_idx++]);
+    x[1] = static_cast<uint8_t>(m_storage[m_idx++]);
+    atom = ((x[0]) | (x[1] << 8));
+    return *this;
+}
+I::IStream& ByteMemoryInStream::operator>> (unsigned short &atom) {
+    short s{};
+    *this >> s;
+    atom = static_cast<unsigned short>(s);
+    return *this;
+}
+I::IStream& ByteMemoryInStream::operator>> (int& atom) {
+    static_assert(sizeof(int) == 4, "Expecting sizeof(int) == 4");
+    atom = static_cast<int>(getU32());
+    return *this;
+}
+//I::IStream& ByteMemoryInStream::operator>> (std::size_t& atom) {
+//    // NB. Type was truncated!
+//    atom = static_cast<std::size_t>(getU32());
+//    return *this;
+//}
+I::IStream& ByteMemoryInStream::operator>> (float& atom) {
+    static_assert(sizeof(float) == 4, "Expecting sizeof(float) == 4");
+    uint32_t tmp = ntohl(getU32());
+    memcpy(&atom, &tmp, sizeof(float));
+    return *this;
+}
+I::IStream& ByteMemoryInStream::operator>> (double& atom) {
+    static_assert(sizeof(double) == 8, "Expecting sizeof(double) == 8");
+    uint32_t tmp[2] = {ntohl(getU32()), ntohl(getU32())};
+    memcpy(&atom, tmp, sizeof(double));
+    return *this;
+}
+I::IStream& ByteMemoryInStream::operator>> (std::string& str) {
+    //std::size_t sz = 0u;
+    uint32_t sz = 0u;
+    *this >> sz;
+    if (sz == 0u) {
+        str.clear();
+    } else {
+        str.resize(sz);
+        for (auto &&i : ade::util::iota(sz)) { *this >> str[i]; }
+    }
+    return *this;
+}
+
+GAPI_EXPORTS void serialize(I::OStream& os, const cv::GMetaArgs &ma) {
+    os << ma;
+}
+GAPI_EXPORTS void serialize(I::OStream& os, const cv::GRunArgs &ra) {
+    os << ra;
+}
+GAPI_EXPORTS GMetaArgs meta_args_deserialize(I::IStream& is) {
+    GMetaArgs s;
+    is >> s;
+    return s;
+}
+GAPI_EXPORTS GRunArgs run_args_deserialize(I::IStream& is) {
+    GRunArgs s;
+    is >> s;
+    return s;
+}
+
+
+} // namespace s11n
+} // namespace gimpl
+} // namespace cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/serialization.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/serialization.hpp
new file mode 100644 (file)
index 0000000..9286bc4
--- /dev/null
@@ -0,0 +1,373 @@
+#ifndef OPENCV_GAPI_COMMON_SERIALIZATION_HPP
+#define OPENCV_GAPI_COMMON_SERIALIZATION_HPP
+
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include <iostream>
+#include <fstream>
+#include <string.h>
+
+#include <ade/util/iota_range.hpp> // used in the vector<</>>
+
+#include "compiler/gmodel.hpp"
+#include "opencv2/gapi/render/render_types.hpp"
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+#pragma warning(disable: 4702)
+#endif
+
+namespace cv {
+namespace gimpl {
+namespace s11n {
+
+struct GSerialized {
+    std::vector<cv::gimpl::Op> m_ops;
+    std::vector<cv::gimpl::Data> m_datas;
+    cv::gimpl::DataObjectCounter m_counter;
+    cv::gimpl::Protocol m_proto;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Stream interfaces, so far temporary
+namespace I {
+    struct GAPI_EXPORTS OStream {
+        virtual ~OStream() = default;
+
+        // Define the native support for basic C++ types at the API level:
+        virtual OStream& operator<< (bool) = 0;
+        virtual OStream& operator<< (char) = 0;
+        virtual OStream& operator<< (unsigned char) = 0;
+        virtual OStream& operator<< (short) = 0;
+        virtual OStream& operator<< (unsigned short) = 0;
+        virtual OStream& operator<< (int) = 0;
+        //virtual OStream& operator<< (std::size_t) = 0;
+        virtual OStream& operator<< (uint32_t) = 0;
+        virtual OStream& operator<< (float) = 0;
+        virtual OStream& operator<< (double) = 0;
+        virtual OStream& operator<< (const std::string&) = 0;
+    };
+
+    struct GAPI_EXPORTS IStream {
+        virtual ~IStream() = default;
+
+        virtual IStream& operator>> (bool &) = 0;
+        virtual IStream& operator>> (char &) = 0;
+        virtual IStream& operator>> (unsigned char &) = 0;
+        virtual IStream& operator>> (short &) = 0;
+        virtual IStream& operator>> (unsigned short &) = 0;
+        virtual IStream& operator>> (int &) = 0;
+        virtual IStream& operator>> (float &) = 0;
+        virtual IStream& operator>> (double &) = 0;
+        //virtual IStream& operator>> (std::size_t &) = 0;
+        virtual IStream& operator >> (uint32_t &) = 0;
+        virtual IStream& operator>> (std::string &) = 0;
+    };
+} // namespace I
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// S11N operators
+// Note: operators for basic types are defined in IStream/OStream
+
+// OpenCV types ////////////////////////////////////////////////////////////////
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Point &pt);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::Point &pt);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Size &sz);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::Size &sz);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Rect &rc);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::Rect &rc);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Scalar &s);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::Scalar &s);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Mat &m);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::Mat &m);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Text &t);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Text &t);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream&, const cv::gapi::wip::draw::FText &);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream&,       cv::gapi::wip::draw::FText &);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Circle &c);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Circle &c);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Rect &r);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Rect &r);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Image &i);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Image &i);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Mosaic &m);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Mosaic &m);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Poly &p);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Poly &p);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Line &l);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::draw::Line &l);
+
+// G-API types /////////////////////////////////////////////////////////////////
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::util::monostate  );
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::util::monostate &);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::GShape  shape);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::GShape &shape);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::detail::ArgKind  k);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::detail::ArgKind &k);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::detail::OpaqueKind  k);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::detail::OpaqueKind &k);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, cv::gimpl::Data::Storage  s);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gimpl::Data::Storage &s);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::DataObjectCounter &c);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gimpl::DataObjectCounter &c);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::Protocol &p);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gimpl::Protocol &p);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GArg &arg);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::GArg &arg);
+
+//Forward declaration
+//I::OStream& operator<< (I::OStream& os, const cv::GRunArg &arg);
+//I::IStream& operator>> (I::IStream& is, cv::GRunArg &arg);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GKernel &k);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::GKernel &k);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GMatDesc &d);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::GMatDesc &d);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GScalarDesc &);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::GScalarDesc &);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GOpaqueDesc &);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::GOpaqueDesc &);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::GArrayDesc &);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::GArrayDesc &);
+
+#if !defined(GAPI_STANDALONE)
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::UMat &);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::UMat &);
+#endif // !defined(GAPI_STANDALONE)
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::IStreamSource::Ptr &);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gapi::wip::IStreamSource::Ptr &);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::detail::VectorRef &);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::detail::VectorRef &);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::detail::OpaqueRef &);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::detail::OpaqueRef &);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::RcDesc &rc);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gimpl::RcDesc &rc);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::Op &op);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gimpl::Op &op);
+
+GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gimpl::Data &op);
+GAPI_EXPORTS I::IStream& operator>> (I::IStream& is,       cv::gimpl::Data &op);
+
+// The top-level serialization routine.
+// Note it is just a single function which takes a GModel and a list of nodes
+// and writes the data to the stream (recursively)
+GAPI_EXPORTS void serialize( I::OStream& os
+                           , const ade::Graph &g
+                           , const std::vector<ade::NodeHandle> &nodes);
+
+// The top-level serialization routine.
+// Note it is just a single function which takes a GModel and a list of nodes
+// and writes the data to the stream (recursively)
+GAPI_EXPORTS void serialize( I::OStream& os
+                           , const ade::Graph &g
+                           , const cv::gimpl::Protocol &p
+                           , const std::vector<ade::NodeHandle> &nodes);
+
+// The top-level deserialization routineS.
+// Unfortunately the deserialization is a two-step process:
+// 1. First we decode a stream into some intermediate representation
+//     (called "GSerialized");
+// 2. Then we produce an ade::Graph from this intermediate representation.
+//
+// An ade::Graph can't be produced from the stream immediately
+// since every GCompiled object has its own unique ade::Graph, so
+// we can't do it once and for all since every compilation process
+// is individual and _is_ altering the ade::Graph state (structure and metadata).
+// At the same time, we can't hold the reference to "is" within the GComputation
+// forever since this input stream may be associated with an external resource
+// and have side effects.
+//
+// Summarizing, the `deserialize()` happens *once per GComputation* immediately
+// during the cv::gapi::deserialize<GComputation>(), and `reconstruct()` happens
+// on every compilation process issued for this GComputation.
+GAPI_EXPORTS GSerialized deserialize(I::IStream& is);
+GAPI_EXPORTS void reconstruct(const GSerialized &s, ade::Graph &g);
+
+// Legacy //////////////////////////////////////////////////////////////////////
+// Generic: unordered_map serialization ////////////////////////////////////////
+template<typename K, typename V>
+I::OStream& operator<< (I::OStream& os, const std::unordered_map<K, V> &m) {
+    //const std::size_t sz = m.size(); // explicitly specify type
+    const uint32_t sz = (uint32_t)m.size(); // explicitly specify type
+    os << sz;
+    for (auto &&it : m) os << it.first << it.second;
+    return os;
+}
+template<typename K, typename V>
+I::IStream& operator>> (I::IStream& is, std::unordered_map<K, V> &m) {
+    m.clear();
+    //std::size_t sz = 0u;
+    uint32_t sz = 0u;
+    is >> sz;
+    if (sz != 0u) {
+        for (auto &&i : ade::util::iota(sz)) {
+            (void) i;
+            K k{};
+            V v{};
+            is >> k >> v;
+            m.insert({k,v});
+        }
+        GAPI_Assert(sz == m.size());
+    }
+    return is;
+}
+
+// Generic: variant serialization //////////////////////////////////////////////
+namespace detail { // FIXME: breaks old code
+template<typename V>
+I::OStream& put_v(I::OStream&, const V&, std::size_t) {
+    GAPI_Assert(false && "variant>>: requested index is invalid");
+};
+template<typename V, typename X, typename... Xs>
+I::OStream& put_v(I::OStream& os, const V& v, std::size_t x) {
+    return (x == 0u)
+        ? os << cv::util::get<X>(v)
+        : put_v<V, Xs...>(os, v, x-1);
+}
+template<typename V>
+I::IStream& get_v(I::IStream&, V&, std::size_t, std::size_t) {
+    GAPI_Assert(false && "variant<<: requested index is invalid");
+}
+template<typename V, typename X, typename... Xs>
+I::IStream& get_v(I::IStream& is, V& v, std::size_t i, std::size_t gi) {
+    if (i == gi) {
+        X x{};
+        is >> x;
+        v = std::move(x);
+        return is;
+    } else return get_v<V, Xs...>(is, v, i+1, gi);
+}
+} // namespace detail FIXME: breaks old code
+
+template<typename... Ts>
+I::OStream& operator<< (I::OStream& os, const cv::util::variant<Ts...> &v) {
+    os << (uint32_t)v.index();
+    return detail::put_v<cv::util::variant<Ts...>, Ts...>(os, v, v.index());
+}
+template<typename... Ts>
+I::IStream& operator>> (I::IStream& is, cv::util::variant<Ts...> &v) {
+    int idx = -1;
+    is >> idx;
+    GAPI_Assert(idx >= 0 && idx < (int)sizeof...(Ts));
+    return detail::get_v<cv::util::variant<Ts...>, Ts...>(is, v, 0u, idx);
+}
+
+// Generic: vector serialization ///////////////////////////////////////////////
+// Moved here to fix CLang issues https://clang.llvm.org/compatibility.html
+// Unqualified lookup in templates
+template<typename T>
+I::OStream& operator<< (I::OStream& os, const std::vector<T> &ts) {
+    //const std::size_t sz = ts.size(); // explicitly specify type
+    const uint32_t sz = (uint32_t)ts.size(); // explicitly specify type
+    os << sz;
+    for (auto &&v : ts) os << v;
+    return os;
+}
+template<typename T>
+I::IStream& operator >> (I::IStream& is, std::vector<T> &ts) {
+    //std::size_t sz = 0u;
+    uint32_t sz = 0u;
+    is >> sz;
+    if (sz == 0u) {
+        ts.clear();
+    }
+    else {
+        ts.resize(sz);
+        for (auto &&i : ade::util::iota(sz)) is >> ts[i];
+    }
+    return is;
+}
+
+// FIXME: Basic Stream implementaions //////////////////////////////////////////
+
+// Basic in-memory stream implementations.
+class GAPI_EXPORTS ByteMemoryOutStream final: public I::OStream {
+    std::vector<char> m_storage;
+
+    //virtual I::OStream& operator << (uint32_t) override;
+    //virtual I::OStream& operator<< (uint32_t) final;
+public:
+    const std::vector<char>& data() const;
+
+    virtual I::OStream& operator<< (bool) override;
+    virtual I::OStream& operator<< (char) override;
+    virtual I::OStream& operator<< (unsigned char) override;
+    virtual I::OStream& operator<< (short) override;
+    virtual I::OStream& operator<< (unsigned short) override;
+    virtual I::OStream& operator<< (int) override;
+    //virtual I::OStream& operator<< (std::size_t) override;
+    virtual I::OStream& operator<< (float) override;
+    virtual I::OStream& operator<< (double) override;
+    virtual I::OStream& operator<< (const std::string&) override;
+    virtual I::OStream& operator<< (uint32_t) override;
+};
+
+class GAPI_EXPORTS ByteMemoryInStream final: public I::IStream {
+    const std::vector<char>& m_storage;
+    size_t m_idx = 0u;
+
+    void check(std::size_t n) { (void) n; GAPI_DbgAssert(m_idx+n-1 < m_storage.size()); }
+    uint32_t getU32() { uint32_t v{}; *this >> v; return v; };
+
+    //virtual I::IStream& operator>> (uint32_t &) final;
+
+public:
+    explicit ByteMemoryInStream(const std::vector<char> &data);
+
+    virtual I::IStream& operator>> (bool &) override;
+    virtual I::IStream& operator>> (char &) override;
+    virtual I::IStream& operator>> (unsigned char &) override;
+    virtual I::IStream& operator>> (short &) override;
+    virtual I::IStream& operator>> (unsigned short &) override;
+    virtual I::IStream& operator>> (int &) override;
+    virtual I::IStream& operator>> (float &) override;
+    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>> (std::string &) override;
+};
+
+GAPI_EXPORTS void serialize(I::OStream& os, const cv::GMetaArgs &ma);
+GAPI_EXPORTS void serialize(I::OStream& os, const cv::GRunArgs &ra);
+GAPI_EXPORTS GMetaArgs meta_args_deserialize(I::IStream& is);
+GAPI_EXPORTS GRunArgs run_args_deserialize(I::IStream& is);
+
+} // namespace s11n
+} // namespace gimpl
+} // namespace cv
+
+#endif // OPENCV_GAPI_COMMON_SERIALIZATION_HPP
index 29310ee..780c0e9 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
 //
 // If not, we need to introduce that!
 using GCPUModel = ade::TypedGraph
-    < cv::gimpl::Unit
+    < cv::gimpl::CPUUnit
     , cv::gimpl::Protocol
     >;
 
 // FIXME: Same issue with Typed and ConstTyped
 using GConstGCPUModel = ade::ConstTypedGraph
-    < cv::gimpl::Unit
+    < cv::gimpl::CPUUnit
     , cv::gimpl::Protocol
     >;
 
@@ -53,14 +53,14 @@ namespace
         {
             GCPUModel gm(graph);
             auto cpu_impl = cv::util::any_cast<cv::GCPUKernel>(impl.opaque);
-            gm.metadata(op_node).set(cv::gimpl::Unit{cpu_impl});
+            gm.metadata(op_node).set(cv::gimpl::CPUUnit{cpu_impl});
         }
 
         virtual EPtr compile(const ade::Graph &graph,
-                             const cv::GCompileArgs &,
+                             const cv::GCompileArgs &compileArgs,
                              const std::vector<ade::NodeHandle> &nodes) const override
         {
-            return EPtr{new cv::gimpl::GCPUExecutable(graph, nodes)};
+            return EPtr{new cv::gimpl::GCPUExecutable(graph, compileArgs, nodes)};
         }
    };
 }
@@ -73,16 +73,29 @@ cv::gapi::GBackend cv::gapi::cpu::backend()
 
 // GCPUExecutable implementation //////////////////////////////////////////////
 cv::gimpl::GCPUExecutable::GCPUExecutable(const ade::Graph &g,
+                                          const cv::GCompileArgs &compileArgs,
                                           const std::vector<ade::NodeHandle> &nodes)
-    : m_g(g), m_gm(m_g)
+    : m_g(g), m_gm(m_g), m_compileArgs(compileArgs)
 {
     // Convert list of operations (which is topologically sorted already)
     // into an execution script.
+    GConstGCPUModel gcm(m_g);
     for (auto &nh : nodes)
     {
         switch (m_gm.metadata(nh).get<NodeType>().t)
         {
-        case NodeType::OP: m_script.push_back({nh, GModel::collectOutputMeta(m_gm, nh)}); break;
+        case NodeType::OP:
+        {
+            m_script.push_back({nh, GModel::collectOutputMeta(m_gm, nh)});
+
+            // If kernel is stateful then prepare storage for its state.
+            GCPUKernel k = gcm.metadata(nh).get<CPUUnit>().k;
+            if (k.m_isStateful)
+            {
+                m_nodesToStates[nh] = GArg{ };
+            }
+            break;
+        }
         case NodeType::DATA:
         {
             m_dataNodes.push_back(nh);
@@ -96,7 +109,7 @@ cv::gimpl::GCPUExecutable::GCPUExecutable(const ade::Graph &g,
             if (desc.storage == Data::Storage::INTERNAL && desc.shape == GShape::GMAT)
             {
                 const auto mat_desc = util::get<cv::GMatDesc>(desc.meta);
-                auto& mat = m_res.slot<cv::gapi::own::Mat>()[desc.rc];
+                auto& mat = m_res.slot<cv::Mat>()[desc.rc];
                 createMat(mat_desc, mat);
             }
             break;
@@ -104,6 +117,9 @@ cv::gimpl::GCPUExecutable::GCPUExecutable(const ade::Graph &g,
         default: util::throw_error(std::logic_error("Unsupported NodeType type"));
         }
     }
+
+    // For each stateful kernel call 'setup' user callback to initialize state.
+    setupKernelStates();
 }
 
 // FIXME: Document what it does
@@ -128,7 +144,7 @@ cv::GArg cv::gimpl::GCPUExecutable::packArg(const GArg &arg)
     const cv::gimpl::RcDesc &ref = arg.get<cv::gimpl::RcDesc>();
     switch (ref.shape)
     {
-    case GShape::GMAT:    return GArg(m_res.slot<cv::gapi::own::Mat>()   [ref.id]);
+    case GShape::GMAT:    return GArg(m_res.slot<cv::Mat>()   [ref.id]);
     case GShape::GSCALAR: return GArg(m_res.slot<cv::Scalar>()[ref.id]);
     // Note: .at() is intentional for GArray and GOpaque as objects MUST be already there
     //   (and constructed by either bindIn/Out or resetInternal)
@@ -140,6 +156,27 @@ cv::GArg cv::gimpl::GCPUExecutable::packArg(const GArg &arg)
     }
 }
 
+void cv::gimpl::GCPUExecutable::setupKernelStates()
+{
+    GConstGCPUModel gcm(m_g);
+    for (auto& nodeToState : m_nodesToStates)
+    {
+        auto& kernelNode = nodeToState.first;
+        auto& kernelState = nodeToState.second;
+
+        const GCPUKernel& kernel = gcm.metadata(kernelNode).get<CPUUnit>().k;
+        kernel.m_setupF(GModel::collectInputMeta(m_gm, kernelNode),
+                        m_gm.metadata(kernelNode).get<Op>().args,
+                        kernelState,
+                        m_compileArgs);
+    }
+}
+
+void cv::gimpl::GCPUExecutable::handleNewStream()
+{
+    m_newStreamStarted = true;
+}
+
 void cv::gimpl::GCPUExecutable::run(std::vector<InObj>  &&input_objs,
                                     std::vector<OutObj> &&output_objs)
 {
@@ -157,7 +194,7 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj>  &&input_objs,
     {
         const auto &desc = gm.metadata(nh).get<Data>();
 
-        if (   desc.storage == Data::Storage::INTERNAL
+        if (   desc.storage == Data::Storage::INTERNAL               // FIXME: to reconsider
             && !util::holds_alternative<util::monostate>(desc.ctor))
         {
             // FIXME: Note that compile-time constant data objects (like
@@ -167,6 +204,14 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj>  &&input_objs,
         }
     }
 
+    // In case if new video-stream happens - for each stateful kernel
+    // call 'setup' user callback to re-initialize state.
+    if (m_newStreamStarted)
+    {
+        setupKernelStates();
+        m_newStreamStarted = false;
+    }
+
     // OpenCV backend execution is not a rocket science at all.
     // Simply invoke our kernels in the proper order.
     GConstGCPUModel gcm(m_g);
@@ -176,7 +221,7 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj>  &&input_objs,
 
         // Obtain our real execution unit
         // TODO: Should kernels be copyable?
-        GCPUKernel k = gcm.metadata(op_info.nh).get<Unit>().k;
+        GCPUKernel k = gcm.metadata(op_info.nh).get<CPUUnit>().k;
 
         // Initialize kernel's execution context:
         // - Input parameters
@@ -185,8 +230,8 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj>  &&input_objs,
 
         using namespace std::placeholders;
         ade::util::transform(op.args,
-                          std::back_inserter(context.m_args),
-                          std::bind(&GCPUExecutable::packArg, this, _1));
+                             std::back_inserter(context.m_args),
+                             std::bind(&GCPUExecutable::packArg, this, _1));
 
         // - Output parameters.
         // FIXME: pre-allocate internal Mats, etc, according to the known meta
@@ -198,8 +243,14 @@ void cv::gimpl::GCPUExecutable::run(std::vector<InObj>  &&input_objs,
             context.m_results[out_port] = magazine::getObjPtr(m_res, out_desc);
         }
 
+        // For stateful kernel add state to its execution context
+        if (k.m_isStateful)
+        {
+            context.m_state = m_nodesToStates.at(op_info.nh);
+        }
+
         // Now trigger the executable unit
-        k.apply(context);
+        k.m_runF(context);
 
         //As Kernels are forbidden to allocate memory for (Mat) outputs,
         //this code seems redundant, at least for Mats
index 28cffa1..6328da0 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GCPUBACKEND_HPP
@@ -23,7 +23,7 @@
 
 namespace cv { namespace gimpl {
 
-struct Unit
+struct CPUUnit
 {
     static const char *name() { return "HostKernel"; }
     GCPUKernel k;
@@ -33,6 +33,7 @@ class GCPUExecutable final: public GIslandExecutable
 {
     const ade::Graph &m_g;
     GModel::ConstGraph m_gm;
+    const cv::GCompileArgs m_compileArgs;
 
     struct OperationInfo
     {
@@ -42,15 +43,27 @@ class GCPUExecutable final: public GIslandExecutable
 
     // Execution script, currently absolutely naive
     std::vector<OperationInfo> m_script;
+
+    // TODO: Check that it is thread-safe
+    // Map of stateful kernel nodes to their kernels' states
+    std::unordered_map<ade::NodeHandle, GArg,
+                       ade::HandleHasher<ade::Node>> m_nodesToStates;
+
     // List of all resources in graph (both internal and external)
     std::vector<ade::NodeHandle> m_dataNodes;
 
     // Actual data of all resources in graph (both internal and external)
     Mag m_res;
+
+    // Flag which identifies if new stream was started
+    bool m_newStreamStarted = false;
+
     GArg packArg(const GArg &arg);
+    void setupKernelStates();
 
 public:
     GCPUExecutable(const ade::Graph                   &graph,
+                   const cv::GCompileArgs             &compileArgs,
                    const std::vector<ade::NodeHandle> &nodes);
 
     virtual inline bool canReshape() const override { return false; }
@@ -62,6 +75,8 @@ public:
         util::throw_error(std::logic_error("GCPUExecutable::reshape() should never be called"));
     }
 
+    virtual void handleNewStream() override;
+
     virtual void run(std::vector<InObj>  &&input_objs,
                      std::vector<OutObj> &&output_objs) override;
 };
index bf2d034..d9c3c3a 100644 (file)
@@ -6,6 +6,7 @@
 
 
 #include "precomp.hpp"
+#include "gnnparsers.hpp"
 
 #include <opencv2/gapi/core.hpp>
 #include <opencv2/gapi/cpu/core.hpp>
@@ -576,6 +577,63 @@ GAPI_OCV_KERNEL(GCPUWarpAffine, cv::gapi::core::GWarpAffine)
     }
 };
 
+GAPI_OCV_KERNEL(GCPUParseSSDBL, cv::gapi::nn::parsers::GParseSSDBL)
+{
+    static void run(const cv::Mat&  in_ssd_result,
+                    const cv::Size& in_size,
+                    const float     confidence_threshold,
+                    const int       filter_label,
+                    std::vector<cv::Rect>& out_boxes,
+                    std::vector<int>&      out_labels)
+    {
+        cv::parseSSDBL(in_ssd_result, in_size, confidence_threshold, filter_label, out_boxes, out_labels);
+    }
+};
+
+GAPI_OCV_KERNEL(GOCVParseSSD, cv::gapi::nn::parsers::GParseSSD)
+{
+    static void run(const cv::Mat&  in_ssd_result,
+                    const cv::Size& in_size,
+                    const float     confidence_threshold,
+                    const bool      alignment_to_square,
+                    const bool      filter_out_of_bounds,
+                    std::vector<cv::Rect>& out_boxes)
+    {
+        cv::parseSSD(in_ssd_result, in_size, confidence_threshold, alignment_to_square, filter_out_of_bounds, out_boxes);
+    }
+};
+
+GAPI_OCV_KERNEL(GCPUParseYolo, cv::gapi::nn::parsers::GParseYolo)
+{
+    static void run(const cv::Mat&  in_yolo_result,
+                    const cv::Size& in_size,
+                    const float     confidence_threshold,
+                    const float     nms_threshold,
+                    const std::vector<float>& anchors,
+                    std::vector<cv::Rect>& out_boxes,
+                    std::vector<int>&      out_labels)
+    {
+        cv::parseYolo(in_yolo_result, in_size, confidence_threshold, nms_threshold, anchors, out_boxes, out_labels);
+    }
+};
+
+GAPI_OCV_KERNEL(GCPUSize, cv::gapi::core::GSize)
+{
+    static void run(const cv::Mat& in, cv::Size& out)
+    {
+        out.width  = in.cols;
+        out.height = in.rows;
+    }
+};
+
+GAPI_OCV_KERNEL(GCPUSizeR, cv::gapi::core::GSizeR)
+{
+    static void run(const cv::Rect& in, cv::Size& out)
+    {
+        out.width  = in.width;
+        out.height = in.height;
+    }
+};
 
 cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
 {
@@ -647,6 +705,11 @@ cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
          , GCPUNormalize
          , GCPUWarpPerspective
          , GCPUWarpAffine
+         , GCPUParseSSDBL
+         , GOCVParseSSD
+         , GCPUParseYolo
+         , GCPUSize
+         , GCPUSizeR
          >();
     return pkg;
 }
index 29328c4..8104565 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -166,6 +166,24 @@ GAPI_OCV_KERNEL(GCPUSobelXY, cv::gapi::imgproc::GSobelXY)
     }
 };
 
+GAPI_OCV_KERNEL(GCPULaplacian, cv::gapi::imgproc::GLaplacian)
+{
+    static void run(const cv::Mat& in, int ddepth, int ksize, double scale,
+                    double delta, int borderType, cv::Mat &out)
+    {
+        cv::Laplacian(in, out, ddepth, ksize, scale, delta, borderType);
+    }
+};
+
+GAPI_OCV_KERNEL(GCPUBilateralFilter, cv::gapi::imgproc::GBilateralFilter)
+{
+    static void run(const cv::Mat& in, int d, double sigmaColor,
+                    double sigmaSpace, int borderType, cv::Mat &out)
+    {
+        cv::bilateralFilter(in, out, d, sigmaColor, sigmaSpace, borderType);
+    }
+};
+
 GAPI_OCV_KERNEL(GCPUEqualizeHist, cv::gapi::imgproc::GEqHist)
 {
     static void run(const cv::Mat& in, cv::Mat &out)
@@ -182,6 +200,17 @@ GAPI_OCV_KERNEL(GCPUCanny, cv::gapi::imgproc::GCanny)
     }
 };
 
+GAPI_OCV_KERNEL(GCPUGoodFeatures, cv::gapi::imgproc::GGoodFeatures)
+{
+    static void run(const cv::Mat& image, int maxCorners, double qualityLevel, double minDistance,
+                    const cv::Mat& mask, int blockSize, bool useHarrisDetector, double k,
+                    std::vector<cv::Point2f> &out)
+    {
+        cv::goodFeaturesToTrack(image, out, maxCorners, qualityLevel, minDistance,
+                                mask, blockSize, useHarrisDetector, k);
+    }
+};
+
 GAPI_OCV_KERNEL(GCPURGB2YUV, cv::gapi::imgproc::GRGB2YUV)
 {
     static void run(const cv::Mat& in, cv::Mat &out)
@@ -411,7 +440,10 @@ cv::gapi::GKernelPackage cv::gapi::imgproc::cpu::kernels()
         , GCPUDilate
         , GCPUSobel
         , GCPUSobelXY
+        , GCPULaplacian
+        , GCPUBilateralFilter
         , GCPUCanny
+        , GCPUGoodFeatures
         , GCPUEqualizeHist
         , GCPURGB2YUV
         , GCPUYUV2RGB
index 238ced2..0d8d737 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
 
 #include <opencv2/gapi/cpu/gcpukernel.hpp>
 
-const cv::gapi::own::Mat& cv::GCPUContext::inMat(int input)
+const cv::Mat& cv::GCPUContext::inMat(int input)
 {
-    return inArg<cv::gapi::own::Mat>(input);
+    return inArg<cv::Mat>(input);
 }
 
-cv::gapi::own::Mat&  cv::GCPUContext::outMatR(int output)
+cv::Mat&  cv::GCPUContext::outMatR(int output)
 {
-    return *util::get<cv::gapi::own::Mat*>(m_results.at(output));
+    return *util::get<cv::Mat*>(m_results.at(output));
 }
 
 const cv::Scalar& cv::GCPUContext::inVal(int input)
@@ -45,13 +45,7 @@ cv::GCPUKernel::GCPUKernel()
 {
 }
 
-cv::GCPUKernel::GCPUKernel(const GCPUKernel::F &f)
-    : m_f(f)
+cv::GCPUKernel::GCPUKernel(const GCPUKernel::RunF &runF, const GCPUKernel::SetupF &setupF)
+    : m_runF(runF), m_setupF(setupF), m_isStateful(m_setupF != nullptr)
 {
 }
-
-void cv::GCPUKernel::apply(GCPUContext &ctx)
-{
-    GAPI_Assert(m_f);
-    m_f(ctx);
-}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuvideo.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuvideo.cpp
new file mode 100644 (file)
index 0000000..ac8e9e4
--- /dev/null
@@ -0,0 +1,100 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <opencv2/gapi/video.hpp>
+#include <opencv2/gapi/cpu/video.hpp>
+#include <opencv2/gapi/cpu/gcpukernel.hpp>
+
+#ifdef HAVE_OPENCV_VIDEO
+#include <opencv2/video.hpp>
+#endif // HAVE_OPENCV_VIDEO
+
+#ifdef HAVE_OPENCV_VIDEO
+
+GAPI_OCV_KERNEL(GCPUBuildOptFlowPyramid, cv::gapi::video::GBuildOptFlowPyramid)
+{
+    static void run(const cv::Mat              &img,
+                    const cv::Size             &winSize,
+                    const cv::Scalar           &maxLevel,
+                          bool                  withDerivatives,
+                          int                   pyrBorder,
+                          int                   derivBorder,
+                          bool                  tryReuseInputImage,
+                          std::vector<cv::Mat> &outPyr,
+                          cv::Scalar           &outMaxLevel)
+    {
+        outMaxLevel = cv::buildOpticalFlowPyramid(img, outPyr, winSize,
+                                                  static_cast<int>(maxLevel[0]),
+                                                  withDerivatives, pyrBorder,
+                                                  derivBorder, tryReuseInputImage);
+    }
+};
+
+GAPI_OCV_KERNEL(GCPUCalcOptFlowLK, cv::gapi::video::GCalcOptFlowLK)
+{
+    static void run(const cv::Mat                  &prevImg,
+                    const cv::Mat                  &nextImg,
+                    const std::vector<cv::Point2f> &prevPts,
+                    const std::vector<cv::Point2f> &predPts,
+                    const cv::Size                 &winSize,
+                    const cv::Scalar               &maxLevel,
+                    const cv::TermCriteria         &criteria,
+                          int                       flags,
+                          double                    minEigThresh,
+                          std::vector<cv::Point2f> &outPts,
+                          std::vector<uchar>       &status,
+                          std::vector<float>       &err)
+    {
+        if (flags & cv::OPTFLOW_USE_INITIAL_FLOW)
+            outPts = predPts;
+        cv::calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, outPts, status, err, winSize,
+                                 static_cast<int>(maxLevel[0]), criteria, flags, minEigThresh);
+    }
+};
+
+GAPI_OCV_KERNEL(GCPUCalcOptFlowLKForPyr, cv::gapi::video::GCalcOptFlowLKForPyr)
+{
+    static void run(const std::vector<cv::Mat>     &prevPyr,
+                    const std::vector<cv::Mat>     &nextPyr,
+                    const std::vector<cv::Point2f> &prevPts,
+                    const std::vector<cv::Point2f> &predPts,
+                    const cv::Size                 &winSize,
+                    const cv::Scalar               &maxLevel,
+                    const cv::TermCriteria         &criteria,
+                          int                       flags,
+                          double                    minEigThresh,
+                          std::vector<cv::Point2f> &outPts,
+                          std::vector<uchar>       &status,
+                          std::vector<float>       &err)
+    {
+        if (flags & cv::OPTFLOW_USE_INITIAL_FLOW)
+            outPts = predPts;
+        cv::calcOpticalFlowPyrLK(prevPyr, nextPyr, prevPts, outPts, status, err, winSize,
+                                 static_cast<int>(maxLevel[0]), criteria, flags, minEigThresh);
+    }
+};
+
+cv::gapi::GKernelPackage cv::gapi::video::cpu::kernels()
+{
+    static auto pkg = cv::gapi::kernels
+        < GCPUBuildOptFlowPyramid
+        , GCPUCalcOptFlowLK
+        , GCPUCalcOptFlowLKForPyr
+        >();
+    return pkg;
+}
+
+#else
+
+cv::gapi::GKernelPackage cv::gapi::video::cpu::kernels()
+{
+    return GKernelPackage();
+}
+
+#endif // HAVE_OPENCV_VIDEO
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gnnparsers.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gnnparsers.cpp
new file mode 100644 (file)
index 0000000..234382d
--- /dev/null
@@ -0,0 +1,338 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include "gnnparsers.hpp"
+
+namespace cv
+{
+namespace gapi
+{
+namespace nn
+{
+class YoloParser
+{
+public:
+    YoloParser(const float* out, const int side, const int lcoords, const int lclasses)
+        : m_out(out), m_side(side), m_lcoords(lcoords), m_lclasses(lclasses)
+    {}
+
+    float scale(const int i, const int b)
+    {
+        int obj_index = index(i, b, m_lcoords);
+        return m_out[obj_index];
+    }
+
+    double x(const int i, const int b)
+    {
+        int box_index = index(i, b, 0);
+        int col = i % m_side;
+        return (col + m_out[box_index]) / m_side;
+    }
+
+    double y(const int i, const int b)
+    {
+        int box_index = index(i, b, 0);
+        int row = i / m_side;
+        return (row + m_out[box_index + m_side * m_side]) / m_side;
+    }
+
+    double width(const int i, const int b, const float anchor)
+    {
+        int box_index = index(i, b, 0);
+        return std::exp(m_out[box_index + 2 * m_side * m_side]) * anchor / m_side;
+    }
+
+    double height(const int i, const int b, const float anchor)
+    {
+        int box_index = index(i, b, 0);
+        return std::exp(m_out[box_index + 3 * m_side * m_side]) * anchor / m_side;
+    }
+
+    float classConf(const int i, const int b, const int label)
+    {
+         int class_index = index(i, b, m_lcoords + 1 + label);
+         return m_out[class_index];
+    }
+
+    cv::Rect toBox(const double x, const double y, const double h, const double w, const cv::Size& in_sz)
+    {
+        auto h_scale = in_sz.height;
+        auto w_scale = in_sz.width;
+        cv::Rect r;
+        r.x = static_cast<int>((x - w / 2) * w_scale);
+        r.y = static_cast<int>((y - h / 2) * h_scale);
+        r.width = static_cast<int>(w * w_scale);
+        r.height = static_cast<int>(h * h_scale);
+        return r;
+    }
+
+private:
+    const float* m_out = nullptr;
+    int m_side = 0, m_lcoords = 0, m_lclasses = 0;
+
+    int index(const int i, const int b, const int entry)
+    {
+        return b * m_side * m_side * (m_lcoords + m_lclasses + 1) + entry * m_side * m_side + i;
+    }
+};
+
+struct YoloParams
+{
+    int    num = 5;
+    int coords = 4;
+};
+
+struct Detection
+{
+    Detection(const cv::Rect& in_rect, const float in_conf, const int in_label)
+        : rect(in_rect), conf(in_conf), label(in_label)
+    {}
+    cv::Rect rect;
+    float    conf = 0.0f;
+    int      label = 0;
+};
+
+class SSDParser
+{
+public:
+    SSDParser(const cv::MatSize& in_ssd_dims, const cv::Size& in_size, const float* data)
+        : m_dims(in_ssd_dims), m_maxProp(in_ssd_dims[2]), m_objSize(in_ssd_dims[3]),
+          m_data(data), m_surface(cv::Rect({0,0}, in_size)), m_size(in_size)
+    {
+        GAPI_Assert(in_ssd_dims.dims() == 4u); // Fixed output layout
+        GAPI_Assert(m_objSize  == 7);          // Fixed SSD object size
+    }
+
+    void adjustBoundingBox(cv::Rect& boundingBox)
+    {
+        auto w = boundingBox.width;
+        auto h = boundingBox.height;
+
+        boundingBox.x -= static_cast<int>(0.067 * w);
+        boundingBox.y -= static_cast<int>(0.028 * h);
+
+        boundingBox.width += static_cast<int>(0.15 * w);
+        boundingBox.height += static_cast<int>(0.13 * h);
+
+        if (boundingBox.width < boundingBox.height)
+        {
+            auto dx = (boundingBox.height - boundingBox.width);
+            boundingBox.x -= dx / 2;
+            boundingBox.width += dx;
+        }
+        else
+        {
+            auto dy = (boundingBox.width - boundingBox.height);
+            boundingBox.y -= dy / 2;
+            boundingBox.height += dy;
+        }
+    }
+
+    std::tuple<cv::Rect, float, float, int> extract(const size_t step)
+    {
+        const float* it = m_data + step * m_objSize;
+        float image_id   = it[0];
+        int   label      = static_cast<int>(it[1]);
+        float confidence = it[2];
+        float rc_left    = it[3];
+        float rc_top     = it[4];
+        float rc_right   = it[5];
+        float rc_bottom  = it[6];
+
+        cv::Rect rc;  // Map relative coordinates to the original image scale
+        rc.x      = static_cast<int>(rc_left   * m_size.width);
+        rc.y      = static_cast<int>(rc_top    * m_size.height);
+        rc.width  = static_cast<int>(rc_right  * m_size.width)  - rc.x;
+        rc.height = static_cast<int>(rc_bottom * m_size.height) - rc.y;
+        return std::make_tuple(rc, image_id, confidence, label);
+    }
+
+    int getMaxProposals()
+    {
+        return m_maxProp;
+    }
+
+    cv::Rect getSurface()
+    {
+        return m_surface;
+    }
+
+private:
+    const cv::MatSize m_dims;
+    int m_maxProp = 0, m_objSize = 0;
+    const float* m_data = nullptr;
+    const cv::Rect m_surface;
+    const cv::Size m_size;
+};
+} // namespace nn
+} // namespace gapi
+
+void parseSSDBL(const cv::Mat&  in_ssd_result,
+                const cv::Size& in_size,
+                const float     confidence_threshold,
+                const int       filter_label,
+                std::vector<cv::Rect>& out_boxes,
+                std::vector<int>&      out_labels)
+{
+    cv::gapi::nn::SSDParser parser(in_ssd_result.size, in_size, in_ssd_result.ptr<float>());
+    out_boxes.clear();
+    out_labels.clear();
+    cv::Rect rc;
+    float image_id, confidence;
+    int label;
+    const size_t range = parser.getMaxProposals();
+    for (size_t i = 0; i < range; ++i)
+    {
+        std::tie(rc, image_id, confidence, label) = parser.extract(i);
+
+        if (image_id < 0.f)
+        {
+            break;    // marks end-of-detections
+        }
+
+        if (confidence < confidence_threshold ||
+            (filter_label != -1 && label != filter_label))
+        {
+            continue; // filter out object classes if filter is specified
+        }             // and skip objects with low confidence
+        out_boxes.emplace_back(rc & parser.getSurface());
+        out_labels.emplace_back(label);
+    }
+}
+
+void parseSSD(const cv::Mat&  in_ssd_result,
+              const cv::Size& in_size,
+              const float     confidence_threshold,
+              const bool      alignment_to_square,
+              const bool      filter_out_of_bounds,
+              std::vector<cv::Rect>& out_boxes)
+{
+    cv::gapi::nn::SSDParser parser(in_ssd_result.size, in_size, in_ssd_result.ptr<float>());
+    out_boxes.clear();
+    cv::Rect rc;
+    float image_id, confidence;
+    int label;
+    const size_t range = parser.getMaxProposals();
+    for (size_t i = 0; i < range; ++i)
+    {
+        std::tie(rc, image_id, confidence, label) = parser.extract(i);
+
+        if (image_id < 0.f)
+        {
+            break;    // marks end-of-detections
+        }
+        if (confidence < confidence_threshold)
+        {
+            continue; // skip objects with low confidence
+        }
+
+        if (alignment_to_square)
+        {
+            parser.adjustBoundingBox(rc);
+        }
+
+        const auto clipped_rc = rc & parser.getSurface();
+        if (filter_out_of_bounds)
+        {
+            if (clipped_rc.area() != rc.area())
+            {
+                continue;
+            }
+        }
+        out_boxes.emplace_back(clipped_rc);
+    }
+}
+
+void parseYolo(const cv::Mat&  in_yolo_result,
+               const cv::Size& in_size,
+               const float     confidence_threshold,
+               const float     nms_threshold,
+               const std::vector<float>& anchors,
+               std::vector<cv::Rect>& out_boxes,
+               std::vector<int>&      out_labels)
+{
+    const auto& dims = in_yolo_result.size;
+    GAPI_Assert(dims.dims() == 4);
+    GAPI_Assert(dims[0] == 1);
+    GAPI_Assert(dims[1] == 13);
+    GAPI_Assert(dims[2] == 13);
+    GAPI_Assert(dims[3] % 5 == 0); // 5 boxes
+    const auto num_classes = dims[3] / 5 - 5;
+    GAPI_Assert(num_classes > 0);
+    GAPI_Assert(0 < nms_threshold && nms_threshold <= 1);
+    out_boxes.clear();
+    out_labels.clear();
+    gapi::nn::YoloParams params;
+    constexpr auto side = 13;
+    constexpr auto side_square = side * side;
+    const auto output = in_yolo_result.ptr<float>();
+
+    gapi::nn::YoloParser parser(output, side, params.coords, num_classes);
+
+    std::vector<gapi::nn::Detection> detections;
+
+    for (int i = 0; i < side_square; ++i)
+    {
+        for (int b = 0; b < params.num; ++b)
+        {
+            float scale = parser.scale(i, b);
+            if (scale < confidence_threshold)
+            {
+                continue;
+            }
+            double x = parser.x(i, b);
+            double y = parser.y(i, b);
+            double height = parser.height(i, b, anchors[2 * b + 1]);
+            double width = parser.width(i, b, anchors[2 * b]);
+
+            for (int label = 0; label < num_classes; ++label)
+            {
+                float prob = scale * parser.classConf(i,b,label);
+                if (prob < confidence_threshold)
+                {
+                    continue;
+                }
+                auto box = parser.toBox(x, y, height, width, in_size);
+                detections.emplace_back(gapi::nn::Detection(box, prob, label));
+            }
+        }
+    }
+    std::stable_sort(std::begin(detections), std::end(detections),
+                     [](const gapi::nn::Detection& a, const gapi::nn::Detection& b)
+                     {
+                         return a.conf > b.conf;
+                     });
+
+    if (nms_threshold < 1.0f)
+    {
+        for (const auto& d : detections)
+        {
+            // Reject boxes which overlap with previously pushed ones
+            // (They are sorted by confidence, so rejected box
+            // always has a smaller confidence
+            if (std::end(out_boxes) ==
+                std::find_if(std::begin(out_boxes), std::end(out_boxes),
+                             [&d, nms_threshold](const cv::Rect& r)
+                             {
+                                 float rectOverlap = 1.f - static_cast<float>(jaccardDistance(r, d.rect));
+                                 return rectOverlap > nms_threshold;
+                             }))
+            {
+                out_boxes. emplace_back(d.rect);
+                out_labels.emplace_back(d.label);
+            }
+        }
+    }
+    else
+    {
+        for (const auto& d: detections)
+        {
+            out_boxes. emplace_back(d.rect);
+            out_labels.emplace_back(d.label);
+        }
+    }
+}
+} // namespace cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gnnparsers.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gnnparsers.hpp
new file mode 100644 (file)
index 0000000..2ae6693
--- /dev/null
@@ -0,0 +1,36 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include <opencv2/gapi/infer/parsers.hpp>
+
+#ifndef OPENCV_NNPARSERS_OCV_HPP
+#define OPENCV_NNPARSERS_OCV_HPP
+
+namespace cv
+{
+void parseSSDBL(const cv::Mat&  in_ssd_result,
+                const cv::Size& in_size,
+                const float     confidence_threshold,
+                const int       filter_label,
+                std::vector<cv::Rect>& out_boxes,
+                std::vector<int>&      out_labels);
+
+void parseSSD(const cv::Mat&  in_ssd_result,
+              const cv::Size& in_size,
+              const float     confidence_threshold,
+              const bool      alignment_to_square,
+              const bool      filter_out_of_bounds,
+              std::vector<cv::Rect>& out_boxes);
+
+void parseYolo(const cv::Mat&  in_yolo_result,
+               const cv::Size& in_size,
+               const float     confidence_threshold,
+               const float     nms_threshold,
+               const std::vector<float>& anchors,
+               std::vector<cv::Rect>& out_boxes,
+               std::vector<int>&      out_labels);
+}
+#endif // OPENCV_NNPARSERS_OCV_HPP
index 735e989..e103c70 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -26,7 +26,6 @@
 #include <opencv2/gapi/gcommon.hpp>
 #include "logger.hpp"
 
-#include <opencv2/gapi/own/convert.hpp>
 #include <opencv2/gapi/gmat.hpp>    //for version of descr_of
 // PRIVATE STUFF!
 #include "compiler/gobjref.hpp"
@@ -87,15 +86,15 @@ namespace
                     return gim.metadata(nh).get<NodeKind>().k == NodeKind::ISLAND;
                 });
 
-            const auto out_rois = cv::gimpl::getCompileArg<cv::GFluidOutputRois>(args);
+            const auto out_rois = cv::gapi::getCompileArg<cv::GFluidOutputRois>(args);
             if (num_islands > 1 && out_rois.has_value())
                 cv::util::throw_error(std::logic_error("GFluidOutputRois feature supports only one-island graphs"));
 
             auto rois = out_rois.value_or(cv::GFluidOutputRois());
 
             auto graph_data = fluidExtractInputDataFromGraph(graph, nodes);
-            const auto parallel_out_rois = cv::gimpl::getCompileArg<cv::GFluidParallelOutputRois>(args);
-            const auto gpfor             = cv::gimpl::getCompileArg<cv::GFluidParallelFor>(args);
+            const auto parallel_out_rois = cv::gapi::getCompileArg<cv::GFluidParallelOutputRois>(args);
+            const auto gpfor             = cv::gapi::getCompileArg<cv::GFluidParallelFor>(args);
 
 #if !defined(GAPI_STANDALONE)
             auto default_pfor = [](std::size_t count, std::function<void(std::size_t)> f){
@@ -833,7 +832,8 @@ cv::gimpl::GFluidExecutable::GFluidExecutable(const ade::Graph
       m_num_int_buffers (traverse_res.m_mat_count),
       m_scratch_users   (traverse_res.m_scratch_users),
       m_id_map          (traverse_res.m_id_map),
-      m_all_gmat_ids    (traverse_res.m_all_gmat_ids)
+      m_all_gmat_ids    (traverse_res.m_all_gmat_ids),
+      m_buffers(m_num_int_buffers + m_scratch_users.size())
 {
     GConstFluidModel fg(m_g);
 
@@ -857,9 +857,6 @@ cv::gimpl::GFluidExecutable::GFluidExecutable(const ade::Graph
     // Actually initialize Fluid buffers
     GAPI_LOG_INFO(NULL, "Initializing " << m_num_int_buffers << " fluid buffer(s)" << std::endl);
 
-    const std::size_t num_scratch = m_scratch_users.size();
-    m_buffers.resize(m_num_int_buffers + num_scratch);
-
     // After buffers are allocated, repack: ...
     for (auto &agent : m_agents)
     {
@@ -882,10 +879,10 @@ cv::gimpl::GFluidExecutable::GFluidExecutable(const ade::Graph
                 auto inEdge = GModel::getInEdgeByPort(m_g, agent->op_handle, in_idx);
                 auto ownStorage = fg.metadata(inEdge).get<FluidUseOwnBorderBuffer>().use;
 
-                gapi::fluid::View view = buffer.mkView(fu.border_size, ownStorage);
                 // NB: It is safe to keep ptr as view lifetime is buffer lifetime
-                agent->in_views[in_idx] = view;
-                agent->in_args[in_idx]  = GArg(view);
+                agent->in_views[in_idx] = buffer.mkView(fu.border_size, ownStorage);
+                agent->in_args[in_idx]  = GArg(&agent->in_views[in_idx]);
+                buffer.addView(&agent->in_views[in_idx]);
             }
             else
             {
@@ -905,6 +902,7 @@ cv::gimpl::GFluidExecutable::GFluidExecutable(const ade::Graph
     }
 
     // After parameters are there, initialize scratch buffers
+    const std::size_t num_scratch = m_scratch_users.size();
     if (num_scratch)
     {
         GAPI_LOG_INFO(NULL, "Initializing " << num_scratch << " scratch buffer(s)" << std::endl);
@@ -932,8 +930,8 @@ std::size_t cv::gimpl::GFluidExecutable::total_buffers_size() const
     for (const auto &i : ade::util::indexed(m_buffers))
     {
         // Check that all internal and scratch buffers are allocated
-        const auto idx = ade::util::index(i);
-        const auto b   = ade::util::value(i);
+        const auto  idx = ade::util::index(i);
+        const auto& b   = ade::util::value(i);
         if (idx >= m_num_int_buffers ||
             fg.metadata(m_all_gmat_ids.at(idx)).get<FluidData>().internal == true)
         {
@@ -1238,7 +1236,7 @@ void cv::gimpl::GFluidExecutable::reshape(ade::Graph &g, const GCompileArgs &arg
     initLineConsumption(g);
     calcLatency(g);
     calcSkew(g);
-    const auto out_rois = cv::gimpl::getCompileArg<cv::GFluidOutputRois>(args).value_or(cv::GFluidOutputRois());
+    const auto out_rois = cv::gapi::getCompileArg<cv::GFluidOutputRois>(args).value_or(cv::GFluidOutputRois());
     makeReshape(out_rois.rois);
 }
 
@@ -1247,10 +1245,11 @@ void cv::gimpl::GFluidExecutable::bindInArg(const cv::gimpl::RcDesc &rc, const G
 {
     switch (rc.shape)
     {
-    case GShape::GMAT:    m_buffers[m_id_map.at(rc.id)].priv().bindTo(util::get<cv::gapi::own::Mat>(arg), true); break;
+    case GShape::GMAT:    m_buffers[m_id_map.at(rc.id)].priv().bindTo(util::get<cv::Mat>(arg), true); break;
     case GShape::GSCALAR: m_res.slot<cv::Scalar>()[rc.id] = util::get<cv::Scalar>(arg); break;
     case GShape::GARRAY:  m_res.slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg); break;
     case GShape::GOPAQUE: m_res.slot<cv::detail::OpaqueRef>()[rc.id] = util::get<cv::detail::OpaqueRef>(arg); break;
+    default: util::throw_error(std::logic_error("Unsupported input GShape type"));
     }
 }
 
@@ -1267,20 +1266,12 @@ void cv::gimpl::GFluidExecutable::bindOutArg(const cv::gimpl::RcDesc &rc, const
 
             switch (arg.index()) {
             // FIXME: See the bindInArg comment on Streaming-related changes
-            case T::index_of<cv::gapi::own::Mat*>(): {
-                auto &outMat = *util::get<cv::gapi::own::Mat*>(arg);
-                GAPI_Assert(outMat.data != nullptr);
-                GAPI_Assert(descr_of(outMat) == desc && "Output argument was not preallocated as it should be ?");
-                bref.bindTo(outMat, false);
-            } break;
-#if !defined(GAPI_STANDALONE)
             case T::index_of<cv::Mat*>(): {
                 auto &outMat = *util::get<cv::Mat*>(arg);
                 GAPI_Assert(outMat.data != nullptr);
-                GAPI_Assert(descr_of(outMat) == desc && "Output argument was not preallocated as it should be ?");
-                bref.bindTo(cv::to_own(outMat), false);
+                GAPI_Assert(cv::descr_of(outMat) == desc && "Output argument was not preallocated as it should be ?");
+                bref.bindTo(outMat, false);
             } break;
-#endif // GAPI_STANDALONE
             default: GAPI_Assert(false);
             } // switch(arg.index())
             break;
index 74336f2..282b066 100644 (file)
@@ -125,7 +125,6 @@ class GFluidExecutable final: public GIslandExecutable
     GModel::ConstGraph m_gm;
 
     std::vector<std::unique_ptr<FluidAgent>> m_agents;
-    std::vector<cv::gapi::fluid::Buffer> m_buffers;
 
     std::vector<FluidAgent*> m_script;
 
@@ -138,6 +137,8 @@ class GFluidExecutable final: public GIslandExecutable
     std::unordered_map<int, std::size_t> m_id_map; // GMat id -> buffer idx map
     std::map<std::size_t, ade::NodeHandle> m_all_gmat_ids;
 
+    std::vector<cv::gapi::fluid::Buffer> m_buffers;
+
     void bindInArg (const RcDesc &rc, const GRunArg &arg);
     void bindOutArg(const RcDesc &rc, const GRunArgP &arg);
     void packArg   (GArg &in_arg, const GArg &op_arg);
@@ -153,6 +154,8 @@ public:
     virtual void run(std::vector<InObj>  &&input_objs,
                      std::vector<OutObj> &&output_objs) override;
 
+    using GIslandExecutable::run; // (IInput&, IOutput&) version
+
     void run(std::vector<InObj>  &input_objs,
              std::vector<OutObj> &output_objs);
 
index 22a9d9e..9c2ec00 100644 (file)
@@ -78,7 +78,7 @@ void fillConstBorderRow(uint8_t* row, int length, int chan, int borderSize, cv::
 }
 
 // Fills const border pixels in the whole mat
-void fillBorderConstant(int borderSize, cv::Scalar borderValue, cv::gapi::own::Mat& mat)
+void fillBorderConstant(int borderSize, cv::Scalar borderValue, cv::Mat& mat)
 {
     // cv::Scalar can contain maximum 4 chan
     GAPI_Assert(mat.channels() > 0 && mat.channels() <= 4);
@@ -178,9 +178,7 @@ const uint8_t* fluid::BorderHandlerT<cv::BORDER_CONSTANT>::inLineB(int /*log_idx
 void fluid::BorderHandlerT<cv::BORDER_CONSTANT>::fillCompileTimeBorder(BufferStorageWithBorder& data)
 {
     m_const_border.create(1, data.cols(), data.data().type());
-    // FIXME: remove this crutch in deowned Mat
-    m_const_border = {m_border_value[0], m_border_value[1],
-                      m_border_value[2], m_border_value[3]};
+    m_const_border = m_border_value;
 
     cv::gapi::fillBorderConstant(m_border_size, m_border_value, data.data());
 }
@@ -266,7 +264,7 @@ const uint8_t* fluid::BufferStorageWithBorder::inLineB(int log_idx, int desc_hei
     }
 }
 
-static void copyWithoutBorder(const cv::gapi::own::Mat& src, int src_border_size, cv::gapi::own::Mat& dst, int dst_border_size, int startSrcLine, int startDstLine, int lpi)
+static void copyWithoutBorder(const cv::Mat& src, int src_border_size, cv::Mat& dst, int dst_border_size, int startSrcLine, int startDstLine, int lpi)
 {
     auto subSrc = src(cv::Rect{src_border_size, startSrcLine, src.cols - 2*src_border_size, lpi});
     auto subDst = dst(cv::Rect{dst_border_size, startDstLine, dst.cols - 2*dst_border_size, lpi});
@@ -362,8 +360,8 @@ std::unique_ptr<fluid::BufferStorage> createStorage(int capacity, int desc_width
 #endif
 }
 
-std::unique_ptr<BufferStorage> createStorage(const cv::gapi::own::Mat& data, cv::Rect roi);
-std::unique_ptr<BufferStorage> createStorage(const cv::gapi::own::Mat& data, cv::Rect roi)
+std::unique_ptr<BufferStorage> createStorage(const cv::Mat& data, cv::Rect roi);
+std::unique_ptr<BufferStorage> createStorage(const cv::Mat& data, cv::Rect roi)
 {
     std::unique_ptr<BufferStorageWithoutBorder> storage(new BufferStorageWithoutBorder);
     storage->attach(data, roi);
@@ -547,10 +545,10 @@ void fluid::Buffer::Priv::allocate(BorderOpt border,
     m_storage->updateOutCache(m_cache, m_write_caret, m_writer_lpi);
 }
 
-void fluid::Buffer::Priv::bindTo(const cv::gapi::own::Mat &data, bool is_input)
+void fluid::Buffer::Priv::bindTo(const cv::Mat &data, bool is_input)
 {
     // FIXME: move all these fields into a separate structure
-    GAPI_Assert(m_desc == descr_of(data));
+    GAPI_Assert(m_desc == cv::descr_of(data));
 
     // Currently m_writer_lpi is obtained from metadata which is shared between islands
     // and this assert can trigger for slot which connects two fluid islands.
@@ -576,7 +574,7 @@ bool fluid::Buffer::Priv::full() const
     {
         // reset with maximum possible value and then find minimum
         slowest_y = m_desc.size.height;
-        for (const auto &v : m_views) slowest_y = std::min(slowest_y, v.y());
+        for (const auto &v : m_views) slowest_y = std::min(slowest_y, v->y());
     }
 
     return m_write_caret + lpi() - slowest_y > m_storage->rows();
@@ -608,7 +606,7 @@ void fluid::Buffer::Priv::reset()
 int fluid::Buffer::Priv::size() const
 {
     std::size_t view_sz = 0;
-    for (const auto &v : m_views) view_sz += v.priv().size();
+    for (const auto &v : m_views) view_sz += v->priv().size();
 
     auto total = view_sz;
     if (m_storage) total += m_storage->size();
@@ -669,16 +667,19 @@ fluid::Buffer::Buffer(const cv::GMatDesc &desc,
     m_priv->allocate(border, border_size, max_line_consumption, skew);
 }
 
-fluid::Buffer::Buffer(const cv::gapi::own::Mat &data, bool is_input)
+fluid::Buffer::Buffer(const cv::Mat &data, bool is_input)
     : m_priv(new Priv())
     , m_cache(&m_priv->cache())
 {
     int wlpi = 1, readStart = 0;
     cv::Rect roi{0, 0, data.cols, data.rows};
-    m_priv->init(descr_of(data), wlpi, readStart, roi);
+    m_priv->init(cv::descr_of(data), wlpi, readStart, roi);
     m_priv->bindTo(data, is_input);
 }
 
+fluid::Buffer::~Buffer() = default;
+fluid::Buffer& fluid::Buffer::operator=(fluid::Buffer&&) = default;
+
 int fluid::Buffer::linesReady() const
 {
     return m_priv->linesReady();
@@ -689,17 +690,26 @@ int fluid::Buffer::lpi() const
     return m_priv->lpi();
 }
 
-fluid::View::View(Priv* p)
-    : m_priv(p), m_cache(&p->cache())
+fluid::View::View(std::unique_ptr<Priv>&& p)
+    : m_priv(std::move(p)), m_cache(&m_priv->cache())
 { /* nothing */ }
 
+
+fluid::View::View() = default;
+fluid::View::View(View&&) = default;
+fluid::View& fluid::View::operator=(View&&) = default;
+fluid::View::~View() = default;
+
 fluid::View fluid::Buffer::mkView(int borderSize, bool ownStorage)
 {
     // FIXME: logic outside of Priv (because View takes pointer to Buffer)
-    auto view = ownStorage ? View(new ViewPrivWithOwnBorder(this, borderSize))
-                           : View(new ViewPrivWithoutOwnBorder(this, borderSize));
-    m_priv->addView(view);
-    return view;
+    return ownStorage ? View(std::unique_ptr<ViewPrivWithOwnBorder>(new ViewPrivWithOwnBorder(this, borderSize)))
+                      : View(std::unique_ptr<ViewPrivWithoutOwnBorder>(new ViewPrivWithoutOwnBorder(this, borderSize)));
+}
+
+void fluid::Buffer::addView(const View* v)
+{
+    m_priv->addView(v);
 }
 
 void fluid::debugBufferPriv(const fluid::Buffer& buffer, std::ostream &os)
@@ -713,7 +723,7 @@ void fluid::debugBufferPriv(const fluid::Buffer& buffer, std::ostream &os)
        <<" (phys " << "[" << p.storage().cols() << " x " <<  p.storage().rows() << "]" << ") :"
        << "  w: " << p.m_write_caret
        << ", r: [";
-    for (const auto &v : p.m_views) { os << &v.priv() << ":" << v.y() << " "; }
+    for (const auto &v : p.m_views) { os << &v->priv() << ":" << v->y() << " "; }
     os << "], avail: " << buffer.linesReady()
        << std::endl;
 }
index 65fa9d4..d6fdc0e 100644 (file)
@@ -53,7 +53,7 @@ template<>
 class BorderHandlerT<cv::BORDER_CONSTANT> : public BorderHandler
 {
     cv::Scalar m_border_value;
-    cv::gapi::own::Mat m_const_border;
+    cv::Mat m_const_border;
 
 public:
     BorderHandlerT(int border_size, cv::Scalar border_value);
@@ -65,7 +65,7 @@ public:
 class BufferStorage
 {
 protected:
-    cv::gapi::own::Mat m_data;
+    cv::Mat m_data;
 
 public:
     void updateInCache(View::Cache& cache, int start_log_idx, int nLines) const;
@@ -80,8 +80,8 @@ public:
 
     inline bool empty() const { return m_data.empty(); }
 
-    inline const cv::gapi::own::Mat& data() const { return m_data; }
-    inline       cv::gapi::own::Mat& data()       { return m_data; }
+    inline const cv::Mat& data() const { return m_data; }
+    inline       cv::Mat& data()       { return m_data; }
 
     inline int rows() const { return m_data.rows; }
     inline int cols() const { return m_data.cols; }
@@ -117,7 +117,7 @@ public:
         return m_data.ptr(physIdx(idx), 0);
     }
 
-    inline void attach(const cv::gapi::own::Mat& _data, cv::Rect _roi)
+    inline void attach(const cv::Mat& _data, cv::Rect _roi)
     {
         m_data = _data(_roi);
         m_roi = _roi;
@@ -239,13 +239,13 @@ class GAPI_EXPORTS Buffer::Priv
 
     int m_write_caret      = -1;
 
-    std::vector<View> m_views;
+    std::vector<const View*> m_views;
 
     std::unique_ptr<BufferStorage> m_storage;
 
     // Coordinate starting from which this buffer is assumed
     // to be read (with border not being taken into account)
-    int m_readStart;
+    int m_readStart = 0;
     cv::Rect m_roi;
 
     friend void debugBufferPriv(const Buffer& p, std::ostream &os);
@@ -263,9 +263,9 @@ public:
               cv::Rect roi);
 
     void allocate(BorderOpt border, int border_size, int line_consumption, int skew);
-    void bindTo(const cv::gapi::own::Mat &data, bool is_input);
+    void bindTo(const cv::Mat &data, bool is_input);
 
-    inline void addView(const View& view) { m_views.push_back(view); }
+    inline void addView(const View* view) { m_views.emplace_back(view); }
 
     inline const GMatDesc& meta() const { return m_desc; }
 
index 01b9be8..a6f8d56 100644 (file)
@@ -797,6 +797,50 @@ GAPI_FLUID_KERNEL(GFluidDivRC, cv::gapi::core::GDivRC, false)
     }
 };
 
+//-------------------
+//
+// Fluid kernels: mask
+//
+//-------------------
+
+template<typename DST, typename SRC>
+static void run_mask(Buffer &dst, const View &src, const View &mask)
+{
+    static_assert(std::is_same<DST, SRC>::value,
+        "Input and output types must match");
+
+    int length  = dst.length(); // dst, src and mask have the same size and are single-channel
+
+    const auto *in      = src.InLine<SRC>(0);
+    const auto *in_mask = mask.InLine<uchar>(0);
+          auto *out     = dst.OutLine<DST>();
+
+    for (int l=0; l < length; l++)
+    {
+        out[l] = in_mask[l] ? in[l] : 0;
+    }
+}
+
+GAPI_FLUID_KERNEL(GFluidMask, cv::gapi::core::GMask, false)
+{
+    static const int Window = 1;
+
+    static void run(const View &src, const View &mask, Buffer &dst)
+    {
+        if (src.meta().chan != 1 || dst.meta().chan != 1)
+            CV_Error(cv::Error::StsBadArg, "input and output must be single-channel");
+        if (mask.meta().chan != 1 || mask.meta().depth != CV_8U)
+            CV_Error(cv::Error::StsBadArg, "unsupported mask type");
+
+        //     DST     SRC     OP        __VA_ARGS__
+        UNARY_(uchar , uchar , run_mask, dst, src, mask);
+        UNARY_( short,  short, run_mask, dst, src, mask);
+        UNARY_(ushort, ushort, run_mask, dst, src, mask);
+
+        CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+    }
+};
+
 //----------------------------
 //
 // Fluid math kernels: bitwise
@@ -806,7 +850,7 @@ GAPI_FLUID_KERNEL(GFluidDivRC, cv::gapi::core::GDivRC, false)
 enum Bitwise { BW_AND, BW_OR, BW_XOR, BW_NOT };
 
 template<typename DST, typename SRC1, typename SRC2>
-static void run_bitwise2(Buffer &dst, const View &src1, const View &src2, Bitwise bitwise)
+static void run_bitwise2(Buffer &dst, const View &src1, const View &src2, Bitwise bitwise_op)
 {
     static_assert(std::is_same<DST, SRC1>::value, "wrong types");
     static_assert(std::is_same<DST, SRC2>::value, "wrong types");
@@ -819,7 +863,7 @@ static void run_bitwise2(Buffer &dst, const View &src1, const View &src2, Bitwis
     int chan   = dst.meta().chan;
     int length = width * chan;
 
-    switch (bitwise)
+    switch (bitwise_op)
     {
     case BW_AND:
         for (int l=0; l < length; l++)
@@ -838,7 +882,7 @@ static void run_bitwise2(Buffer &dst, const View &src1, const View &src2, Bitwis
 }
 
 template<typename DST, typename SRC>
-static void run_bitwise1(Buffer &dst, const View &src, Bitwise bitwise)
+static void run_bitwise1(Buffer &dst, const View &src, Bitwise bitwise_op)
 {
     static_assert(std::is_same<DST, SRC>::value, "wrong types");
 
@@ -849,7 +893,7 @@ static void run_bitwise1(Buffer &dst, const View &src, Bitwise bitwise)
     int chan   = dst.meta().chan;
     int length = width * chan;
 
-    switch (bitwise)
+    switch (bitwise_op)
     {
     case BW_NOT:
         for (int l=0; l < length; l++)
@@ -922,6 +966,133 @@ GAPI_FLUID_KERNEL(GFluidNot, cv::gapi::core::GNot, false)
     }
 };
 
+//--------------------------------------
+//
+// Fluid math kernels: bitwise with Scalar
+//
+//--------------------------------------
+
+static std::array<int,4> convertScalarForBitwise(const cv::Scalar &_scalar)
+{
+    std::array<int,4> scalarI = {
+        static_cast<int>(_scalar[0]),
+        static_cast<int>(_scalar[1]),
+        static_cast<int>(_scalar[2]),
+        static_cast<int>(_scalar[3])
+    };
+
+    if (!((_scalar[0] == scalarI[0]) && (_scalar[1] == scalarI[1]) &&
+          (_scalar[2] == scalarI[2]) && (_scalar[3] == scalarI[3])))
+    {
+        CV_Error(cv::Error::StsBadArg, "Bitwise operations make sense with integral types only");
+    }
+    return scalarI;
+}
+
+template<typename DST>
+static inline DST bw_andS(DST x, int y)
+{
+    return x & saturate<DST>(y);
+}
+
+template<typename DST>
+static inline DST bw_orS(DST x, int y)
+{
+    return x | saturate<DST>(y);
+}
+
+template<typename DST>
+static inline DST bw_xorS(DST x, int y)
+{
+    return x ^ saturate<DST>(y);
+}
+
+// manually unroll the inner cycle by channels
+// (reuse arithmetic function above of the same purpose)
+template<typename DST, typename FUNC>
+static inline void run_bitwise_s(DST out[], const DST in[], int width, int chan,
+                                 const int scalar[4], FUNC func)
+{
+    run_arithm_s(out, in, width, chan, scalar, func);
+}
+
+template<typename DST, typename SRC>
+static void run_bitwise_s(Buffer &dst, const View &src, const int scalar[4], Bitwise bitwise_op)
+{
+    static_assert(std::is_same<DST, SRC>::value, "wrong types");
+
+    const auto *in  = src.InLine<SRC>(0);
+          auto *out = dst.OutLine<DST>();
+
+    int width  = dst.length();
+    int chan   = dst.meta().chan;
+
+    switch (bitwise_op)
+    {
+    case BW_AND:
+        run_bitwise_s(out, in, width, chan, scalar, bw_andS<DST>);
+        break;
+    case BW_OR:
+        run_bitwise_s(out, in, width, chan, scalar, bw_orS<DST>);
+        break;
+    case BW_XOR:
+        run_bitwise_s(out, in, width, chan, scalar, bw_xorS<DST>);
+        break;
+    default: CV_Error(cv::Error::StsBadArg, "unsupported bitwise operation");
+    }
+}
+
+GAPI_FLUID_KERNEL(GFluidAndS, cv::gapi::core::GAndS, false)
+{
+    static const int Window = 1;
+
+    static void run(const View &src, const cv::Scalar &_scalar, Buffer &dst)
+    {
+        std::array<int,4> scalar = convertScalarForBitwise(_scalar);
+
+        //     DST     SRC     OP            __VA_ARGS__
+        UNARY_(uchar , uchar , run_bitwise_s, dst, src, scalar.data(), BW_AND);
+        UNARY_(ushort, ushort, run_bitwise_s, dst, src, scalar.data(), BW_AND);
+        UNARY_( short,  short, run_bitwise_s, dst, src, scalar.data(), BW_AND);
+
+        CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+    }
+};
+
+GAPI_FLUID_KERNEL(GFluidOrS, cv::gapi::core::GOrS, false)
+{
+    static const int Window = 1;
+
+    static void run(const View &src, const cv::Scalar &_scalar, Buffer &dst)
+    {
+        std::array<int,4> scalar = convertScalarForBitwise(_scalar);
+
+        //     DST     SRC     OP            __VA_ARGS__
+        UNARY_(uchar , uchar , run_bitwise_s, dst, src, scalar.data(), BW_OR);
+        UNARY_(ushort, ushort, run_bitwise_s, dst, src, scalar.data(), BW_OR);
+        UNARY_( short,  short, run_bitwise_s, dst, src, scalar.data(), BW_OR);
+
+        CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+    }
+};
+
+GAPI_FLUID_KERNEL(GFluidXorS, cv::gapi::core::GXorS, false)
+{
+    static const int Window = 1;
+
+    static void run(const View &src, const cv::Scalar &_scalar, Buffer &dst)
+    {
+        std::array<int,4> scalar = convertScalarForBitwise(_scalar);
+
+        //     DST     SRC     OP            __VA_ARGS__
+        UNARY_(uchar , uchar , run_bitwise_s, dst, src, scalar.data(), BW_XOR);
+        UNARY_(ushort, ushort, run_bitwise_s, dst, src, scalar.data(), BW_XOR);
+        UNARY_( short,  short, run_bitwise_s, dst, src, scalar.data(), BW_XOR);
+
+        CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+    }
+};
+
 //-------------------
 //
 // Fluid kernels: LUT
@@ -1059,12 +1230,19 @@ GAPI_FLUID_KERNEL(GFluidConvertTo, cv::gapi::core::GConvertTo, false)
         //     DST     SRC     OP             __VA_ARGS__
         UNARY_(uchar , uchar , run_convertto, dst, src, alpha, beta);
         UNARY_(uchar , ushort, run_convertto, dst, src, alpha, beta);
+        UNARY_(uchar ,  short, run_convertto, dst, src, alpha, beta);
         UNARY_(uchar ,  float, run_convertto, dst, src, alpha, beta);
         UNARY_(ushort, uchar , run_convertto, dst, src, alpha, beta);
         UNARY_(ushort, ushort, run_convertto, dst, src, alpha, beta);
+        UNARY_(ushort,  short, run_convertto, dst, src, alpha, beta);
         UNARY_(ushort,  float, run_convertto, dst, src, alpha, beta);
+        UNARY_( short, uchar , run_convertto, dst, src, alpha, beta);
+        UNARY_( short, ushort, run_convertto, dst, src, alpha, beta);
+        UNARY_( short,  short, run_convertto, dst, src, alpha, beta);
+        UNARY_( short,  float, run_convertto, dst, src, alpha, beta);
         UNARY_( float, uchar , run_convertto, dst, src, alpha, beta);
         UNARY_( float, ushort, run_convertto, dst, src, alpha, beta);
+        UNARY_( float,  short, run_convertto, dst, src, alpha, beta);
         UNARY_( float,  float, run_convertto, dst, src, alpha, beta);
 
         CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
@@ -2030,10 +2208,16 @@ GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::core::GResize, true)
     }
 
     static void initScratch(const cv::GMatDesc& in,
-                            cv::Size outSz, double /*fx*/, double /*fy*/, int /*interp*/,
+                            cv::Size outSz, double fx, double fy, int /*interp*/,
                             cv::gapi::fluid::Buffer &scratch)
     {
-        CV_Assert(in.depth == CV_8U && in.chan == 3);
+        GAPI_Assert(in.depth == CV_8U && in.chan == 3);
+
+        if (outSz.area() == 0)
+        {
+            outSz.width  = static_cast<int>(round(in.size.width  * fx));
+            outSz.height = static_cast<int>(round(in.size.height * fy));
+        }
 
         cv::Size scratch_size{static_cast<int>(outSz.width * sizeof(ResizeUnit)), 1};
 
@@ -2169,6 +2353,9 @@ cv::gapi::GKernelPackage cv::gapi::core::fluid::kernels()
             ,GFluidAnd
             ,GFluidOr
             ,GFluidXor
+            ,GFluidAndS
+            ,GFluidOrS
+            ,GFluidXorS
             ,GFluidMin
             ,GFluidMax
             ,GFluidCmpGT
@@ -2196,6 +2383,7 @@ cv::gapi::GKernelPackage cv::gapi::core::fluid::kernels()
             ,GFluidMulCOld
             ,GFluidDivC
             ,GFluidDivRC
+            ,GFluidMask
             ,GFluidAbsDiffC
             ,GFluidCmpGTScalar
             ,GFluidCmpGEScalar
index 3941642..df4ffb1 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 #include "precomp.hpp"
 
 #include <opencv2/gapi/util/any.hpp>
 #include <opencv2/gapi/gtype_traits.hpp>
 #include <opencv2/gapi/infer.hpp>
+#include <opencv2/gapi/own/convert.hpp>
 
 #include "compiler/gobjref.hpp"
 #include "compiler/gmodel.hpp"
 
 #include "backends/ie/util.hpp"
+#include "backends/ie/giebackend/giewrapper.hpp"
 
 #include "api/gbackend_priv.hpp" // FIXME: Make it part of Backend SDK!
 
@@ -175,14 +177,9 @@ struct IEUnit {
 
     explicit IEUnit(const cv::gapi::ie::detail::ParamDesc &pp)
         : params(pp) {
-
-        IE::CNNNetReader reader;
-        reader.ReadNetwork(params.model_path);
-        reader.ReadWeights(params.weights_path);
-        net = reader.getNetwork();
-        inputs = net.getInputsInfo();
+        net = cv::gimpl::ie::wrap::readNetwork(params);
+        inputs  = net.getInputsInfo();
         outputs = net.getOutputsInfo();
-
         // The practice shows that not all inputs and not all outputs
         // are mandatory to specify in IE model.
         // So what we're concerned here about is:
@@ -207,53 +204,9 @@ struct IEUnit {
     }
 
     // This method is [supposed to be] called at Island compilation stage
-    // TODO: Move to a new OpenVINO Core API!
     cv::gimpl::ie::IECompiled compile() const {
-        auto this_plugin = IE::PluginDispatcher().getPluginByDevice(params.device_id);
-
-        // Load extensions (taken from DNN module)
-        if (params.device_id == "CPU" || params.device_id == "FPGA")
-        {
-            const std::string suffixes[] = { "_avx2", "_sse4", ""};
-            const bool haveFeature[] = {
-                cv::checkHardwareSupport(CPU_AVX2),
-                cv::checkHardwareSupport(CPU_SSE4_2),
-                true
-            };
-            std::vector<std::string> candidates;
-            for (auto &&it : ade::util::zip(ade::util::toRange(suffixes),
-                                            ade::util::toRange(haveFeature)))
-            {
-                std::string suffix;
-                bool available = false;
-                std::tie(suffix, available) = it;
-                if (!available) continue;
-#ifdef _WIN32
-                candidates.push_back("cpu_extension" + suffix + ".dll");
-#elif defined(__APPLE__)
-                candidates.push_back("libcpu_extension" + suffix + ".so");  // built as loadable module
-                candidates.push_back("libcpu_extension" + suffix + ".dylib");  // built as shared library
-#else
-                candidates.push_back("libcpu_extension" + suffix + ".so");
-#endif  // _WIN32
-            }
-            for (auto &&extlib : candidates)
-            {
-                try
-                {
-                    this_plugin.AddExtension(IE::make_so_pointer<IE::IExtension>(extlib));
-                    CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << extlib);
-                    break;
-                }
-                catch(...)
-                {
-                    CV_LOG_WARNING(NULL, "Failed to load IE extension " << extlib);
-                }
-            }
-        }
-
-        auto this_network = this_plugin.LoadNetwork(net, {}); // FIXME: 2nd parameter to be
-                                                              // configurable via the API
+        auto plugin       = cv::gimpl::ie::wrap::getPlugin(params);
+        auto this_network = cv::gimpl::ie::wrap::loadNetwork(plugin, net, params);
         auto this_request = this_network.CreateInferRequest();
 
         // Bind const data to infer request
@@ -264,8 +217,7 @@ struct IEUnit {
             // Still, constant data is to set only once.
             this_request.SetBlob(p.first, wrapIE(p.second.first, p.second.second));
         }
-
-        return {this_plugin, this_network, this_request};
+        return {plugin, this_network, this_request};
     }
 };
 
@@ -285,11 +237,11 @@ struct IECallContext
     const T& inArg(std::size_t input) { return args.at(input).get<T>(); }
 
     // Syntax sugar
-    const cv::gapi::own::Mat&   inMat(std::size_t input) {
-        return inArg<cv::gapi::own::Mat>(input);
+    const cv::Mat&   inMat(std::size_t input) {
+        return inArg<cv::Mat>(input);
     }
-    cv::gapi::own::Mat&         outMatR(std::size_t output) {
-        return *cv::util::get<cv::gapi::own::Mat*>(results.at(output));
+    cv::Mat&         outMatR(std::size_t output) {
+        return *cv::util::get<cv::Mat*>(results.at(output));
     }
 
     template<typename T> std::vector<T>& outVecR(std::size_t output) { // FIXME: the same issue
@@ -391,7 +343,7 @@ cv::GArg cv::gimpl::ie::GIEExecutable::packArg(const cv::GArg &arg) {
     const cv::gimpl::RcDesc &ref = arg.get<cv::gimpl::RcDesc>();
     switch (ref.shape)
     {
-    case GShape::GMAT:    return GArg(m_res.slot<cv::gapi::own::Mat>()[ref.id]);
+    case GShape::GMAT:    return GArg(m_res.slot<cv::Mat>()[ref.id]);
 
     // Note: .at() is intentional for GArray as object MUST be already there
     //   (and constructed by either bindIn/Out or resetInternal)
@@ -486,7 +438,6 @@ struct Infer: public cv::detail::KernelTag {
 
             const auto &meta = util::get<cv::GMatDesc>(mm);
             ii->setPrecision(toIE(meta.depth));
-            ii->setLayout(meta.isND() ? IE::Layout::NCHW : IE::Layout::NHWC);
             ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
         }
 
@@ -514,7 +465,7 @@ struct Infer: public cv::detail::KernelTag {
             // and redirect our data producers to this memory
             // (A memory dialog comes to the picture again)
 
-            const cv::Mat this_mat = to_ocv(ctx.inMat(i));
+            const cv::Mat this_mat = ctx.inMat(i);
             // FIXME: By default here we trait our inputs as images.
             // May be we need to make some more intelligence here about it
             IE::Blob::Ptr this_blob = wrapIE(this_mat, cv::gapi::ie::TraitAs::IMAGE);
@@ -528,7 +479,7 @@ struct Infer: public cv::detail::KernelTag {
             // Not a <very> big deal for classifiers and detectors,
             // but may be critical to segmentation.
 
-            cv::gapi::own::Mat& out_mat = ctx.outMatR(i);
+            cv::Mat& out_mat = ctx.outMatR(i);
             IE::Blob::Ptr this_blob = iec.this_request.GetBlob(uu.params.output_names[i]);
             copyFromIE(this_blob, out_mat);
         }
@@ -567,7 +518,6 @@ struct InferList: public cv::detail::KernelTag {
 
             const auto &meta = util::get<cv::GMatDesc>(mm);
             ii->setPrecision(toIE(meta.depth));
-            ii->setLayout(meta.isND() ? IE::Layout::NCHW : IE::Layout::NHWC);
             ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
         }
 
@@ -586,7 +536,7 @@ struct InferList: public cv::detail::KernelTag {
         GAPI_Assert(uu.params.num_in == 1); // roi list is not counted in net's inputs
 
         const auto& in_roi_vec = ctx.inArg<cv::detail::VectorRef>(0u).rref<cv::Rect>();
-        const cv::Mat this_mat = to_ocv(ctx.inMat(1u));
+        const cv::Mat this_mat = ctx.inMat(1u);
         // Since we do a ROI list inference, always assume our input buffer is image
         IE::Blob::Ptr this_blob = wrapIE(this_mat, cv::gapi::ie::TraitAs::IMAGE);
 
@@ -621,6 +571,137 @@ struct InferList: public cv::detail::KernelTag {
     }
 };
 
+struct InferList2: public cv::detail::KernelTag {
+    using API = cv::GInferList2Base;
+    static cv::gapi::GBackend backend()  { return cv::gapi::ie::backend(); }
+    static KImpl kernel()                { return KImpl{outMeta, run}; }
+
+    static cv::GMetaArgs outMeta(const ade::Graph      &gr,
+                                 const ade::NodeHandle &nh,
+                                 const cv::GMetaArgs   &in_metas,
+                                 const cv::GArgs       &/*in_args*/) {
+        // Specify the input information to the IE from the framework
+        // NB: Have no clue if network's input [dimensions] may ever define
+        // its output dimensions. It seems possible with OpenCV DNN APIs
+
+        GConstGIEModel gm(gr);
+        const auto &uu = gm.metadata(nh).get<IEUnit>();
+
+        // Initialize input information
+        // Note our input layers list order matches the API order and so
+        // meta order.
+        GAPI_Assert(uu.params.input_names.size() == (in_metas.size() - 1u)
+                    && "Known input layers count doesn't match input meta count");
+
+        const auto &op = gm.metadata(nh).get<Op>();
+
+        // In contrast to InferList, the InferList2 has only one
+        // "full-frame" image argument, and all the rest are arrays of
+        // ether ROI or blobs. So here we set the 0th arg image format
+        // to all inputs which are ROI-based (skipping the
+        // "blob"-based ones)
+        // FIXME: this is filtering not done, actually! GArrayDesc has
+        // no hint for its underlying type!
+        const auto &mm_0   = in_metas[0u];
+        const auto &meta_0 = util::get<cv::GMatDesc>(mm_0);
+        GAPI_Assert(   !meta_0.isND()
+                    && !meta_0.planar
+                    && "Only images are supported as the 0th argument");
+        std::size_t idx = 1u;
+        for (auto &&input_name : uu.params.input_names) {
+                  auto &ii = uu.inputs.at(input_name);
+            const auto &mm = in_metas[idx];
+            GAPI_Assert(util::holds_alternative<cv::GArrayDesc>(mm)
+                        && "Non-array inputs are not supported");
+
+            if (op.k.inKinds[idx] == cv::detail::OpaqueKind::CV_RECT) {
+                // This is a cv::Rect -- configure the IE preprocessing
+                ii->setPrecision(toIE(meta_0.depth));
+                ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
+            } else {
+                // This is a cv::GMat (equals to: cv::Mat)
+                // Just validate that it is really the type
+                // (other types are prohibited here)
+                GAPI_Assert(op.k.inKinds[idx] == cv::detail::OpaqueKind::CV_MAT);
+            }
+            idx++; // NB: Never forget to increment the counter
+        }
+
+        // roi-list version is much easier at the moment.
+        // All our outputs are vectors which don't have
+        // metadata at the moment - so just create a vector of
+        // "empty" array metadatas of the required size.
+        return cv::GMetaArgs(uu.params.output_names.size(),
+                             cv::GMetaArg{cv::empty_array_desc()});
+    }
+
+    static void run(IECompiled &iec, const IEUnit &uu, IECallContext &ctx) {
+        GAPI_Assert(ctx.args.size() > 1u
+                    && "This operation must have at least two arguments");
+
+        // Since we do a ROI list inference, always assume our input buffer is image
+        const cv::Mat mat_0  = ctx.inMat(0u);
+        IE::Blob::Ptr blob_0 = wrapIE(mat_0, cv::gapi::ie::TraitAs::IMAGE);
+
+        // Take the next argument, which must be vector (of any kind).
+        // Use it only to obtain the ROI list size (sizes of all other
+        // vectors must be equal to this one)
+        const auto list_size = ctx.inArg<cv::detail::VectorRef>(1u).size();
+
+        // FIXME: This could be done ONCE at graph compile stage!
+        std::vector< std::vector<int> > cached_dims(uu.params.num_out);
+        for (auto i : ade::util::iota(uu.params.num_out)) {
+            const IE::DataPtr& ie_out = uu.outputs.at(uu.params.output_names[i]);
+            cached_dims[i] = toCV(ie_out->getTensorDesc().getDims());
+            ctx.outVecR<cv::Mat>(i).clear();
+            // FIXME: Isn't this should be done automatically
+            // by some resetInternalData(), etc? (Probably at the GExecutor level)
+        }
+
+        // For every ROI in the list {{{
+        for (const auto &list_idx : ade::util::iota(list_size)) {
+            // For every input of the net {{{
+            for (auto in_idx : ade::util::iota(uu.params.num_in)) {
+                const auto &this_vec = ctx.inArg<cv::detail::VectorRef>(in_idx+1u);
+                GAPI_Assert(this_vec.size() == list_size);
+                // Prepare input {{{
+                IE::Blob::Ptr this_blob;
+                if (this_vec.getKind() == cv::detail::OpaqueKind::CV_RECT) {
+                    // ROI case - create an ROI blob
+                    const auto &vec = this_vec.rref<cv::Rect>();
+                    this_blob = IE::make_shared_blob(blob_0, toIE(vec[list_idx]));
+                } else if (this_vec.getKind() == cv::detail::OpaqueKind::CV_MAT) {
+                    // Mat case - create a regular blob
+                    // FIXME: NOW Assume Mats are always BLOBS (not
+                    // images)
+                    const auto &vec = this_vec.rref<cv::Mat>();
+                    const auto &mat = vec[list_idx];
+                    this_blob = wrapIE(mat, cv::gapi::ie::TraitAs::TENSOR);
+                } else {
+                    GAPI_Assert(false && "Only Rect and Mat types are supported for infer list 2!");
+                }
+                iec.this_request.SetBlob(uu.params.input_names[in_idx], this_blob);
+                // }}} (Preapre input)
+            } // }}} (For every input of the net)
+
+            // Run infer request {{{
+            iec.this_request.Infer();
+            // }}} (Run infer request)
+
+            // For every output of the net {{{
+            for (auto i : ade::util::iota(uu.params.num_out)) {
+                // Push results to the list {{{
+                std::vector<cv::Mat> &out_vec = ctx.outVecR<cv::Mat>(i);
+                IE::Blob::Ptr out_blob = iec.this_request.GetBlob(uu.params.output_names[i]);
+                cv::Mat out_mat(cached_dims[i], toCV(out_blob->getTensorDesc().getPrecision()));
+                copyFromIE(out_blob, out_mat);  // FIXME: Avoid data copy. Not sure if it is possible though
+                out_vec.push_back(std::move(out_mat));
+                // }}} (Push results to the list)
+            } // }}} (For every output of the net)
+        } // }}} (For every ROI in the list)
+    }
+};
+
 } // namespace ie
 } // namespace gapi
 } // namespace cv
@@ -653,6 +734,7 @@ namespace {
         virtual cv::gapi::GKernelPackage auxiliaryKernels() const override {
             return cv::gapi::kernels< cv::gimpl::ie::Infer
                                     , cv::gimpl::ie::InferList
+                                    , cv::gimpl::ie::InferList2
                                     >();
         }
     };
@@ -663,18 +745,18 @@ cv::gapi::GBackend cv::gapi::ie::backend() {
     return this_backend;
 }
 
-cv::Mat cv::gapi::ie::util::to_ocv(InferenceEngine::Blob::Ptr blob) {
+cv::Mat cv::gapi::ie::util::to_ocv(IE::Blob::Ptr blob) {
     const auto& tdesc = blob->getTensorDesc();
     return cv::Mat(toCV(tdesc.getDims()),
                    toCV(tdesc.getPrecision()),
                    blob->buffer().as<uint8_t*>());
 }
 
-std::vector<int> cv::gapi::ie::util::to_ocv(const InferenceEngine::SizeVector &dims) {
+std::vector<int> cv::gapi::ie::util::to_ocv(const IE::SizeVector &dims) {
     return toCV(dims);
 }
 
-InferenceEngine::Blob::Ptr cv::gapi::ie::util::to_ie(cv::Mat &blob) {
+IE::Blob::Ptr cv::gapi::ie::util::to_ie(cv::Mat &blob) {
     return wrapIE(blob, cv::gapi::ie::TraitAs::IMAGE);
 }
 
index 2a71d83..4bac71c 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 #ifndef OPENCV_GAPI_GIEBACKEND_HPP
 #define OPENCV_GAPI_GIEBACKEND_HPP
 
 #include <ade/util/algorithm.hpp> // type_list_index
 
-////////////////////////////////////////////////////////////////////////////////
-// FIXME: Suppress deprecation warnings for OpenVINO 2019R2+
-// BEGIN {{{
-#if defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-#ifdef _MSC_VER
-#pragma warning(disable: 4996)  // was declared deprecated
-#endif
-
-#if defined(__GNUC__)
-#pragma GCC visibility push(default)
-#endif
-
 #include <inference_engine.hpp>
 
-#if defined(__GNUC__)
-#pragma GCC visibility pop
-#endif
-// END }}}
-////////////////////////////////////////////////////////////////////////////////
-
 #include <opencv2/gapi/garg.hpp>
 #include <opencv2/gapi/gproto.hpp>
 
@@ -48,7 +28,11 @@ namespace gimpl {
 namespace ie {
 
 struct IECompiled {
+#if INF_ENGINE_RELEASE < 2019020000  // < 2019.R2
     InferenceEngine::InferencePlugin   this_plugin;
+#else
+    InferenceEngine::Core              this_core;
+#endif
     InferenceEngine::ExecutableNetwork this_network;
     InferenceEngine::InferRequest      this_request;
 };
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/ie/giebackend/giewrapper.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/ie/giebackend/giewrapper.cpp
new file mode 100644 (file)
index 0000000..444d955
--- /dev/null
@@ -0,0 +1,123 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifdef HAVE_INF_ENGINE
+
+#include <vector>
+#include <string>
+#include <tuple>
+
+#include "backends/ie/giebackend/giewrapper.hpp"
+
+#include <ade/util/range.hpp>
+#include <ade/util/zip_range.hpp>
+
+#include <opencv2/core/utility.hpp>
+#include <opencv2/core/utils/logger.hpp>
+
+namespace IE = InferenceEngine;
+namespace giewrap = cv::gimpl::ie::wrap;
+using GIEParam = cv::gapi::ie::detail::ParamDesc;
+
+#if INF_ENGINE_RELEASE < 2020000000  // < 2020.1
+// Load extensions (taken from DNN module)
+std::vector<std::string> giewrap::getExtensions(const GIEParam& params) {
+    std::vector<std::string> candidates;
+    if (params.device_id == "CPU" || params.device_id == "FPGA")
+    {
+        const std::string suffixes[] = { "_avx2", "_sse4", ""};
+        const bool haveFeature[] = {
+            cv::checkHardwareSupport(CPU_AVX2),
+            cv::checkHardwareSupport(CPU_SSE4_2),
+            true
+        };
+        for (auto &&it : ade::util::zip(ade::util::toRange(suffixes),
+                                        ade::util::toRange(haveFeature)))
+        {
+            std::string suffix;
+            bool available = false;
+            std::tie(suffix, available) = it;
+            if (!available) continue;
+#ifdef _WIN32
+            candidates.push_back("cpu_extension" + suffix + ".dll");
+#elif defined(__APPLE__)
+            candidates.push_back("libcpu_extension" + suffix + ".so");  // built as loadable module
+            candidates.push_back("libcpu_extension" + suffix + ".dylib");  // built as shared library
+#else
+            candidates.push_back("libcpu_extension" + suffix + ".so");
+#endif  // _WIN32
+        }
+    }
+    return candidates;
+}
+
+IE::CNNNetwork giewrap::readNetwork(const GIEParam& params) {
+    IE::CNNNetReader reader;
+    reader.ReadNetwork(params.model_path);
+    reader.ReadWeights(params.weights_path);
+    return reader.getNetwork();
+}
+#else // >= 2020.1
+std::vector<std::string> giewrap::getExtensions(const GIEParam&) {
+    return std::vector<std::string>();
+}
+
+IE::CNNNetwork giewrap::readNetwork(const GIEParam& params) {
+    auto core = giewrap::getCore();
+    return core.ReadNetwork(params.model_path, params.weights_path);
+}
+#endif // INF_ENGINE_RELEASE < 2020000000
+
+#if INF_ENGINE_RELEASE < 2019020000  // < 2019.R2
+IE::InferencePlugin giewrap::getPlugin(const GIEParam& params) {
+    auto plugin = IE::PluginDispatcher().getPluginByDevice(params.device_id);
+    if (params.device_id == "CPU" || params.device_id == "FPGA")
+    {
+        for (auto &&extlib : giewrap::getExtensions(params))
+        {
+            try
+            {
+                plugin.AddExtension(IE::make_so_pointer<IE::IExtension>(extlib));
+                CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << extlib);
+                break;
+            }
+            catch(...)
+            {
+                CV_LOG_INFO(NULL, "Failed to load IE extension: " << extlib);
+            }
+        }
+    }
+    return plugin;
+}
+#else // >= 2019.R2
+IE::Core giewrap::getCore() {
+    static IE::Core core;
+    return core;
+}
+
+IE::Core giewrap::getPlugin(const GIEParam& params) {
+    auto plugin = giewrap::getCore();
+    if (params.device_id == "CPU" || params.device_id == "FPGA")
+    {
+        for (auto &&extlib : giewrap::getExtensions(params))
+        {
+            try
+            {
+                plugin.AddExtension(IE::make_so_pointer<IE::IExtension>(extlib), params.device_id);
+                CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << extlib);
+                break;
+            }
+            catch(...)
+            {
+                CV_LOG_INFO(NULL, "Failed to load IE extension: " << extlib);
+            }
+        }
+    }
+    return plugin;
+}
+#endif // INF_ENGINE_RELEASE < 2019020000
+
+#endif //HAVE_INF_ENGINE
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/ie/giebackend/giewrapper.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/ie/giebackend/giewrapper.hpp
new file mode 100644 (file)
index 0000000..7871942
--- /dev/null
@@ -0,0 +1,51 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_IEWRAPPER_HPP
+#define OPENCV_GAPI_IEWRAPPER_HPP
+
+#ifdef HAVE_INF_ENGINE
+
+#include <inference_engine.hpp>
+
+#include <vector>
+#include <string>
+
+#include "opencv2/gapi/infer/ie.hpp"
+
+namespace IE = InferenceEngine;
+using GIEParam = cv::gapi::ie::detail::ParamDesc;
+
+namespace cv {
+namespace gimpl {
+namespace ie {
+namespace wrap {
+// NB: These functions are EXPORTed to make them accessible by the
+// test suite only.
+GAPI_EXPORTS std::vector<std::string> getExtensions(const GIEParam& params);
+GAPI_EXPORTS IE::CNNNetwork readNetwork(const GIEParam& params);
+
+#if INF_ENGINE_RELEASE < 2019020000  // < 2019.R2
+GAPI_EXPORTS IE::InferencePlugin getPlugin(const GIEParam& params);
+GAPI_EXPORTS inline IE::ExecutableNetwork loadNetwork(      IE::InferencePlugin& plugin,
+                                                      const IE::CNNNetwork&      net,
+                                                      const GIEParam&) {
+    return plugin.LoadNetwork(net, {}); // FIXME: 2nd parameter to be
+                                        // configurable via the API
+}
+#else // >= 2019.R2
+GAPI_EXPORTS IE::Core getCore();
+GAPI_EXPORTS IE::Core getPlugin(const GIEParam& params);
+GAPI_EXPORTS inline IE::ExecutableNetwork loadNetwork(      IE::Core&       core,
+                                                      const IE::CNNNetwork& net,
+                                                      const GIEParam& params) {
+    return core.LoadNetwork(net, params.device_id);
+}
+#endif // INF_ENGINE_RELEASE < 2019020000
+}}}}
+
+#endif //HAVE_INF_ENGINE
+#endif // OPENCV_GAPI_IEWRAPPER_HPP
index 718cd31..8705deb 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
 //
 // If not, we need to introduce that!
 using GOCLModel = ade::TypedGraph
-    < cv::gimpl::Unit
+    < cv::gimpl::OCLUnit
     , cv::gimpl::Protocol
     >;
 
 // FIXME: Same issue with Typed and ConstTyped
 using GConstGOCLModel = ade::ConstTypedGraph
-    < cv::gimpl::Unit
+    < cv::gimpl::OCLUnit
     , cv::gimpl::Protocol
     >;
 
@@ -53,7 +53,7 @@ namespace
         {
             GOCLModel gm(graph);
             auto ocl_impl = cv::util::any_cast<cv::GOCLKernel>(impl.opaque);
-            gm.metadata(op_node).set(cv::gimpl::Unit{ocl_impl});
+            gm.metadata(op_node).set(cv::gimpl::OCLUnit{ocl_impl});
         }
 
         virtual EPtr compile(const ade::Graph &graph,
@@ -96,7 +96,7 @@ cv::gimpl::GOCLExecutable::GOCLExecutable(const ade::Graph &g,
             if (desc.storage == Data::Storage::INTERNAL && desc.shape == GShape::GMAT)
             {
                 const auto mat_desc = util::get<cv::GMatDesc>(desc.meta);
-                auto& mat = m_res.slot<cv::gapi::own::Mat>()[desc.rc];
+                auto& mat = m_res.slot<cv::Mat>()[desc.rc];
                 createMat(mat_desc, mat);
             }
             break;
@@ -198,7 +198,7 @@ void cv::gimpl::GOCLExecutable::run(std::vector<InObj>  &&input_objs,
 
         // Obtain our real execution unit
         // TODO: Should kernels be copyable?
-        GOCLKernel k = gcm.metadata(op_info.nh).get<Unit>().k;
+        GOCLKernel k = gcm.metadata(op_info.nh).get<OCLUnit>().k;
 
         // Initialize kernel's execution context:
         // - Input parameters
index 52cf6d2..da6204b 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GOCLBACKEND_HPP
@@ -23,7 +23,7 @@
 
 namespace cv { namespace gimpl {
 
-struct Unit
+struct OCLUnit
 {
     static const char *name() { return "OCLKernel"; }
     GOCLKernel k;
index 5795f44..07069ae 100644 (file)
@@ -147,6 +147,24 @@ GAPI_OCL_KERNEL(GOCLSobel, cv::gapi::imgproc::GSobel)
     }
 };
 
+GAPI_OCL_KERNEL(GOCLLaplacian, cv::gapi::imgproc::GLaplacian)
+{
+    static void run(const cv::UMat& in, int ddepth, int ksize, double scale,
+                    double delta, int borderType, cv::UMat &out)
+    {
+        cv::Laplacian(in, out, ddepth, ksize, scale, delta, borderType);
+    }
+};
+
+GAPI_OCL_KERNEL(GOCLBilateralFilter, cv::gapi::imgproc::GBilateralFilter)
+{
+    static void run(const cv::UMat& in, int ddepth, double sigmaColor,
+                    double sigmaSpace, int borderType, cv::UMat &out)
+    {
+        cv::bilateralFilter(in, out, ddepth, sigmaColor, sigmaSpace, borderType);
+    }
+};
+
 GAPI_OCL_KERNEL(GOCLEqualizeHist, cv::gapi::imgproc::GEqHist)
 {
     static void run(const cv::UMat& in, cv::UMat &out)
@@ -260,6 +278,8 @@ cv::gapi::GKernelPackage cv::gapi::imgproc::ocl::kernels()
         , GOCLErode
         , GOCLDilate
         , GOCLSobel
+        , GOCLLaplacian
+        , GOCLBilateralFilter
         , GOCLCanny
         , GOCLEqualizeHist
         , GOCLRGB2YUV
index fcd52c9..d2c78eb 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2019 Intel Corporation
+// Copyright (C) 2019-2020 Intel Corporation
 
 
 #ifdef HAVE_PLAIDML
@@ -57,7 +57,7 @@ namespace
                              const std::vector<cv::gimpl::Data>& ins_data,
                              const std::vector<cv::gimpl::Data>& outs_data) const override
         {
-            auto has_config = cv::gimpl::getCompileArg<cv::gapi::plaidml::config>(args);
+            auto has_config = cv::gapi::getCompileArg<cv::gapi::plaidml::config>(args);
 
             if (!has_config)
             {
@@ -212,20 +212,12 @@ void cv::gimpl::GPlaidMLExecutable::bindInArg(const RcDesc &rc, const GRunArg  &
 
         switch (arg.index())
         {
-        case GRunArg::index_of<cv::gapi::own::Mat>():
-        {
-            auto& arg_mat = util::get<cv::gapi::own::Mat>(arg);
-            binder_->input(it->second).copy_from(arg_mat.data);
-        }
-        break;
-#if !defined(GAPI_STANDALONE)
         case GRunArg::index_of<cv::Mat>() :
         {
             auto& arg_mat = util::get<cv::Mat>(arg);
             binder_->input(it->second).copy_from(arg_mat.data);
         }
         break;
-#endif //  !defined(GAPI_STANDALONE)
         default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
         }
     }
@@ -248,20 +240,12 @@ void cv::gimpl::GPlaidMLExecutable::bindOutArg(const RcDesc &rc, const GRunArgP
 
         switch (arg.index())
         {
-        case GRunArgP::index_of<cv::gapi::own::Mat*>():
-        {
-            auto& arg_mat = *util::get<cv::gapi::own::Mat*>(arg);
-            binder_->output(it->second).copy_into(arg_mat.data);
-        }
-        break;
-#if !defined(GAPI_STANDALONE)
         case GRunArgP::index_of<cv::Mat*>() :
         {
             auto& arg_mat = *util::get<cv::Mat*>(arg);
             binder_->output(it->second).copy_into(arg_mat.data);
         }
         break;
-#endif //  !defined(GAPI_STANDALONE)
         default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
         }
     }
index e81e4b7..c15f84c 100644 (file)
@@ -5,12 +5,14 @@
 // Copyright (C) 2019 Intel Corporation
 
 
-#ifdef HAVE_PLAIDML
-
 #include "precomp.hpp"
 
 #include <opencv2/gapi/core.hpp>
+
 #include <opencv2/gapi/plaidml/core.hpp>
+
+#ifdef HAVE_PLAIDML
+
 #include <opencv2/gapi/plaidml/gplaidmlkernel.hpp>
 
 #include <plaidml2/edsl/edsl.h>
@@ -51,4 +53,12 @@ cv::gapi::GKernelPackage cv::gapi::core::plaidml::kernels()
     return pkg;
 }
 
-#endif // HACE_PLAIDML
+#else // HAVE_PLAIDML
+
+cv::gapi::GKernelPackage cv::gapi::core::plaidml::kernels()
+{
+    // Still provide this symbol to avoid linking issues
+    util::throw_error(std::runtime_error("G-API has been compiled without PlaidML2 support"));
+}
+
+#endif // HAVE_PLAIDML
index 4fde80b..e597c49 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 #include "precomp.hpp"
 
@@ -93,7 +93,7 @@ void cv::gimpl::render::ocv::GRenderExecutable::run(std::vector<InObj>  &&input_
 
     context.m_args.emplace_back(m_ftpr.get());
 
-    k.apply(context);
+    k.m_runF(context);
 
     for (auto &it : output_objs) magazine::writeBack(m_res, it.first, it.second);
 }
@@ -113,7 +113,7 @@ cv::GArg cv::gimpl::render::ocv::GRenderExecutable::packArg(const cv::GArg &arg)
     const cv::gimpl::RcDesc &ref = arg.get<cv::gimpl::RcDesc>();
     switch (ref.shape)
     {
-    case GShape::GMAT:   return GArg(m_res.slot<cv::gapi::own::Mat>()[ref.id]);
+    case GShape::GMAT:   return GArg(m_res.slot<cv::Mat>()[ref.id]);
     case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id));
     default:
         util::throw_error(std::logic_error("Unsupported GShape type"));
@@ -136,7 +136,7 @@ namespace {
                              const std::vector<ade::NodeHandle> &nodes) const override {
 
             using namespace cv::gapi::wip::draw;
-            auto has_freetype_font = cv::gimpl::getCompileArg<freetype_font>(args);
+            auto has_freetype_font = cv::gapi::getCompileArg<freetype_font>(args);
             std::unique_ptr<FTTextRender> ftpr;
             if (has_freetype_font)
             {
index bc1d76c..00340da 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -72,6 +72,12 @@ void cv::GCompiled::Priv::reshape(const GMetaArgs& inMetas, const GCompileArgs&
     m_metas = inMetas;
 }
 
+void cv::GCompiled::Priv::prepareForNewStream()
+{
+    GAPI_Assert(m_exec);
+    m_exec->prepareForNewStream();
+}
+
 const cv::gimpl::GModel::Graph& cv::GCompiled::Priv::model() const
 {
     GAPI_Assert(nullptr != m_exec);
@@ -155,3 +161,8 @@ void cv::GCompiled::reshape(const GMetaArgs& inMetas, const GCompileArgs& args)
 {
     m_priv->reshape(inMetas, args);
 }
+
+void cv::GCompiled::prepareForNewStream()
+{
+    m_priv->prepareForNewStream();
+}
index b7bf0f6..f21bfc8 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GCOMPILED_PRIV_HPP
@@ -48,6 +48,7 @@ public:
 
     bool canReshape() const;
     void reshape(const GMetaArgs& inMetas, const GCompileArgs &args);
+    void prepareForNewStream();
 
     void run(cv::gimpl::GRuntimeArgs &&args);
     const GMetaArgs& metas() const;
index 06327dc..6f137a3 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -38,8 +38,9 @@
 
 // <FIXME:>
 #if !defined(GAPI_STANDALONE)
-#include <opencv2/gapi/cpu/core.hpp>    // Also directly refer to Core
-#include <opencv2/gapi/cpu/imgproc.hpp> // ...and Imgproc kernel implementations
+#include <opencv2/gapi/cpu/core.hpp>    // Also directly refer to Core,
+#include <opencv2/gapi/cpu/imgproc.hpp> // ...Imgproc
+#include <opencv2/gapi/cpu/video.hpp>   // ...and Video kernel implementations
 #include <opencv2/gapi/render/render.hpp>   // render::ocv::backend()
 #endif // !defined(GAPI_STANDALONE)
 // </FIXME:>
@@ -60,34 +61,34 @@ namespace
             return combine(pkg, aux_pkg);
         };
 
-        auto has_use_only = cv::gimpl::getCompileArg<cv::gapi::use_only>(args);
+        auto has_use_only = cv::gapi::getCompileArg<cv::gapi::use_only>(args);
         if (has_use_only)
             return withAuxKernels(has_use_only.value().pkg);
 
         static auto ocv_pkg =
 #if !defined(GAPI_STANDALONE)
-            // FIXME add N-arg version combine
-            combine(combine(cv::gapi::core::cpu::kernels(),
-                    cv::gapi::imgproc::cpu::kernels()),
+            combine(cv::gapi::core::cpu::kernels(),
+                    cv::gapi::imgproc::cpu::kernels(),
+                    cv::gapi::video::cpu::kernels(),
                     cv::gapi::render::ocv::kernels());
 #else
             cv::gapi::GKernelPackage();
 #endif // !defined(GAPI_STANDALONE)
 
-        auto user_pkg = cv::gimpl::getCompileArg<cv::gapi::GKernelPackage>(args);
+        auto user_pkg = cv::gapi::getCompileArg<cv::gapi::GKernelPackage>(args);
         auto user_pkg_with_aux = withAuxKernels(user_pkg.value_or(cv::gapi::GKernelPackage{}));
         return combine(ocv_pkg, user_pkg_with_aux);
     }
 
     cv::gapi::GNetPackage getNetworkPackage(cv::GCompileArgs &args)
     {
-        return cv::gimpl::getCompileArg<cv::gapi::GNetPackage>(args)
+        return cv::gapi::getCompileArg<cv::gapi::GNetPackage>(args)
             .value_or(cv::gapi::GNetPackage{});
     }
 
     cv::util::optional<std::string> getGraphDumpDirectory(cv::GCompileArgs& args)
     {
-        auto dump_info = cv::gimpl::getCompileArg<cv::graph_dump_path>(args);
+        auto dump_info = cv::gapi::getCompileArg<cv::graph_dump_path>(args);
         if (!dump_info.has_value())
         {
             const char* path = getenv("GRAPH_DUMP_PATH");
@@ -110,24 +111,6 @@ namespace
         return result;
     }
 
-    // Creates ADE graph from input/output proto args
-    std::unique_ptr<ade::Graph> makeGraph(const cv::GProtoArgs &ins, const cv::GProtoArgs &outs) {
-        std::unique_ptr<ade::Graph> pG(new ade::Graph);
-        ade::Graph& g = *pG;
-
-        cv::gimpl::GModel::Graph gm(g);
-        cv::gimpl::GModel::init(gm);
-        cv::gimpl::GModelBuilder builder(g);
-        auto proto_slots = builder.put(ins, outs);
-
-        // Store Computation's protocol in metadata
-        cv::gimpl::Protocol p;
-        std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
-        gm.metadata().set(p);
-
-        return pG;
-    }
-
     using adeGraphs = std::vector<std::unique_ptr<ade::Graph>>;
 
     // Creates ADE graphs (patterns and substitutes) from pkg's transformations
@@ -145,14 +128,10 @@ namespace
                                       ade::util::toRange(patterns),
                                       ade::util::toRange(substitutes))) {
             const auto& t = std::get<0>(it);
-            auto& p = std::get<1>(it);
-            auto& s = std::get<2>(it);
-
-            auto pattern_comp = t.pattern();
-            p = makeGraph(pattern_comp.priv().m_ins, pattern_comp.priv().m_outs);
-
-            auto substitute_comp = t.substitute();
-            s = makeGraph(substitute_comp.priv().m_ins, substitute_comp.priv().m_outs);
+            auto&       p = std::get<1>(it);
+            auto&       s = std::get<2>(it);
+            p = cv::gimpl::GCompiler::makeGraph(t.pattern().priv());
+            s = cv::gimpl::GCompiler::makeGraph(t.substitute().priv());
         }
     }
 
@@ -310,11 +289,19 @@ cv::gimpl::GCompiler::GCompiler(const cv::GComputation &c,
 
 void cv::gimpl::GCompiler::validateInputMeta()
 {
-    if (m_metas.size() != m_c.priv().m_ins.size())
+    // FIXME: implement testing/accessor methods at the Priv's API level?
+    if (!util::holds_alternative<GComputation::Priv::Expr>(m_c.priv().m_shape))
+    {
+        GAPI_LOG_WARNING(NULL, "Metadata validation is not implemented yet for"
+                               " deserialized graphs!");
+        return;
+    }
+    const auto &c_expr = util::get<cv::GComputation::Priv::Expr>(m_c.priv().m_shape);
+    if (m_metas.size() != c_expr.m_ins.size())
     {
         util::throw_error(std::logic_error
                     ("COMPILE: GComputation interface / metadata mismatch! "
-                     "(expected " + std::to_string(m_c.priv().m_ins.size()) + ", "
+                     "(expected " + std::to_string(c_expr.m_ins.size()) + ", "
                      "got " + std::to_string(m_metas.size()) + " meta arguments)"));
     }
 
@@ -324,6 +311,7 @@ void cv::gimpl::GCompiler::validateInputMeta()
         // FIXME: Auto-generate methods like this from traits:
         case GProtoArg::index_of<cv::GMat>():
         case GProtoArg::index_of<cv::GMatP>():
+        case GProtoArg::index_of<cv::GFrame>():
             return util::holds_alternative<cv::GMatDesc>(meta);
 
         case GProtoArg::index_of<cv::GScalar>():
@@ -341,7 +329,7 @@ void cv::gimpl::GCompiler::validateInputMeta()
         return false; // should never happen
     };
 
-    for (const auto &meta_arg_idx : ade::util::indexed(ade::util::zip(m_metas, m_c.priv().m_ins)))
+    for (const auto &meta_arg_idx : ade::util::indexed(ade::util::zip(m_metas, c_expr.m_ins)))
     {
         const auto &meta  = std::get<0>(ade::util::value(meta_arg_idx));
         const auto &proto = std::get<1>(ade::util::value(meta_arg_idx));
@@ -360,7 +348,15 @@ void cv::gimpl::GCompiler::validateInputMeta()
 
 void cv::gimpl::GCompiler::validateOutProtoArgs()
 {
-    for (const auto &out_pos : ade::util::indexed(m_c.priv().m_outs))
+    // FIXME: implement testing/accessor methods at the Priv's API level?
+    if (!util::holds_alternative<GComputation::Priv::Expr>(m_c.priv().m_shape))
+    {
+        GAPI_LOG_WARNING(NULL, "Output parameter validation is not implemented yet for"
+                               " deserialized graphs!");
+        return;
+    }
+    const auto &c_expr = util::get<cv::GComputation::Priv::Expr>(m_c.priv().m_shape);
+    for (const auto &out_pos : ade::util::indexed(c_expr.m_outs))
     {
         const auto &node = proto::origin_of(ade::util::value(out_pos)).node;
         if (node.shape() != cv::GNode::NodeShape::CALL)
@@ -381,7 +377,7 @@ cv::gimpl::GCompiler::GPtr cv::gimpl::GCompiler::generateGraph()
         validateInputMeta();
     }
     validateOutProtoArgs();
-    auto g = makeGraph(m_c.priv().m_ins, m_c.priv().m_outs);
+    auto g = makeGraph(m_c.priv());
     if (!m_metas.empty())
     {
         GModel::Graph(*g).metadata().set(OriginalInputMeta{m_metas});
@@ -450,7 +446,8 @@ cv::GStreamingCompiled cv::gimpl::GCompiler::produceStreamingCompiled(GPtr &&pg)
         outMetas = GModel::ConstGraph(*pg).metadata().get<OutputMeta>().outMeta;
     }
 
-    std::unique_ptr<GStreamingExecutor> pE(new GStreamingExecutor(std::move(pg)));
+    std::unique_ptr<GStreamingExecutor> pE(new GStreamingExecutor(std::move(pg),
+                                                                  m_args));
     if (!m_metas.empty() && !outMetas.empty())
     {
         compiled.priv().setup(m_metas, outMetas, std::move(pE));
@@ -509,3 +506,27 @@ void cv::gimpl::GCompiler::runMetaPasses(ade::Graph &g, const cv::GMetaArgs &met
     }
     engine.runPasses(g);
 }
+
+// Creates ADE graph from input/output proto args OR from its
+// deserialized form
+cv::gimpl::GCompiler::GPtr cv::gimpl::GCompiler::makeGraph(const cv::GComputation::Priv &priv) {
+    std::unique_ptr<ade::Graph> pG(new ade::Graph);
+    ade::Graph& g = *pG;
+
+    if (cv::util::holds_alternative<cv::GComputation::Priv::Expr>(priv.m_shape)) {
+        auto c_expr = cv::util::get<cv::GComputation::Priv::Expr>(priv.m_shape);
+        cv::gimpl::GModel::Graph gm(g);
+        cv::gimpl::GModel::init(gm);
+        cv::gimpl::GModelBuilder builder(g);
+        auto proto_slots = builder.put(c_expr.m_ins, c_expr.m_outs);
+
+        // Store Computation's protocol in metadata
+        cv::gimpl::Protocol p;
+        std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
+        gm.metadata().set(p);
+    } else if (cv::util::holds_alternative<cv::GComputation::Priv::Dump>(priv.m_shape)) {
+        auto c_dump = cv::util::get<cv::GComputation::Priv::Dump>(priv.m_shape);
+        cv::gimpl::s11n::reconstruct(c_dump, g);
+    }
+    return pG;
+}
index f111d16..85b05d5 100644 (file)
@@ -58,6 +58,8 @@ public:
     GCompiled   produceCompiled(GPtr &&pg);    // Produce GCompiled from processed GModel
     GStreamingCompiled  produceStreamingCompiled(GPtr &&pg); // Produce GStreamingCompiled from processed GMbodel
     static void runMetaPasses(ade::Graph &g, const cv::GMetaArgs &metas);
+
+    static GPtr makeGraph(const cv::GComputation::Priv &);
 };
 
 }}
index 75644fa..a135123 100644 (file)
@@ -12,6 +12,7 @@
 #include <unordered_map>
 
 #include <ade/util/checked_cast.hpp>
+#include <ade/util/zip_range.hpp> // zip_range, indexed
 
 #include "api/gbackend_priv.hpp" // GBackend::Priv().compile()
 #include "compiler/gmodel.hpp"
@@ -117,8 +118,7 @@ ade::NodeHandle GIsland::producer(const ade::Graph &g,
     }
     // Consistency: A GIsland requested for producer() of slot_nh should
     // always had the appropriate GModel node handle in its m_out_ops vector.
-    GAPI_Assert(false);
-    return ade::NodeHandle();
+    GAPI_Assert(false && "Broken GIslandModel ?.");
 }
 
 std::string GIsland::name() const
@@ -319,5 +319,60 @@ ade::NodeHandle GIslandModel::producerOf(const ConstGraph &g, ade::NodeHandle &d
     return ade::NodeHandle();
 }
 
+void GIslandExecutable::run(GIslandExecutable::IInput &in, GIslandExecutable::IOutput &out)
+{
+    // Default implementation: just reuse the existing old-fashioned run
+    // Build a single synchronous execution frame for it.
+    std::vector<InObj>  in_objs;
+    std::vector<OutObj> out_objs;
+    const auto &in_desc  = in.desc();
+    const auto &out_desc = out.desc();
+    const auto  in_msg   = in.get();
+    if (cv::util::holds_alternative<cv::gimpl::EndOfStream>(in_msg))
+    {
+        out.post(cv::gimpl::EndOfStream{});
+        return;
+    }
+    GAPI_Assert(cv::util::holds_alternative<cv::GRunArgs>(in_msg));
+    const auto in_vector = cv::util::get<cv::GRunArgs>(in_msg);
+    in_objs.reserve(in_desc.size());
+    out_objs.reserve(out_desc.size());
+    for (auto &&it: ade::util::zip(ade::util::toRange(in_desc),
+                                   ade::util::toRange(in_vector)))
+    {
+        // FIXME: Not every Island expects a cv::Mat instead of own::Mat on input
+        // This kludge should go as a result of de-ownification
+        const cv::GRunArg& in_data_orig = std::get<1>(it);
+        cv::GRunArg in_data;
+#if !defined(GAPI_STANDALONE)
+        switch (in_data_orig.index())
+        {
+        case cv::GRunArg::index_of<cv::Mat>():
+            in_data = cv::GRunArg{cv::util::get<cv::Mat>(in_data_orig)};
+            break;
+        case cv::GRunArg::index_of<cv::Scalar>():
+            in_data = cv::GRunArg{(cv::util::get<cv::Scalar>(in_data_orig))};
+            break;
+        default:
+            in_data = in_data_orig;
+            break;
+        }
+#else
+        in_data = in_data_orig;
+#endif // GAPI_STANDALONE
+        in_objs.emplace_back(std::get<0>(it), std::move(in_data));
+    }
+    for (auto &&it: ade::util::indexed(ade::util::toRange(out_desc)))
+    {
+        out_objs.emplace_back(ade::util::value(it),
+                              out.get(ade::util::checked_cast<int>(ade::util::index(it))));
+    }
+    run(std::move(in_objs), std::move(out_objs));
+    for (auto &&it: out_objs)
+    {
+        out.post(std::move(it.second)); // report output objects as "ready" to the executor
+    }
+}
+
 } // namespace cv
 } // namespace gimpl
index 5998115..390bdb5 100644 (file)
@@ -89,33 +89,82 @@ protected:
     util::optional<std::string> m_user_tag;
 };
 
-
-
 // GIslandExecutable - a backend-specific thing which executes
 // contents of an Island
 // * Is instantiated by the last step of the Islands fusion procedure;
 // * Is orchestrated by a GExecutor instance.
 //
-
-class GIslandExecutable
+// GAPI_EXPORTS is here since this class comes with the default
+// implementation to some methods and it needs to be exported to allow
+// it to use in the external (extra) backends.
+class GAPI_EXPORTS GIslandExecutable
 {
 public:
     using InObj  = std::pair<RcDesc, cv::GRunArg>;
     using OutObj = std::pair<RcDesc, cv::GRunArgP>;
 
+    class  IODesc;
+    struct IInput;
+    struct IOutput;
+
     // FIXME: now run() requires full input vector to be available.
     // actually, parts of subgraph may execute even if there's no all data
     // slots in place.
     // TODO: Add partial execution capabilities
+    // TODO: This method is now obsolette and is here for backwards
+    //       compatibility only.  Use (implement) the new run instead.
     virtual void run(std::vector<InObj>  &&input_objs,
                      std::vector<OutObj> &&output_objs) = 0;
 
+    // Let the island execute. I/O data is obtained from/submitted to
+    // in/out objects.
+    virtual void run(IInput &in, IOutput &out);
+
     virtual bool canReshape() const = 0;
     virtual void reshape(ade::Graph& g, const GCompileArgs& args) = 0;
 
+    // This method is called when the GStreamingCompiled gets a new
+    // input source to process. Normally this method is called once
+    // per stream execution.
+    //
+    // The idea of this method is to reset backend's stream-associated
+    // internal state, if there is any.
+    //
+    // The regular GCompiled invocation doesn't call this, there may
+    // be reset() introduced there but it is completely unnecessary at
+    // this moment.
+    //
+    // FIXME: The design on this and so-called "stateful" kernels is not
+    // closed yet.
+    // FIXME: This thing will likely break stuff once we introduce
+    // "multi-source streaming", a better design needs to be proposed
+    // at that stage.
+    virtual void handleNewStream() {}; // do nothing here by default
+
     virtual ~GIslandExecutable() = default;
 };
 
+class GIslandExecutable::IODesc {
+    std::vector<cv::gimpl::RcDesc> d;
+public:
+    void set(std::vector<cv::gimpl::RcDesc> &&newd)      { d = std::move(newd); }
+    void set(const std::vector<cv::gimpl::RcDesc> &newd) { d = newd; }
+    const std::vector<cv::gimpl::RcDesc> &desc() const   { return d; }
+};
+struct EndOfStream {};
+using StreamMsg = cv::util::variant<EndOfStream, cv::GRunArgs>;
+struct GIslandExecutable::IInput: public GIslandExecutable::IODesc {
+    virtual ~IInput() = default;
+    virtual StreamMsg get() = 0;     // Get a new input vector (blocking)
+    virtual StreamMsg try_get() = 0; // Get a new input vector (non-blocking)
+};
+struct GIslandExecutable::IOutput: public GIslandExecutable::IODesc {
+    virtual ~IOutput() = default;
+    virtual GRunArgP get(int idx) = 0;  // Allocate (wrap) a new data object for output idx
+    virtual void post(GRunArgP&&) = 0;  // Release the object back to the framework (mark available)
+    virtual void post(EndOfStream&&) = 0; // Post end-of-stream marker back to the framework
+};
+
 // GIslandEmitter - a backend-specific thing which feeds data into
 // the pipeline. This one is just an interface, implementations are executor-defined.
 class GIslandEmitter
index cbeaf81..39dc1da 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -54,7 +54,7 @@ ade::NodeHandle GModel::mkDataNode(GModel::Graph &g, const GOrigin& origin)
     // associated host-type constructor (e.g. when the array is
     // somewhere in the middle of the graph).
     auto ctor_copy = origin.ctor;
-    g.metadata(data_h).set(Data{origin.shape, id, meta, ctor_copy, storage});
+    g.metadata(data_h).set(Data{origin.shape, id, meta, ctor_copy, origin.kind, storage});
     return data_h;
 }
 
@@ -67,8 +67,9 @@ ade::NodeHandle GModel::mkDataNode(GModel::Graph &g, const GShape shape)
     GMetaArg meta;
     HostCtor ctor;
     Data::Storage storage = Data::Storage::INTERNAL; // By default, all objects are marked INTERNAL
+    cv::detail::OpaqueKind kind = cv::detail::OpaqueKind::CV_UNKNOWN;
 
-    g.metadata(data_h).set(Data{shape, id, meta, ctor, storage});
+    g.metadata(data_h).set(Data{shape, id, meta, ctor, kind, storage});
     return data_h;
 }
 
index bb327d0..8f78ba4 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GMODEL_HPP
@@ -26,6 +26,7 @@
 
 #include <opencv2/gapi/garg.hpp>
 #include <opencv2/gapi/gkernel.hpp>
+#include <opencv2/gapi/gcommon.hpp>
 
 #include "compiler/gobjref.hpp"
 #include "compiler/gislandmodel.hpp"
@@ -71,9 +72,10 @@ struct Data
     int      rc;
     GMetaArg meta;
     HostCtor ctor;  // T-specific helper to deal with unknown types in our code
+    cv::detail::OpaqueKind kind; // FIXME: is needed to store GArray/GOpaque type
     // FIXME: Why rc+shape+meta is not represented as RcDesc here?
 
-    enum class Storage
+    enum class Storage: int
     {
         INTERNAL,   // data object is not listed in GComputation protocol
         INPUT,      // data object is listed in GComputation protocol as Input
@@ -138,7 +140,9 @@ class DataObjectCounter
 public:
     static const char* name() { return "DataObjectCounter"; }
     int GetNewId(GShape shape) { return m_next_data_id[shape]++; }
-private:
+
+    // NB: private!!! but used in the serialization
+    // couldn't get the `friend` stuff working correctly -- DM
     std::unordered_map<cv::GShape, int> m_next_data_id;
 };
 
@@ -166,6 +170,19 @@ struct Streaming
     static const char *name() { return "StreamingFlag"; }
 };
 
+
+// This is a graph-global flag indicating this graph is compiled
+// after the deserialization. Some bits of information may be
+// unavailable (mainly callbacks) so let sensitive passes obtain
+// the required information in their special way.
+//
+// FIXME: Probably a better design can be suggested.
+struct Deserialized
+{
+    static const char *name() { return "DeserializedFlag"; }
+};
+
+
 // Backend-specific inference parameters for a neural network.
 // Since these parameters are set on compilation stage (not
 // on a construction stage), these parameters are bound lately
@@ -213,6 +230,7 @@ namespace GModel
         , ActiveBackends
         , CustomMetaFunction
         , Streaming
+        , Deserialized
         >;
 
     // FIXME: How to define it based on GModel???
@@ -234,6 +252,7 @@ namespace GModel
         , ActiveBackends
         , CustomMetaFunction
         , Streaming
+        , Deserialized
         >;
 
     // FIXME:
index c53c7b2..87e9ab5 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -139,7 +139,7 @@ cv::gimpl::Unrolled cv::gimpl::unrollExpr(const GProtoArgs &ins,
                     std::size_t port  = ade::util::index(it);
                     GShape shape      = ade::util::value(it);
 
-                    GOrigin org { shape, node, port};
+                    GOrigin org { shape, node, port, {}, origin.kind };
                     origins.insert(org);
                 }
 
index acbb64b..dd0939c 100644 (file)
@@ -29,6 +29,7 @@ namespace gimpl
     using ConstVal = util::variant
     < util::monostate
     , cv::Scalar
+    , cv::detail::VectorRef
     >;
 
     struct RcDesc
index 84b3621..69b339f 100644 (file)
@@ -150,6 +150,17 @@ void cv::gimpl::passes::resolveKernels(ade::passes::PassContext   &ctx,
             selected_backend.priv().unpackKernel(ctx.graph, nh, selected_impl);
             op.backend = selected_backend;
             active_backends.insert(selected_backend);
+
+            if (gr.metadata().contains<Deserialized>())
+            {
+                // Trick: in this case, the op.k.outMeta is by default
+                // missing. Take it from the resolved kernel
+                GAPI_Assert(op.k.outMeta == nullptr);
+                const_cast<cv::GKernel::M&>(op.k.outMeta) = selected_impl.outMeta;
+            } else {
+                // Sanity check: the metadata funciton must be present
+                GAPI_Assert(op.k.outMeta != nullptr);
+            }
         }
     }
     gr.metadata().set(ActiveBackends{active_backends});
index 40c6f9a..51d4c88 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -94,18 +94,21 @@ void cv::gimpl::passes::inferMeta(ade::passes::PassContext &ctx, bool meta_is_in
                 GAPI_Assert(gr.metadata(output_nh).get<NodeType>().t == NodeType::DATA);
 
                 auto       &output_meta = gr.metadata(output_nh).get<Data>().meta;
-                if (!meta_is_initialized && !util::holds_alternative<util::monostate>(output_meta))
-                {
-                    GAPI_LOG_INFO(NULL,
-                                  "!!! Output object has an initialized meta - "
-                                  "how it is possible today?" << std::endl; );
-                    if (output_meta != out_metas.at(output_port))
-                    {
-                      util::throw_error(std::logic_error("Fatal: meta mismatch"));
-                        // FIXME: New exception type?
-                        // FIXME: More details!
-                    }
-                }
+
+                cv::util::suppress_unused_warning(meta_is_initialized);
+                // FIXME: calling compile() with meta the second time when cannot reshape will lead to error below
+                //if (!meta_is_initialized && !util::holds_alternative<util::monostate>(output_meta))
+                //{
+                //    GAPI_LOG_INFO(NULL,
+                //                  "!!! Output object has an initialized meta - "
+                //                  "how it is possible today?" << std::endl; );
+                //    if (output_meta != out_metas.at(output_port))
+                //    {
+                //      util::throw_error(std::logic_error("Fatal: meta mismatch"));
+                //        // FIXME: New exception type?
+                //        // FIXME: More details!
+                //    }
+                //}
                 // Store meta in graph
                 output_meta = out_metas.at(output_port);
             }
index f3b9638..62407fe 100644 (file)
@@ -77,7 +77,8 @@ bool tryToSubstitute(ade::Graph& main,
 
     // 2. build substitute graph inside the main graph
     cv::gimpl::GModelBuilder builder(main);
-    const auto& proto_slots = builder.put(substitute.priv().m_ins, substitute.priv().m_outs);
+    auto expr = cv::util::get<cv::GComputation::Priv::Expr>(substitute.priv().m_shape);
+    const auto& proto_slots = builder.put(expr.m_ins, expr.m_outs);
     Protocol substituteP;
     std::tie(substituteP.inputs, substituteP.outputs, substituteP.in_nhs, substituteP.out_nhs) =
         proto_slots;
index d316f5b..eb5ac27 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "precomp.hpp"
@@ -100,7 +100,7 @@ void cv::gimpl::GExecutor::initResource(const ade::NodeHandle &orig_nh)
     case GShape::GMAT:
         {
             const auto desc = util::get<cv::GMatDesc>(d.meta);
-            auto& mat = m_res.slot<cv::gapi::own::Mat>()[d.rc];
+            auto& mat = m_res.slot<cv::Mat>()[d.rc];
             createMat(desc, mat);
         }
         break;
@@ -114,6 +114,13 @@ void cv::gimpl::GExecutor::initResource(const ade::NodeHandle &orig_nh)
         break;
 
     case GShape::GARRAY:
+        if (d.storage == Data::Storage::CONST_VAL)
+        {
+            auto rc = RcDesc{d.rc, d.shape, d.ctor};
+            magazine::bindInArg(m_res, rc, m_gm.metadata(orig_nh).get<ConstValue>().arg);
+        }
+        break;
+    case GShape::GOPAQUE:
         // Constructed on Reset, do nothing here
         break;
 
@@ -122,6 +129,30 @@ void cv::gimpl::GExecutor::initResource(const ade::NodeHandle &orig_nh)
     }
 }
 
+class cv::gimpl::GExecutor::Input final: public cv::gimpl::GIslandExecutable::IInput
+{
+    cv::gimpl::Mag &mag;
+    virtual StreamMsg get() override
+    {
+        cv::GRunArgs res;
+        for (const auto &rc : desc()) { res.emplace_back(magazine::getArg(mag, rc)); }
+        return StreamMsg{std::move(res)};
+    }
+    virtual StreamMsg try_get() override { return get(); }
+public:
+    Input(cv::gimpl::Mag &m, const std::vector<RcDesc> &rcs) : mag(m) { set(rcs); }
+};
+
+class cv::gimpl::GExecutor::Output final: public cv::gimpl::GIslandExecutable::IOutput
+{
+    cv::gimpl::Mag &mag;
+    virtual GRunArgP get(int idx) override { return magazine::getObjPtr(mag, desc()[idx]); }
+    virtual void post(GRunArgP&&) override { } // Do nothing here
+    virtual void post(EndOfStream&&) override {} // Do nothing here too
+public:
+    Output(cv::gimpl::Mag &m, const std::vector<RcDesc> &rcs) : mag(m) { set(rcs); }
+};
+
 void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
 {
     // (2)
@@ -144,8 +175,9 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
 
     namespace util = ade::util;
 
-    //ensure that output Mat parameters are correctly allocated
-    for (auto index : util::iota(proto.out_nhs.size()) )     //FIXME: avoid copy of NodeHandle and GRunRsltComp ?
+    // ensure that output Mat parameters are correctly allocated
+    // FIXME: avoid copy of NodeHandle and GRunRsltComp ?
+    for (auto index : util::iota(proto.out_nhs.size()))
     {
         auto& nh = proto.out_nhs.at(index);
         const Data &d = m_gm.metadata(nh).get<Data>();
@@ -156,14 +188,15 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
 
             auto check_own_mat = [&desc, &args, &index]()
             {
-                auto& out_mat = *get<cv::gapi::own::Mat*>(args.outObjs.at(index));
+                auto& out_mat = *get<cv::Mat*>(args.outObjs.at(index));
                 GAPI_Assert(out_mat.data != nullptr &&
                         desc.canDescribe(out_mat));
             };
 
 #if !defined(GAPI_STANDALONE)
-            // Building as part of OpenCV - follow OpenCV behavior
-            // In the case of cv::Mat if output buffer is not enough to hold the result, reallocate it
+            // Building as part of OpenCV - follow OpenCV behavior In
+            // the case of cv::Mat if output buffer is not enough to
+            // hold the result, reallocate it
             if (cv::util::holds_alternative<cv::Mat*>(args.outObjs.at(index)))
             {
                 auto& out_mat = *get<cv::Mat*>(args.outObjs.at(index));
@@ -204,24 +237,9 @@ void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
     for (auto &op : m_ops)
     {
         // (5)
-        using InObj  = GIslandExecutable::InObj;
-        using OutObj = GIslandExecutable::OutObj;
-        std::vector<InObj>  in_objs;
-        std::vector<OutObj> out_objs;
-        in_objs.reserve (op.in_objects.size());
-        out_objs.reserve(op.out_objects.size());
-
-        for (const auto &rc : op.in_objects)
-        {
-            in_objs.emplace_back(InObj{rc, magazine::getArg(m_res, rc)});
-        }
-        for (const auto &rc : op.out_objects)
-        {
-            out_objs.emplace_back(OutObj{rc, magazine::getObjPtr(m_res, rc)});
-        }
-
-        // (6)
-        op.isl_exec->run(std::move(in_objs), std::move(out_objs));
+        Input i{m_res, op.in_objects};
+        Output o{m_res, op.out_objects};
+        op.isl_exec->run(i, o);
     }
 
     // (7)
@@ -253,3 +271,11 @@ void cv::gimpl::GExecutor::reshape(const GMetaArgs& inMetas, const GCompileArgs&
     passes::inferMeta(ctx, true);
     m_ops[0].isl_exec->reshape(g, args);
 }
+
+void cv::gimpl::GExecutor::prepareForNewStream()
+{
+    for (auto &op : m_ops)
+    {
+        op.isl_exec->handleNewStream();
+    }
+}
index e4128ba..d4fe96e 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_GEXECUTOR_HPP
@@ -77,6 +77,9 @@ protected:
     };
     std::vector<DataDesc> m_slots;
 
+    class Input;
+    class Output;
+
     Mag m_res;
 
     void initResource(const ade::NodeHandle &orig_nh); // FIXME: shouldn't it be RcDesc?
@@ -88,6 +91,8 @@ public:
     bool canReshape() const;
     void reshape(const GMetaArgs& inMetas, const GCompileArgs& args);
 
+    void prepareForNewStream();
+
     const GModel::Graph& model() const; // FIXME: make it ConstGraph?
 };
 
index 70be78f..1f9af29 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2019 Intel Corporation
+// Copyright (C) 2019-2020 Intel Corporation
 
 #include "precomp.hpp"
 
 
 #include <opencv2/gapi/opencv_includes.hpp>
 
-#include "executor/gstreamingexecutor.hpp"
+#include "api/gproto_priv.hpp" // ptr(GRunArgP)
 #include "compiler/passes/passes.hpp"
 #include "backends/common/gbackend.hpp" // createMat
 #include "compiler/gcompiler.hpp" // for compileIslands
 
+#include "executor/gstreamingexecutor.hpp"
+
 namespace
 {
 using namespace cv::gimpl::stream;
@@ -96,8 +98,6 @@ std::vector<cv::gimpl::stream::Q*> input_queues(      ade::Graph &g,
 
 void sync_data(cv::GRunArgs &results, cv::GRunArgsP &outputs)
 {
-    namespace own = cv::gapi::own;
-
     for (auto && it : ade::util::zip(ade::util::toRange(outputs),
                                      ade::util::toRange(results)))
     {
@@ -108,20 +108,18 @@ void sync_data(cv::GRunArgs &results, cv::GRunArgsP &outputs)
         using T = cv::GRunArgP;
         switch (out_obj.index())
         {
-#if !defined(GAPI_STANDALONE)
         case T::index_of<cv::Mat*>():
             *cv::util::get<cv::Mat*>(out_obj) = std::move(cv::util::get<cv::Mat>(res_obj));
             break;
-#endif // !GAPI_STANDALONE
-        case T::index_of<own::Mat*>():
-            *cv::util::get<own::Mat*>(out_obj) = std::move(cv::util::get<own::Mat>(res_obj));
-            break;
         case T::index_of<cv::Scalar*>():
             *cv::util::get<cv::Scalar*>(out_obj) = std::move(cv::util::get<cv::Scalar>(res_obj));
             break;
         case T::index_of<cv::detail::VectorRef>():
             cv::util::get<cv::detail::VectorRef>(out_obj).mov(cv::util::get<cv::detail::VectorRef>(res_obj));
             break;
+        case T::index_of<cv::detail::OpaqueRef>():
+            cv::util::get<cv::detail::OpaqueRef>(out_obj).mov(cv::util::get<cv::detail::OpaqueRef>(res_obj));
+            break;
         default:
             GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode.
             break;
@@ -359,6 +357,203 @@ void emitterActorThread(std::shared_ptr<cv::gimpl::GIslandEmitter> emitter,
     }
 }
 
+class StreamingInput final: public cv::gimpl::GIslandExecutable::IInput
+{
+    QueueReader &qr;
+    std::vector<Q*> &in_queues; // FIXME: This can be part of QueueReader
+    cv::GRunArgs &in_constants; // FIXME: This can be part of QueueReader
+
+    virtual cv::gimpl::StreamMsg get() override
+    {
+        cv::GRunArgs isl_input_args;
+        if (!qr.getInputVector(in_queues, in_constants, isl_input_args))
+        {
+            // Stop case
+            return cv::gimpl::StreamMsg{cv::gimpl::EndOfStream{}};
+        }
+        return cv::gimpl::StreamMsg{std::move(isl_input_args)};
+    }
+    virtual cv::gimpl::StreamMsg try_get() override
+    {
+        // FIXME: This is not very usable at the moment!
+        return get();
+    }
+ public:
+    explicit StreamingInput(QueueReader &rdr,
+                            std::vector<Q*> &inq,
+                            cv::GRunArgs &inc,
+                            const std::vector<cv::gimpl::RcDesc> &in_descs)
+        : qr(rdr), in_queues(inq), in_constants(inc)
+    {
+        set(in_descs);
+    }
+};
+
+class StreamingOutput final: public cv::gimpl::GIslandExecutable::IOutput
+{
+    // These objects form an internal state of the StreamingOutput
+    struct Posting
+    {
+        using V = cv::util::variant<cv::GRunArg, cv::gimpl::EndOfStream>;
+        V data;
+        bool ready = false;
+    };
+    using PostingList = std::list<Posting>;
+    std::vector<PostingList> m_postings;
+    std::unordered_map< const void*
+                      , std::pair<int, PostingList::iterator>
+                      > m_postIdx;
+    std::size_t m_stops_sent = 0u;
+
+    // These objects are owned externally
+    const cv::GMetaArgs &m_metas;
+    std::vector< std::vector<Q*> > &m_out_queues;
+
+    // Allocate a new data object for output under idx
+    // Prepare this object for posting
+    virtual cv::GRunArgP get(int idx) override
+    {
+        using MatType = cv::Mat;
+        using SclType = cv::Scalar;
+
+        // Allocate a new posting first, then bind this GRunArgP to this item
+        auto iter    = m_postings[idx].insert(m_postings[idx].end(), Posting{});
+        const auto r = desc()[idx];
+        cv::GRunArg& out_arg = cv::util::get<cv::GRunArg>(iter->data);
+        cv::GRunArgP ret_val;
+        switch (r.shape) {
+            // Allocate a data object based on its shape & meta, and put it into our vectors.
+            // Yes, first we put a cv::Mat GRunArg, and then specify _THAT_
+            // pointer as an output parameter - to make sure that after island completes,
+            // our GRunArg still has the right (up-to-date) value.
+            // Same applies to other types.
+            // FIXME: This is absolutely ugly but seem to work perfectly for its purpose.
+        case cv::GShape::GMAT:
+            {
+                MatType newMat;
+                cv::gimpl::createMat(cv::util::get<cv::GMatDesc>(m_metas[idx]), newMat);
+                out_arg = cv::GRunArg(std::move(newMat));
+                ret_val = cv::GRunArgP(&cv::util::get<MatType>(out_arg));
+            }
+            break;
+        case cv::GShape::GSCALAR:
+            {
+                SclType newScl;
+                out_arg = cv::GRunArg(std::move(newScl));
+                ret_val = cv::GRunArgP(&cv::util::get<SclType>(out_arg));
+            }
+            break;
+        case cv::GShape::GARRAY:
+            {
+                cv::detail::VectorRef newVec;
+                cv::util::get<cv::detail::ConstructVec>(r.ctor)(newVec);
+                out_arg = cv::GRunArg(std::move(newVec));
+                // VectorRef is implicitly shared so no pointer is taken here
+                // FIXME: that variant MOVE problem again
+                const auto &rr = cv::util::get<cv::detail::VectorRef>(out_arg);
+                ret_val = cv::GRunArgP(rr);
+            }
+            break;
+        case cv::GShape::GOPAQUE:
+            {
+                cv::detail::OpaqueRef newOpaque;
+                cv::util::get<cv::detail::ConstructOpaque>(r.ctor)(newOpaque);
+                out_arg = cv::GRunArg(std::move(newOpaque));
+                // OpaqueRef is implicitly shared so no pointer is taken here
+                // FIXME: that variant MOVE problem again
+                const auto &rr = cv::util::get<cv::detail::OpaqueRef>(out_arg);
+                ret_val = cv::GRunArgP(rr);
+            }
+            break;
+        default:
+            cv::util::throw_error(std::logic_error("Unsupported GShape"));
+        }
+        m_postIdx[cv::gimpl::proto::ptr(ret_val)] = std::make_pair(idx, iter);
+        return ret_val;
+    }
+    virtual void post(cv::GRunArgP&& argp) override
+    {
+        // Mark the output ready for posting. If it is the first in the line,
+        // actually post it and all its successors which are ready for posting too.
+        auto it = m_postIdx.find(cv::gimpl::proto::ptr(argp));
+        GAPI_Assert(it != m_postIdx.end());
+        const int out_idx = it->second.first;
+        const auto out_iter = it->second.second;
+        out_iter->ready = true;
+        m_postIdx.erase(it); // Drop the link from the cache anyway
+        if (out_iter != m_postings[out_idx].begin())
+        {
+            return; // There are some pending postings in the beginning, return
+        }
+
+        GAPI_Assert(out_iter == m_postings[out_idx].begin());
+        auto post_iter = m_postings[out_idx].begin();
+        while (post_iter != m_postings[out_idx].end() && post_iter->ready == true)
+        {
+            Cmd cmd;
+            if (cv::util::holds_alternative<cv::GRunArg>(post_iter->data))
+            {
+                // FIXME: That ugly VARIANT problem
+                cmd = Cmd{const_cast<const cv::GRunArg&>(cv::util::get<cv::GRunArg>(post_iter->data))};
+            }
+            else
+            {
+                GAPI_Assert(cv::util::holds_alternative<cv::gimpl::EndOfStream>(post_iter->data));
+                cmd = Cmd{Stop{}};
+                m_stops_sent++;
+            }
+            for (auto &&q : m_out_queues[out_idx])
+            {
+                // FIXME: This ugly VARIANT problem
+                q->push(const_cast<const Cmd&>(cmd));
+            }
+            post_iter = m_postings[out_idx].erase(post_iter);
+        }
+    }
+    virtual void post(cv::gimpl::EndOfStream&&) override
+    {
+        // If the posting list is empty, just broadcast the stop message.
+        // If it is not, enqueue the Stop message in the postings list.
+        for (auto &&it : ade::util::indexed(m_postings))
+        {
+            const auto  idx = ade::util::index(it);
+                  auto &lst = ade::util::value(it);
+            if (lst.empty())
+            {
+                for (auto &&q : m_out_queues[idx])
+                {
+                    q->push(Cmd(Stop{}));
+                }
+                m_stops_sent++;
+            }
+            else
+            {
+                Posting p;
+                p.data = Posting::V{cv::gimpl::EndOfStream{}};
+                p.ready = true;
+                lst.push_back(std::move(p)); // FIXME: For some reason {}-ctor didn't work here
+            }
+        }
+    }
+public:
+    explicit StreamingOutput(const cv::GMetaArgs &metas,
+                             std::vector< std::vector<Q*> > &out_queues,
+                             const std::vector<cv::gimpl::RcDesc> &out_descs)
+        : m_metas(metas)
+        , m_out_queues(out_queues)
+    {
+        set(out_descs);
+        m_postings.resize(out_descs.size());
+    }
+
+    bool done() const
+    {
+        // The streaming actor work is considered DONE for this stream
+        // when it posted/resent all STOP messages to all its outputs.
+        return m_stops_sent == desc().size();
+    }
+};
+
 // This thread is a plain dumb processing actor. What it do is just:
 // - Reads input from the input queue(s), sleeps if there's nothing to read
 // - Once a full input vector is obtained, passes it to the underlying island
@@ -377,123 +572,11 @@ void islandActorThread(std::vector<cv::gimpl::RcDesc> in_rcs,                //
     GAPI_Assert(out_queues.size() == out_rcs.size());
     GAPI_Assert(out_queues.size() == out_metas.size());
     QueueReader qr;
-    while (true)
+    StreamingInput input(qr, in_queues, in_constants, in_rcs);
+    StreamingOutput output(out_metas, out_queues, out_rcs);
+    while (!output.done())
     {
-        std::vector<cv::gimpl::GIslandExecutable::InObj> isl_inputs;
-        isl_inputs.resize(in_rcs.size());
-
-        cv::GRunArgs isl_input_args;
-        if (!qr.getInputVector(in_queues, in_constants, isl_input_args))
-        {
-            // Stop received -- broadcast Stop down to the pipeline and quit
-            for (auto &&out_qq : out_queues)
-            {
-                for (auto &&out_q : out_qq) out_q->push(Cmd{Stop{}});
-            }
-            return;
-        }
-        GAPI_Assert(isl_inputs.size() == isl_input_args.size());
-        for (auto &&it : ade::util::indexed(ade::util::zip(ade::util::toRange(in_rcs),
-                                            ade::util::toRange(isl_inputs),
-                                            ade::util::toRange(isl_input_args))))
-        {
-            const auto &value     = ade::util::value(it);
-            const auto &in_rc     = std::get<0>(value);
-            auto       &isl_input = std::get<1>(value);
-            const auto &in_arg    = std::get<2>(value); // FIXME: MOVE PROBLEM
-            isl_input.first = in_rc;
-#if defined(GAPI_STANDALONE)
-            // Standalone mode - simply store input argument in the vector as-is
-            auto id               = ade::util::index(it);
-            isl_inputs[id].second = in_arg;
-#else
-            // Make Islands operate on own:: data types (i.e. in the same
-            // environment as GExecutor provides)
-            // This way several backends (e.g. Fluid) remain OpenCV-independent.
-            switch (in_arg.index()) {
-            case cv::GRunArg::index_of<cv::Mat>():
-                isl_input.second = cv::GRunArg{cv::to_own(cv::util::get<cv::Mat>(in_arg))};
-                break;
-            case cv::GRunArg::index_of<cv::Scalar>():
-                isl_input.second = cv::GRunArg{cv::util::get<cv::Scalar>(in_arg)};
-                break;
-            default:
-                isl_input.second = in_arg;
-                break;
-            }
-#endif // GAPI_STANDALONE
-        }
-        // Once the vector is obtained, prepare data for island execution
-        // Note - we first allocate output vector via GRunArg!
-        // Then it is converted to a GRunArgP.
-        std::vector<cv::gimpl::GIslandExecutable::OutObj> isl_outputs;
-        cv::GRunArgs out_data;
-        isl_outputs.resize(out_rcs.size());
-        out_data.resize(out_rcs.size());
-        for (auto &&it : ade::util::indexed(out_rcs))
-        {
-            auto id = ade::util::index(it);
-            auto &r = ade::util::value(it);
-
-#if !defined(GAPI_STANDALONE)
-            using MatType = cv::Mat;
-            using SclType = cv::Scalar;
-#else
-            using MatType = cv::gapi::own::Mat;
-            using SclType = cv::Scalar;
-#endif // GAPI_STANDALONE
-
-            switch (r.shape) {
-                // Allocate a data object based on its shape & meta, and put it into our vectors.
-                // Yes, first we put a cv::Mat GRunArg, and then specify _THAT_
-                // pointer as an output parameter - to make sure that after island completes,
-                // our GRunArg still has the right (up-to-date) value.
-                // Same applies to other types.
-                // FIXME: This is absolutely ugly but seem to work perfectly for its purpose.
-            case cv::GShape::GMAT:
-                {
-                    MatType newMat;
-                    cv::gimpl::createMat(cv::util::get<cv::GMatDesc>(out_metas[id]), newMat);
-                    out_data[id] = cv::GRunArg(std::move(newMat));
-                    isl_outputs[id] = { r, cv::GRunArgP(&cv::util::get<MatType>(out_data[id])) };
-                }
-                break;
-            case cv::GShape::GSCALAR:
-                {
-                    SclType newScl;
-                    out_data[id] = cv::GRunArg(std::move(newScl));
-                    isl_outputs[id] = { r, cv::GRunArgP(&cv::util::get<SclType>(out_data[id])) };
-                }
-                break;
-            case cv::GShape::GARRAY:
-                {
-                    cv::detail::VectorRef newVec;
-                    cv::util::get<cv::detail::ConstructVec>(r.ctor)(newVec);
-                    out_data[id] = cv::GRunArg(std::move(newVec));
-                    // VectorRef is implicitly shared so no pointer is taken here
-                    const auto &rr = cv::util::get<cv::detail::VectorRef>(out_data[id]); // FIXME: that variant MOVE problem again
-                    isl_outputs[id] = { r, cv::GRunArgP(rr) };
-                }
-                break;
-            default:
-                cv::util::throw_error(std::logic_error("Unsupported GShape"));
-                break;
-            }
-        }
-        // Now ask Island to execute on this data
-        island->run(std::move(isl_inputs), std::move(isl_outputs));
-
-        // Once executed, dispatch our results down to the pipeline.
-        for (auto &&it : ade::util::zip(ade::util::toRange(out_queues),
-                                        ade::util::toRange(out_data)))
-        {
-            for (auto &&q : std::get<0>(it))
-            {
-                // FIXME: FATAL VARIANT ISSUE!!
-                const auto tmp = std::get<1>(it);
-                q->push(Cmd{tmp});
-            }
-        }
+        island->run(input, output);
     }
 }
 
@@ -520,10 +603,14 @@ void collectorThread(std::vector<Q*> in_queues,
 }
 } // anonymous namespace
 
-cv::gimpl::GStreamingExecutor::GStreamingExecutor(std::unique_ptr<ade::Graph> &&g_model)
+// GStreamingExecutor expects compile arguments as input to have possibility to do
+// proper graph reshape and islands recompilation
+cv::gimpl::GStreamingExecutor::GStreamingExecutor(std::unique_ptr<ade::Graph> &&g_model,
+                                                  const GCompileArgs &comp_args)
     : m_orig_graph(std::move(g_model))
     , m_island_graph(GModel::Graph(*m_orig_graph).metadata()
                      .get<IslandModel>().model)
+    , m_comp_args(comp_args)
     , m_gim(*m_island_graph)
 {
     GModel::Graph gm(*m_orig_graph);
@@ -717,6 +804,7 @@ void cv::gimpl::GStreamingExecutor::setSource(GRunArgs &&ins)
             }
         }
     };
+    bool islandsRecompiled = false;
     const auto new_meta = cv::descr_of(ins); // 0
     if (gm.metadata().contains<OriginalInputMeta>()) // (1)
     {
@@ -738,6 +826,8 @@ void cv::gimpl::GStreamingExecutor::setSource(GRunArgs &&ins)
             }
             update_int_metas(); // (7)
             m_reshapable = util::make_optional(is_reshapable);
+
+            islandsRecompiled = true;
         }
         else // (8)
         {
@@ -847,6 +937,15 @@ void cv::gimpl::GStreamingExecutor::setSource(GRunArgs &&ins)
             out_queues.push_back(reader_queues(*m_island_graph, out_eh));
         }
 
+        // If Island Executable is recompiled, all its stuff including internal kernel states
+        // are recreated and re-initialized automatically.
+        // But if not, we should notify Island Executable about new started stream to let it update
+        // its internal variables.
+        if (!islandsRecompiled)
+        {
+            op.isl_exec->handleNewStream();
+        }
+
         m_threads.emplace_back(islandActorThread,
                                op.in_objects,
                                op.out_objects,
index 66d4f67..d10f9ed 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2019 Intel Corporation
+// Copyright (C) 2019-2020 Intel Corporation
 
 #ifndef OPENCV_GAPI_GSTREAMING_EXECUTOR_HPP
 #define OPENCV_GAPI_GSTREAMING_EXECUTOR_HPP
@@ -126,7 +126,8 @@ protected:
     void wait_shutdown();
 
 public:
-    explicit GStreamingExecutor(std::unique_ptr<ade::Graph> &&g_model);
+    explicit GStreamingExecutor(std::unique_ptr<ade::Graph> &&g_model,
+                                const cv::GCompileArgs &comp_args);
     ~GStreamingExecutor();
     void setSource(GRunArgs &&args);
     void start();
index ff4c759..cb169bf 100644 (file)
 #  include "opencv2/core/utils/logger.hpp"
 #  define GAPI_LOG_INFO(tag, ...)    CV_LOG_INFO(tag, __VA_ARGS__)
 #  define GAPI_LOG_WARNING(tag, ...) CV_LOG_WARNING(tag, __VA_ARGS__)
+#  define GAPI_LOG_DEBUG(tag, ...)    CV_LOG_DEBUG(tag, __VA_ARGS__)
 #else
 #  define GAPI_LOG_INFO(tag, ...)
 #  define GAPI_LOG_WARNING(tag, ...)
+#  define GAPI_LOG_DEBUG(tag, ...)
 #endif //  !defined(GAPI_STANDALONE)
 
 
index f1364e9..523ecb0 100644 (file)
@@ -227,6 +227,73 @@ namespace
         }
     };
 
+    G_TYPED_KERNEL(GToInterleaved, <GMat(GMatP)>, "org.opencv.test.to_interleaved")
+    {
+        static GMatDesc outMeta(GMatDesc in)
+        {
+            GAPI_Assert(in.planar == true);
+            GAPI_Assert(in.chan == 3);
+            return in.asInterleaved();
+        }
+    };
+
+    G_TYPED_KERNEL(GToPlanar, <GMatP(GMat)>, "org.opencv.test.to_planar")
+    {
+        static GMatDesc outMeta(GMatDesc in)
+        {
+            GAPI_Assert(in.planar == false);
+            GAPI_Assert(in.chan == 3);
+            return in.asPlanar();
+        }
+    };
+
+    GAPI_OCV_KERNEL(GToInterleavedImpl, GToInterleaved)
+    {
+        static void run(const cv::Mat& in, cv::Mat& out)
+        {
+            constexpr int inPlanesCount = 3;
+            int inPlaneHeight = in.rows / inPlanesCount;
+
+            std::vector<cv::Mat> inPlanes(inPlanesCount);
+            for (int i = 0; i < inPlanesCount; ++i)
+            {
+                int startRow = i * inPlaneHeight;
+                int endRow = startRow + inPlaneHeight;
+                inPlanes[i] = in.rowRange(startRow, endRow);
+            }
+
+            cv::merge(inPlanes, out);
+        }
+    };
+
+    GAPI_OCV_KERNEL(GToPlanarImpl, GToPlanar)
+    {
+        static void run(const cv::Mat& in, cv::Mat& out)
+        {
+            std::vector<cv::Mat> inPlanes;
+            cv::split(in, inPlanes);
+            cv::vconcat(inPlanes, out);
+        }
+    };
+
+    G_TYPED_KERNEL(GCompoundToInterleavedToPlanar, <GMatP(GMatP)>,
+                   "org.opencv.test.compound_to_interleaved_to_planar")
+    {
+        static GMatDesc outMeta(GMatDesc in)
+        {
+            GAPI_Assert(in.planar == true);
+            GAPI_Assert(in.chan == 3);
+            return in;
+        }
+    };
+
+    GAPI_COMPOUND_KERNEL(GCompoundToInterleavedToPlanarImpl, GCompoundToInterleavedToPlanar)
+    {
+        static GMatP expand(cv::GMatP in)
+        {
+            return GToPlanar::on(GToInterleaved::on(in));
+        }
+    };
 } // namespace
 
 // FIXME avoid cv::combine that use custom and default kernels together
@@ -497,4 +564,29 @@ TEST(GCompoundKernel, RightGArrayHandle)
     EXPECT_EQ(0, cvtest::norm(out_mat, ref_mat, NORM_INF));
 
 }
+
+TEST(GCompoundKernel, ToInterleavedToPlanar)
+{
+    cv::GMatP in;
+    cv::GMatP out = GCompoundToInterleavedToPlanar::on(in);
+    const auto pkg = cv::gapi::kernels<GCompoundToInterleavedToPlanarImpl,
+                                       GToInterleavedImpl,
+                                       GToPlanarImpl>();
+
+    cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+
+    constexpr int numPlanes = 3;
+    cv::Mat in_mat(cv::Size(15, 15), CV_8UC1),
+            out_mat,
+            ref_mat;
+
+    cv::randu(in_mat, 0, 255);
+    ref_mat = in_mat;
+
+    comp.compile(cv::descr_of(in_mat).asPlanar(numPlanes), cv::compile_args(pkg))
+         (cv::gin(in_mat), cv::gout(out_mat));
+
+    EXPECT_EQ(0, cvtest::norm(out_mat, ref_mat, NORM_INF));
+
+}
 } // opencv_test
index 1d8bba9..308f886 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018-2019 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_CORE_TESTS_HPP
@@ -11,6 +11,7 @@
 #include <iostream>
 
 #include "gapi_tests_common.hpp"
+#include "gapi_parsers_tests_common.hpp"
 
 namespace opencv_test
 {
@@ -87,8 +88,8 @@ GAPI_TEST_FIXTURE(MeanTest, initMatrixRandU, <>, 0)
 GAPI_TEST_FIXTURE(MaskTest, initMatrixRandU, <>, 0)
 GAPI_TEST_FIXTURE(Polar2CartTest, initMatsRandU, <>, 0)
 GAPI_TEST_FIXTURE(Cart2PolarTest, initMatsRandU, <>, 0)
-GAPI_TEST_FIXTURE(CmpTest, initMatsRandU, FIXTURE_API(CmpTypes,bool), 2, opType, testWithScalar)
-GAPI_TEST_FIXTURE(BitwiseTest, initMatsRandU, FIXTURE_API(bitwiseOp), 1, opType)
+GAPI_TEST_FIXTURE(CmpTest, initMatsRandU, FIXTURE_API(CmpTypes,bool,CompareMats), 3, opType, testWithScalar, cmpF)
+GAPI_TEST_FIXTURE(BitwiseTest, initMatsRandU, FIXTURE_API(bitwiseOp,bool), 2, opType, testWithScalar)
 GAPI_TEST_FIXTURE(NotTest, initMatrixRandU, <>, 0)
 GAPI_TEST_FIXTURE(SelectTest, initMatsRandU, <>, 0)
 GAPI_TEST_FIXTURE(MinTest, initMatsRandU, <>, 0)
@@ -128,7 +129,7 @@ GAPI_TEST_FIXTURE(PhaseTest, initMatsRandU, FIXTURE_API(bool), 1, angle_in_degre
 GAPI_TEST_FIXTURE(SqrtTest, initMatrixRandU, <>, 0)
 GAPI_TEST_FIXTURE(NormalizeTest, initNothing, FIXTURE_API(CompareMats,double,double,int,MatType2), 5,
     cmpF, a, b, norm_type, ddepth)
-struct BackendOutputAllocationTest : TestWithParamBase<>
+struct BackendOutputAllocationTest : TestWithParams<>
 {
     BackendOutputAllocationTest()
     {
@@ -149,6 +150,15 @@ GAPI_TEST_FIXTURE(WarpPerspectiveTest, initMatrixRandU,
 GAPI_TEST_FIXTURE(WarpAffineTest, initMatrixRandU,
         FIXTURE_API(CompareMats, double , double, int, int, cv::Scalar),
         6, cmpF, angle, scale, flags, border_mode, border_value)
+
+GAPI_TEST_EXT_BASE_FIXTURE(ParseSSDBLTest, ParserSSDTest, initNothing,
+    FIXTURE_API(float, int), 2, confidence_threshold, filter_label)
+GAPI_TEST_EXT_BASE_FIXTURE(ParseSSDTest, ParserSSDTest, initNothing,
+    FIXTURE_API(float, bool, bool), 3, confidence_threshold, alignment_to_square, filter_out_of_bounds)
+GAPI_TEST_EXT_BASE_FIXTURE(ParseYoloTest, ParserYoloTest, initNothing,
+    FIXTURE_API(float, float, int), 3, confidence_threshold, nms_threshold, num_classes)
+GAPI_TEST_FIXTURE(SizeTest, initMatrixRandU, <>, 0)
+GAPI_TEST_FIXTURE(SizeRTest, initNothing, <>, 0)
 } // opencv_test
 
 #endif //OPENCV_GAPI_CORE_TESTS_HPP
index b5ed58c..331ef70 100644 (file)
@@ -9,6 +9,7 @@
 #define OPENCV_GAPI_CORE_TESTS_INL_HPP
 
 #include <opencv2/gapi/core.hpp>
+#include <opencv2/gapi/infer/parsers.hpp>
 #include "gapi_core_tests.hpp"
 
 namespace opencv_test
@@ -47,14 +48,14 @@ TEST_P(MathOpTest, MatricesAccuracyTest)
         {
             if( doReverseOp )
             {
-                in_mat1.setTo(1, in_mat1 == 0);  // avoid zeros in divide input data
+                in_mat1.setTo(1, in_mat1 == 0);  // avoiding zeros in divide input data
                 out = cv::gapi::divRC(sc1, in1, scale, dtype);
                 cv::divide(sc, in_mat1, out_mat_ocv, scale, dtype);
                 break;
             }
             else
             {
-                sc += Scalar(1, 1, 1, 1);  // avoid zeros in divide input data
+                sc += Scalar(sc[0] == 0, sc[1] == 0, sc[2] == 0, sc[3] == 0);  // avoiding zeros in divide input data
                 out = cv::gapi::divC(in1, sc1, scale, dtype);
                 cv::divide(in_mat1, sc, out_mat_ocv, scale, dtype);
                 break;
@@ -93,7 +94,7 @@ TEST_P(MathOpTest, MatricesAccuracyTest)
         }
         case (DIV):
         {
-            in_mat2.setTo(1, in_mat2 == 0);  // avoid zeros in divide input data
+            in_mat2.setTo(1, in_mat2 == 0);  // avoiding zeros in divide input data
             out = cv::gapi::div(in1, in2, scale, dtype);
             cv::divide(in_mat1, in_mat2, out_mat_ocv, scale, dtype);
             break;
@@ -405,7 +406,7 @@ TEST_P(CmpTest, AccuracyTest)
     // Comparison //////////////////////////////////////////////////////////////
     {
         ASSERT_EQ(out_mat_gapi.size(), sz);
-        EXPECT_EQ(0, cvtest::norm(out_mat_gapi, out_mat_ocv, NORM_INF));
+        EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
     }
 }
 
@@ -413,33 +414,52 @@ TEST_P(BitwiseTest, AccuracyTest)
 {
     // G-API code & corresponding OpenCV code ////////////////////////////////
     cv::GMat in1, in2, out;
-    switch(opType)
+    if( testWithScalar )
     {
-        case AND:
-        {
-            out = cv::gapi::bitwise_and(in1, in2);
-            cv::bitwise_and(in_mat1, in_mat2, out_mat_ocv);
-            break;
-        }
-        case OR:
-        {
-            out = cv::gapi::bitwise_or(in1, in2);
-            cv::bitwise_or(in_mat1, in_mat2, out_mat_ocv);
-            break;
-        }
-        case XOR:
+        cv::GScalar sc1;
+        switch(opType)
         {
-            out = cv::gapi::bitwise_xor(in1, in2);
-            cv::bitwise_xor(in_mat1, in_mat2, out_mat_ocv);
-            break;
+            case AND:
+                out = cv::gapi::bitwise_and(in1, sc1);
+                cv::bitwise_and(in_mat1, sc, out_mat_ocv);
+                break;
+            case OR:
+                out = cv::gapi::bitwise_or(in1, sc1);
+                cv::bitwise_or(in_mat1, sc, out_mat_ocv);
+                break;
+            case XOR:
+                out = cv::gapi::bitwise_xor(in1, sc1);
+                cv::bitwise_xor(in_mat1, sc, out_mat_ocv);
+                break;
+            default:
+                FAIL() << "no such bitwise operation type!";
         }
-        default:
+        cv::GComputation c(GIn(in1, sc1), GOut(out));
+        c.apply(gin(in_mat1, sc), gout(out_mat_gapi), getCompileArgs());
+    }
+    else
+    {
+        switch(opType)
         {
-            FAIL() << "no such bitwise operation type!";
+            case AND:
+                out = cv::gapi::bitwise_and(in1, in2);
+                cv::bitwise_and(in_mat1, in_mat2, out_mat_ocv);
+                break;
+            case OR:
+                out = cv::gapi::bitwise_or(in1, in2);
+                cv::bitwise_or(in_mat1, in_mat2, out_mat_ocv);
+                break;
+            case XOR:
+                out = cv::gapi::bitwise_xor(in1, in2);
+                cv::bitwise_xor(in_mat1, in_mat2, out_mat_ocv);
+                break;
+            default:
+                FAIL() << "no such bitwise operation type!";
         }
+        cv::GComputation c(GIn(in1, in2), GOut(out));
+        c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), getCompileArgs());
     }
-    cv::GComputation c(GIn(in1, in2), GOut(out));
-    c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), getCompileArgs());
+
 
     // Comparison //////////////////////////////////////////////////////////////
     {
@@ -1578,6 +1598,95 @@ TEST_P(ReInitOutTest, TestWithAdd)
     run_and_compare();
 }
 
+TEST_P(ParseSSDBLTest, ParseTest)
+{
+    cv::Mat in_mat = generateSSDoutput(sz);
+    std::vector<cv::Rect> boxes_gapi, boxes_ref;
+    std::vector<int> labels_gapi, labels_ref;
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    cv::GOpaque<cv::Size> op_sz;
+    auto out = cv::gapi::parseSSD(in, op_sz, confidence_threshold, filter_label);
+    cv::GComputation c(cv::GIn(in, op_sz), cv::GOut(std::get<0>(out), std::get<1>(out)));
+    c.apply(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi), getCompileArgs());
+
+    // Reference code //////////////////////////////////////////////////////////
+    parseSSDBLref(in_mat, sz, confidence_threshold, filter_label, boxes_ref, labels_ref);
+
+    // Comparison //////////////////////////////////////////////////////////////
+    EXPECT_TRUE(boxes_gapi == boxes_ref);
+    EXPECT_TRUE(labels_gapi == labels_ref);
+}
+
+TEST_P(ParseSSDTest, ParseTest)
+{
+    cv::Mat in_mat = generateSSDoutput(sz);
+    std::vector<cv::Rect> boxes_gapi, boxes_ref;
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    cv::GOpaque<cv::Size> op_sz;
+    auto out = cv::gapi::parseSSD(in, op_sz, confidence_threshold,
+                                  alignment_to_square, filter_out_of_bounds);
+    cv::GComputation c(cv::GIn(in, op_sz), cv::GOut(out));
+    c.apply(cv::gin(in_mat, sz), cv::gout(boxes_gapi), getCompileArgs());
+
+    // Reference code //////////////////////////////////////////////////////////
+    parseSSDref(in_mat, sz, confidence_threshold, alignment_to_square,
+                filter_out_of_bounds, boxes_ref);
+
+    // Comparison //////////////////////////////////////////////////////////////
+    EXPECT_TRUE(boxes_gapi == boxes_ref);
+}
+
+TEST_P(ParseYoloTest, ParseTest)
+{
+    cv::Mat in_mat = generateYoloOutput(num_classes);
+    auto anchors = cv::gapi::nn::parsers::GParseYolo::defaultAnchors();
+    std::vector<cv::Rect> boxes_gapi, boxes_ref;
+    std::vector<int> labels_gapi, labels_ref;
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    cv::GOpaque<cv::Size> op_sz;
+    auto out = cv::gapi::parseYolo(in, op_sz, confidence_threshold, nms_threshold, anchors);
+    cv::GComputation c(cv::GIn(in, op_sz), cv::GOut(std::get<0>(out), std::get<1>(out)));
+    c.apply(cv::gin(in_mat, sz), cv::gout(boxes_gapi, labels_gapi), getCompileArgs());
+
+    // Reference code //////////////////////////////////////////////////////////
+    parseYoloRef(in_mat, sz, confidence_threshold, nms_threshold, num_classes, anchors, boxes_ref, labels_ref);
+
+    // Comparison //////////////////////////////////////////////////////////////
+    EXPECT_TRUE(boxes_gapi == boxes_ref);
+    EXPECT_TRUE(labels_gapi == labels_ref);
+}
+
+TEST_P(SizeTest, ParseTest)
+{
+    cv::GMat in;
+    cv::Size out_sz;
+
+    auto out = cv::gapi::size(in);
+    cv::GComputation c(cv::GIn(in), cv::GOut(out));
+    c.apply(cv::gin(in_mat1), cv::gout(out_sz), getCompileArgs());
+
+    EXPECT_EQ(out_sz, sz);
+}
+
+TEST_P(SizeRTest, ParseTest)
+{
+    cv::Rect rect(cv::Point(0,0), sz);
+    cv::Size out_sz;
+
+    cv::GOpaque<cv::Rect> op_rect;
+    auto out = cv::gapi::size(op_rect);
+    cv::GComputation c(cv::GIn(op_rect), cv::GOut(out));
+    c.apply(cv::gin(rect), cv::gout(out_sz), getCompileArgs());
+
+    EXPECT_EQ(out_sz, sz);
+}
+
 } // opencv_test
 
 #endif //OPENCV_GAPI_CORE_TESTS_INL_HPP
index cba6b2a..cd074ef 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018-2019 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_IMGPROC_TESTS_HPP
@@ -14,6 +14,7 @@
 
 namespace opencv_test
 {
+
 // Create new value-parameterized test fixture:
 // Filter2DTest - fixture name
 // initMatrixRandN - function that is used to initialize input/output data
@@ -49,9 +50,20 @@ GAPI_TEST_FIXTURE(SobelTest, initMatrixRandN, FIXTURE_API(CompareMats,int,int,in
     cmpF, kernSize, dx, dy)
 GAPI_TEST_FIXTURE(SobelXYTest, initMatrixRandN, FIXTURE_API(CompareMats,int,int,int,int), 5,
     cmpF, kernSize, order, border_type, border_val)
+GAPI_TEST_FIXTURE(LaplacianTest, initMatrixRandN,
+                  FIXTURE_API(CompareMats,int,double,int), 4,
+                  cmpF, kernSize, scale, borderType)
+GAPI_TEST_FIXTURE(BilateralFilterTest, initMatrixRandN,
+                  FIXTURE_API(CompareMats,int,double,double,int), 5,
+                  cmpF, d, sigmaColor, sigmaSpace, borderType)
 GAPI_TEST_FIXTURE(EqHistTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
 GAPI_TEST_FIXTURE(CannyTest, initMatrixRandN, FIXTURE_API(CompareMats,double,double,int,bool), 5,
     cmpF, thrLow, thrUp, apSize, l2gr)
+GAPI_TEST_FIXTURE_SPEC_PARAMS(GoodFeaturesTest,
+                              FIXTURE_API(CompareVectors<cv::Point2f>,std::string,int,int,double,
+                                          double,int,bool),
+                              8, cmpF, fileName, type, maxCorners, qualityLevel, minDistance,
+                              blockSize, useHarrisDetector)
 GAPI_TEST_FIXTURE(RGB2GrayTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
 GAPI_TEST_FIXTURE(BGR2GrayTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
 GAPI_TEST_FIXTURE(RGB2YUVTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
index 3c62ff3..4aadc17 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018-2019 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #ifndef OPENCV_GAPI_IMGPROC_TESTS_INL_HPP
@@ -342,6 +342,45 @@ TEST_P(SobelXYTest, AccuracyTest)
     }
 }
 
+TEST_P(LaplacianTest, AccuracyTest)
+{
+    double delta = 10;
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    auto out = cv::gapi::Laplacian(in, dtype, kernSize, scale, delta, borderType);
+
+    cv::GComputation c(in, out);
+    c.apply(in_mat1, out_mat_gapi, getCompileArgs());
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::Laplacian(in_mat1, out_mat_ocv, dtype, kernSize, scale, delta, borderType);
+    }
+    // Comparison //////////////////////////////////////////////////////////////
+    {
+        EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+        EXPECT_EQ(out_mat_gapi.size(), sz);
+    }
+}
+
+TEST_P(BilateralFilterTest, AccuracyTest)
+{
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    auto out = cv::gapi::bilateralFilter(in, d, sigmaColor, sigmaSpace, borderType);
+
+    cv::GComputation c(in, out);
+    c.apply(in_mat1, out_mat_gapi, getCompileArgs());
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::bilateralFilter(in_mat1, out_mat_ocv, d, sigmaColor, sigmaSpace, borderType);
+    }
+    // Comparison //////////////////////////////////////////////////////////////
+    {
+        EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+        EXPECT_EQ(out_mat_gapi.size(), sz);
+    }
+}
+
 TEST_P(EqHistTest, AccuracyTest)
 {
     // G-API code //////////////////////////////////////////////////////////////
@@ -380,6 +419,34 @@ TEST_P(CannyTest, AccuracyTest)
     }
 }
 
+TEST_P(GoodFeaturesTest, AccuracyTest)
+{
+    double k = 0.04;
+
+    initMatFromImage(type, fileName);
+
+    std::vector<cv::Point2f> outVecOCV, outVecGAPI;
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    auto out = cv::gapi::goodFeaturesToTrack(in, maxCorners, qualityLevel, minDistance, cv::Mat(),
+                                             blockSize, useHarrisDetector, k);
+
+    cv::GComputation c(cv::GIn(in), cv::GOut(out));
+    c.apply(cv::gin(in_mat1), cv::gout(outVecGAPI), getCompileArgs());
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::goodFeaturesToTrack(in_mat1, outVecOCV, maxCorners, qualityLevel, minDistance,
+                                cv::noArray(), blockSize, useHarrisDetector, k);
+    }
+
+    // Comparison //////////////////////////////////////////////////////////////
+    {
+        EXPECT_TRUE(cmpF(outVecGAPI, outVecOCV));
+    }
+}
+
 TEST_P(RGB2GrayTest, AccuracyTest)
 {
     // G-API code //////////////////////////////////////////////////////////////
@@ -756,7 +823,6 @@ TEST_P(RGB2YUV422Test, AccuracyTest)
         EXPECT_EQ(out_mat_gapi.size(), sz);
     }
 }
-
 } // opencv_test
 
 #endif //OPENCV_GAPI_IMGPROC_TESTS_INL_HPP
index 70bf477..9a195e0 100644 (file)
 
 namespace opencv_test
 {
+enum operation
+{
+    ADD,  SUB,  MUL,  DIV,
+    ADDR, SUBR, MULR, DIVR,
+    GT,  LT,  GE,  LE,  EQ,  NE,
+    GTR, LTR, GER, LER, EQR, NER,
+    AND,  OR,  XOR,
+    ANDR, ORR, XORR
+};
+
+// Note: namespace must match the namespace of the type of the printed object
+inline std::ostream& operator<<(std::ostream& os, operation op)
+{
+#define CASE(v) case operation::v: os << #v; break
+    switch (op)
+    {
+        CASE(ADD);  CASE(SUB);  CASE(MUL);  CASE(DIV);
+        CASE(ADDR); CASE(SUBR); CASE(MULR); CASE(DIVR);
+        CASE(GT);  CASE(LT);  CASE(GE);  CASE(LE);  CASE(EQ);  CASE(NE);
+        CASE(GTR); CASE(LTR); CASE(GER); CASE(LER); CASE(EQR); CASE(NER);
+        CASE(AND);  CASE(OR);  CASE(XOR);
+        CASE(ANDR); CASE(ORR); CASE(XORR);
+        default: GAPI_Assert(false && "unknown operation value");
+    }
+#undef CASE
+    return os;
+}
+
+namespace
+{
+// declare test cases for matrix and scalar operators
+auto opADD_gapi  = [](cv::GMat in,cv::GScalar c){return in + c;};
+auto opADD_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::add(in, c, out);};
+
+auto opADDR_gapi = [](cv::GMat in,cv::GScalar c){return c + in;};
+auto opADDR_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::add(c, in, out);};
+
+auto opSUB_gapi  = [](cv::GMat in,cv::GScalar c){return in - c;};
+auto opSUB_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::subtract(in, c, out);};
+
+auto opSUBR_gapi = [](cv::GMat in,cv::GScalar c){return c - in;};
+auto opSUBR_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::subtract(c, in, out);};
+
+auto opMUL_gapi  = [](cv::GMat in,cv::GScalar c){return in * c;};
+auto opMUL_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::multiply(in, c, out);};
+
+auto opMULR_gapi = [](cv::GMat in,cv::GScalar c){return c * in;};
+auto opMULR_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::multiply(c, in, out);};
+
+auto opDIV_gapi  = [](cv::GMat in,cv::GScalar c){return in / c;};
+auto opDIV_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::divide(in, c, out);};
+
+auto opDIVR_gapi = [](cv::GMat in,cv::GScalar c){return c / in;};
+auto opDIVR_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::divide(c, in, out);};
+
+
+auto opGT_gapi  = [](cv::GMat in,cv::GScalar c){return in > c;};
+auto opGT_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_GT);};
+
+auto opGTR_gapi = [](cv::GMat in,cv::GScalar c){return c > in;};
+auto opGTR_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_GT);};
+
+auto opLT_gapi  = [](cv::GMat in,cv::GScalar c){return in < c;};
+auto opLT_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_LT);};
+
+auto opLTR_gapi = [](cv::GMat in,cv::GScalar c){return c < in;};
+auto opLTR_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_LT);};
+
+auto opGE_gapi  = [](cv::GMat in,cv::GScalar c){return in >= c;};
+auto opGE_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_GE);};
+
+auto opGER_gapi = [](cv::GMat in,cv::GScalar c){return c >= in;};
+auto opGER_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_GE);};
+
+auto opLE_gapi  = [](cv::GMat in,cv::GScalar c){return in <= c;};
+auto opLE_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_LE);};
+
+auto opLER_gapi = [](cv::GMat in,cv::GScalar c){return c <= in;};
+auto opLER_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_LE);};
+
+auto opEQ_gapi  = [](cv::GMat in,cv::GScalar c){return in == c;};
+auto opEQ_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_EQ);};
+
+auto opEQR_gapi = [](cv::GMat in,cv::GScalar c){return c == in;};
+auto opEQR_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_EQ);};
+
+auto opNE_gapi  = [](cv::GMat in,cv::GScalar c){return in != c;};
+auto opNE_ocv   = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_NE);};
+
+auto opNER_gapi = [](cv::GMat in,cv::GScalar c){return c != in;};
+auto opNER_ocv  = [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_NE);};
+
+
+auto opAND_gapi  = [](cv::GMat in,cv::GScalar c){return in & c;};
+auto opAND_ocv   = [](const cv::Mat& in, const cv::Scalar& c, cv::Mat& out){cv::bitwise_and(in, c, out);};
+
+auto opOR_gapi   = [](cv::GMat in,cv::GScalar c){return in | c;};
+auto opOR_ocv    = [](const cv::Mat& in, const cv::Scalar& c, cv::Mat& out){cv::bitwise_or(in, c, out);};
+
+auto opXOR_gapi  = [](cv::GMat in,cv::GScalar c){return in ^ c;};
+auto opXOR_ocv   = [](const cv::Mat& in, const cv::Scalar& c, cv::Mat& out){cv::bitwise_xor(in, c, out);};
+
+auto opANDR_gapi = [](cv::GMat in,cv::GScalar c){return c & in;};
+auto opANDR_ocv  = [](const cv::Mat& in, const cv::Scalar& c, cv::Mat& out){cv::bitwise_and(c, in, out);};
+
+auto opORR_gapi  = [](cv::GMat in,cv::GScalar c){return c | in;};
+auto opORR_ocv   = [](const cv::Mat& in, const cv::Scalar& c, cv::Mat& out){cv::bitwise_or(c, in, out);};
+
+auto opXORR_gapi = [](cv::GMat in,cv::GScalar c){return c ^ in;};
+auto opXORR_ocv  = [](const cv::Mat& in, const cv::Scalar& c, cv::Mat& out){cv::bitwise_xor(c, in, out);};
+
+// declare test cases for matrix and matrix operators
+auto opADDM_gapi = [](cv::GMat in1,cv::GMat in2){return in1 + in2;};
+auto opADDM_ocv  = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::add(in1, in2, out);};
+
+auto opSUBM_gapi = [](cv::GMat in1,cv::GMat in2){return in1 - in2;};
+auto opSUBM_ocv  = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::subtract(in1, in2, out);};
+
+auto opDIVM_gapi = [](cv::GMat in1,cv::GMat in2){return in1 / in2;};
+auto opDIVM_ocv  = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::divide(in1, in2, out);};
+
+
+auto opGTM_gapi  = [](cv::GMat in1,cv::GMat in2){return in1 > in2;};
+auto opGTM_ocv   = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_GT);};
+
+auto opGEM_gapi  = [](cv::GMat in1,cv::GMat in2){return in1 >= in2;};
+auto opGEM_ocv   = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_GE);};
+
+auto opLTM_gapi  = [](cv::GMat in1,cv::GMat in2){return in1 < in2;};
+auto opLTM_ocv   = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_LT);};
+
+auto opLEM_gapi  = [](cv::GMat in1,cv::GMat in2){return in1 <= in2;};
+auto opLEM_ocv   = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_LE);};
+
+auto opEQM_gapi  = [](cv::GMat in1,cv::GMat in2){return in1 == in2;};
+auto opEQM_ocv   = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_EQ);};
+
+auto opNEM_gapi  = [](cv::GMat in1,cv::GMat in2){return in1 != in2;};
+auto opNEM_ocv   = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_NE);};
+
+
+auto opANDM_gapi = [](cv::GMat in1,cv::GMat in2){return in1 & in2;};
+auto opANDM_ocv  = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::bitwise_and(in1, in2, out);};
+
+auto opORM_gapi  = [](cv::GMat in1,cv::GMat in2){return in1 | in2;};
+auto opORM_ocv   = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::bitwise_or(in1, in2, out);};
+
+auto opXORM_gapi = [](cv::GMat in1,cv::GMat in2){return in1 ^ in2;};
+auto opXORM_ocv  = [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::bitwise_xor(in1, in2, out);};
+} // anonymous namespace
 
 struct g_api_ocv_pair_mat_scalar {
     using g_api_function_t = std::function<cv::GMat(cv::GMat,cv::GScalar)>;
     using ocv_function_t   = std::function<void(cv::Mat const&, cv::Scalar, cv::Mat&)>;
 
-    std::string      name;
     g_api_function_t g_api_function;
     ocv_function_t   ocv_function;
 
-
-    g_api_ocv_pair_mat_scalar(std::string const& n, g_api_function_t const& g, ocv_function_t const& o)
-    : name(n), g_api_function(g), ocv_function(o) {}
-
     g_api_ocv_pair_mat_scalar() = default;
 
-    friend std::ostream& operator<<(std::ostream& o, const g_api_ocv_pair_mat_scalar& p)
+#define CASE(v) case operation::v: \
+    g_api_function = op##v##_gapi; \
+    ocv_function   = op##v##_ocv;  \
+    break
+
+    g_api_ocv_pair_mat_scalar(operation op)
     {
-        return o<<p.name;
+        switch (op)
+        {
+            CASE(ADD);  CASE(SUB);  CASE(MUL);  CASE(DIV);
+            CASE(ADDR); CASE(SUBR); CASE(MULR); CASE(DIVR);
+            CASE(GT);  CASE(LT);  CASE(GE);  CASE(LE);  CASE(EQ);  CASE(NE);
+            CASE(GTR); CASE(LTR); CASE(GER); CASE(LER); CASE(EQR); CASE(NER);
+            CASE(AND);  CASE(OR);  CASE(XOR);
+            CASE(ANDR); CASE(ORR); CASE(XORR);
+            default: GAPI_Assert(false && "unknown operation value");
+        }
     }
+#undef CASE
 };
 
 struct g_api_ocv_pair_mat_mat {
     using g_api_function_t = std::function<cv::GMat(cv::GMat,cv::GMat)>;
     using ocv_function_t   = std::function<void(cv::Mat const&, cv::Mat const&, cv::Mat&)>;
 
-    std::string      name;
     g_api_function_t g_api_function;
     ocv_function_t   ocv_function;
 
-
-    g_api_ocv_pair_mat_mat(std::string const& n, g_api_function_t const& g, ocv_function_t const& o)
-    : name(n), g_api_function(g), ocv_function(o) {}
-
     g_api_ocv_pair_mat_mat() = default;
 
-    friend std::ostream& operator<<(std::ostream& o, const g_api_ocv_pair_mat_mat& p)
+#define CASE(v) case operation::v:  \
+    g_api_function = op##v##M_gapi; \
+    ocv_function   = op##v##M_ocv;  \
+    break
+
+    g_api_ocv_pair_mat_mat(operation op)
     {
-        return o<<p.name;
+        switch (op)
+        {
+            CASE(ADD);  CASE(SUB);  CASE(DIV);
+            CASE(GT); CASE(LT); CASE(GE); CASE(LE); CASE(EQ); CASE(NE);
+            CASE(AND); CASE(OR); CASE(XOR);
+            default: GAPI_Assert(false && "unknown operation value");
+        }
     }
+#undef CASE
 };
 
-////////////////////////////////////////////////////////////////////////////////
-//
-// FIXME: Please refactor this test to a template test (T,U) with enum (OP)
-//
-////////////////////////////////////////////////////////////////////////////////
-namespace
-{
-
-//declare test cases for matrix and scalar operators
-g_api_ocv_pair_mat_scalar opPlus =  {std::string{"operator+"},
-                                    [](cv::GMat in,cv::GScalar c){return in+c;},
-                                    [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::add(in, c, out);}};
-g_api_ocv_pair_mat_scalar opPlusR = {std::string{"rev_operator+"},
-                                    [](cv::GMat in,cv::GScalar c){return c+in;},
-                                    [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::add(c, in, out);}};
-g_api_ocv_pair_mat_scalar opMinus = {std::string{"operator-"},
-                                    [](cv::GMat in,cv::GScalar c){return in-c;},
-                                    [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::subtract(in, c, out);}};
-g_api_ocv_pair_mat_scalar opMinusR = {std::string{"rev_operator-"},
-                                    [](cv::GMat in,cv::GScalar c){return c-in;},
-                                    [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::subtract(c, in, out);}};
-g_api_ocv_pair_mat_scalar opMul =   {std::string{"operator*"},
-                                    [](cv::GMat in,cv::GScalar c){return in*c;},
-                                    [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::multiply(in, c, out);}};
-g_api_ocv_pair_mat_scalar opMulR =  {std::string{"rev_operator*"},
-                                    [](cv::GMat in,cv::GScalar c){return c*in;},
-                                    [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::multiply(c, in, out);}};
-g_api_ocv_pair_mat_scalar opDiv =   {std::string{"operator/"},
-                                    [](cv::GMat in,cv::GScalar c){return in/c;},
-                                    [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::divide(in, c, out);}};
-g_api_ocv_pair_mat_scalar opDivR =  {std::string{"rev_operator/"},
-                                    [](cv::GMat in,cv::GScalar c){return c/in;},
-                                    [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::divide(c, in, out);}};
-
-g_api_ocv_pair_mat_scalar opGT = {std::string{"operator>"},
-                                            [](cv::GMat in,cv::GScalar c){return in>c;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_GT);}};
-g_api_ocv_pair_mat_scalar opLT = {std::string{"operator<"},
-                                            [](cv::GMat in,cv::GScalar c){return in<c;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_LT);}};
-g_api_ocv_pair_mat_scalar opGE = {std::string{"operator>="},
-                                            [](cv::GMat in,cv::GScalar c){return in>=c;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_GE);}};
-g_api_ocv_pair_mat_scalar opLE = {std::string{"operator<="},
-                                            [](cv::GMat in,cv::GScalar c){return in<=c;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_LE);}};
-g_api_ocv_pair_mat_scalar opEQ = {std::string{"operator=="},
-                                            [](cv::GMat in,cv::GScalar c){return in==c;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_EQ);}};
-g_api_ocv_pair_mat_scalar opNE = {std::string{"operator!="},
-                                            [](cv::GMat in,cv::GScalar c){return in!=c;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_NE);}};
-g_api_ocv_pair_mat_scalar opGTR = {std::string{"rev_operator>"},
-                                            [](cv::GMat in,cv::GScalar c){return c>in;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_GT);}};
-g_api_ocv_pair_mat_scalar opLTR = {std::string{"rev_operator<"},
-                                            [](cv::GMat in,cv::GScalar c){return c<in;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_LT);}};
-g_api_ocv_pair_mat_scalar opGER = {std::string{"rev_operator>="},
-                                            [](cv::GMat in,cv::GScalar c){return c>=in;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_GE);}};
-g_api_ocv_pair_mat_scalar opLER = {std::string{"rev_operator<="},
-                                            [](cv::GMat in,cv::GScalar c){return c<=in;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_LE);}};
-g_api_ocv_pair_mat_scalar opEQR = {std::string{"rev_operator=="},
-                                            [](cv::GMat in,cv::GScalar c){return c==in;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_EQ);}};
-g_api_ocv_pair_mat_scalar opNER = {std::string{"rev_operator!="},
-                                            [](cv::GMat in,cv::GScalar c){return c!=in;},
-                                            [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_NE);}};
-
-g_api_ocv_pair_mat_scalar opAND = {std::string{"operator&"},
-                                        [](cv::GMat in1,cv::GScalar in2){return in1&in2;},
-                                        [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_and(in1, in2, out);}};
-g_api_ocv_pair_mat_scalar opOR = {std::string{"operator|"},
-                                        [](cv::GMat in1,cv::GScalar in2){return in1|in2;},
-                                        [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_or(in1, in2, out);}};
-g_api_ocv_pair_mat_scalar opXOR = {std::string{"operator^"},
-                                        [](cv::GMat in1,cv::GScalar in2){return in1^in2;},
-                                        [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_xor(in1, in2, out);}};
-g_api_ocv_pair_mat_scalar opANDR = {std::string{"rev_operator&"},
-                                        [](cv::GMat in1,cv::GScalar in2){return in2&in1;},
-                                        [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_and(in2, in1, out);}};
-g_api_ocv_pair_mat_scalar opORR = {std::string{"rev_operator|"},
-                                        [](cv::GMat in1,cv::GScalar in2){return in2|in1;},
-                                        [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_or(in2, in1, out);}};
-g_api_ocv_pair_mat_scalar opXORR = {std::string{"rev_operator^"},
-                                        [](cv::GMat in1,cv::GScalar in2){return in2^in1;},
-                                        [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_xor(in2, in1, out);}};
-
-// declare test cases for matrix and matrix operators
-g_api_ocv_pair_mat_mat opPlusM =  {std::string{"operator+"},
-                                            [](cv::GMat in1,cv::GMat in2){return in1+in2;},
-                                            [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::add(in1, in2, out);}};
-g_api_ocv_pair_mat_mat opMinusM = {std::string{"operator-"},
-                                            [](cv::GMat in,cv::GMat in2){return in-in2;},
-                                            [](const cv::Mat& in, const cv::Mat& in2, cv::Mat& out){cv::subtract(in, in2, out);}};
-g_api_ocv_pair_mat_mat opDivM = {std::string{"operator/"},
-                                            [](cv::GMat in,cv::GMat in2){return in/in2;},
-                                            [](const cv::Mat& in, const cv::Mat& in2, cv::Mat& out){cv::divide(in, in2, out);}};
-g_api_ocv_pair_mat_mat opGreater =  {std::string{"operator>"},
-                                            [](cv::GMat in1,cv::GMat in2){return in1>in2;},
-                                            [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_GT);}};
-g_api_ocv_pair_mat_mat opGreaterEq = {std::string{"operator>="},
-                                            [](cv::GMat in1,cv::GMat in2){return in1>=in2;},
-                                            [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_GE);}};
-g_api_ocv_pair_mat_mat opLess = {std::string{"operator<"},
-                                            [](cv::GMat in1,cv::GMat in2){return in1<in2;},
-                                            [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_LT);}};
-g_api_ocv_pair_mat_mat opLessEq = {std::string{"operator<="},
-                                            [](cv::GMat in1,cv::GMat in2){return in1<=in2;},
-                                            [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_LE);}};
-g_api_ocv_pair_mat_mat opEq = {std::string{"operator=="},
-                                            [](cv::GMat in1,cv::GMat in2){return in1==in2;},
-                                            [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_EQ);}};
-g_api_ocv_pair_mat_mat opNotEq = {std::string{"operator!="},
-                                            [](cv::GMat in1,cv::GMat in2){return in1!=in2;},
-                                            [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_NE);}};
-
-g_api_ocv_pair_mat_mat opAnd = {std::string{"operator&"},
-                                        [](cv::GMat in1,cv::GMat in2){return in1&in2;},
-                                        [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::bitwise_and(in1, in2, out);}};
-g_api_ocv_pair_mat_mat opOr = {std::string{"operator|"},
-                                        [](cv::GMat in1,cv::GMat in2){return in1|in2;},
-                                        [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::bitwise_or(in1, in2, out);}};
-g_api_ocv_pair_mat_mat opXor = {std::string{"operator^"},
-                                        [](cv::GMat in1,cv::GMat in2){return in1^in2;},
-                                        [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::bitwise_xor(in1, in2, out);}};
-
-} // anonymous namespace
-
 // Create new value-parameterized test fixture:
 // MathOperatorMatScalarTest - fixture name
 // initMatsRandU - function that is used to initialize input/output data
@@ -200,9 +236,9 @@ g_api_ocv_pair_mat_mat opXor = {std::string{"operator^"},
 //      - available in test body
 // Note: all parameter _values_ (e.g. type CV_8UC3) are set via INSTANTIATE_TEST_CASE_P macro
 GAPI_TEST_FIXTURE(MathOperatorMatScalarTest, initMatsRandU,
-    FIXTURE_API(CompareMats, g_api_ocv_pair_mat_scalar), 2, cmpF, op)
+    FIXTURE_API(CompareMats, operation), 2, cmpF, op)
 GAPI_TEST_FIXTURE(MathOperatorMatMatTest, initMatsRandU,
-    FIXTURE_API(CompareMats, g_api_ocv_pair_mat_mat), 2, cmpF, op)
+    FIXTURE_API(CompareMats, operation), 2, cmpF, op)
 GAPI_TEST_FIXTURE(NotOperatorTest, initMatrixRandU, <>, 0)
 } // opencv_test
 
index 8d974d8..ad57929 100644 (file)
@@ -14,8 +14,14 @@ namespace opencv_test
 {
 TEST_P(MathOperatorMatScalarTest, OperatorAccuracyTest )
 {
-    auto fun_gapi = op.g_api_function;
-    auto fun_ocv = op.ocv_function ;
+    g_api_ocv_pair_mat_scalar funcs(op);
+    auto fun_gapi = funcs.g_api_function;
+    auto fun_ocv  = funcs.ocv_function;
+
+    if (op == DIVR)
+        in_mat1.setTo(1, in_mat1 == 0);                               // avoiding zeros in divide input data
+    if (op == DIV)
+        sc += Scalar(sc[0] == 0, sc[1] == 0, sc[2] == 0, sc[3] == 0); // avoiding zeros in divide input data
 
     // G-API code & corresponding OpenCV code ////////////////////////////////
 
@@ -37,8 +43,12 @@ TEST_P(MathOperatorMatScalarTest, OperatorAccuracyTest )
 
 TEST_P(MathOperatorMatMatTest, OperatorAccuracyTest )
 {
-    auto fun_gapi = op.g_api_function;
-    auto fun_ocv = op.ocv_function ;
+    g_api_ocv_pair_mat_mat funcs(op);
+    auto fun_gapi = funcs.g_api_function;
+    auto fun_ocv  = funcs.ocv_function;
+
+    if (op == DIV)
+        in_mat2.setTo(1, in_mat2 == 0); // avoiding zeros in divide input data
 
     // G-API code & corresponding OpenCV code ////////////////////////////////
 
@@ -77,6 +87,81 @@ TEST_P(NotOperatorTest, OperatorAccuracyTest)
         EXPECT_EQ(0, cvtest::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
     }
 }
+
+namespace for_test
+{
+class Foo {};
+
+inline int operator&(Foo, int) { return 1; }
+inline int operator|(Foo, int) { return 1; }
+inline int operator^(Foo, int) { return 1; }
+inline int operator~(Foo)      { return 1; }
+
+inline int operator+(Foo, int) { return 1; }
+inline int operator-(Foo, int) { return 1; }
+inline int operator*(Foo, int) { return 1; }
+inline int operator/(Foo, int) { return 1; }
+
+inline int operator> (Foo, int) { return 1; }
+inline int operator>=(Foo, int) { return 1; }
+inline int operator< (Foo, int) { return 1; }
+inline int operator<=(Foo, int) { return 1; }
+inline int operator==(Foo, int) { return 1; }
+inline int operator!=(Foo, int) { return 1; }
+
+TEST(CVNamespaceOperatorsTest, OperatorCompilationTest)
+{
+    cv::GScalar sc;
+    cv::GMat mat_in1, mat_in2;
+
+    cv::GMat op_not = ~ mat_in1;
+
+    cv::GMat op_mat_mat1  = mat_in1 &  mat_in2;
+    cv::GMat op_mat_mat2  = mat_in1 |  mat_in2;
+    cv::GMat op_mat_mat3  = mat_in1 ^  mat_in2;
+    cv::GMat op_mat_mat4  = mat_in1 +  mat_in2;
+    cv::GMat op_mat_mat5  = mat_in1 -  mat_in2;
+    cv::GMat op_mat_mat6  = mat_in1 /  mat_in2;
+    cv::GMat op_mat_mat7  = mat_in1 >  mat_in2;
+    cv::GMat op_mat_mat8  = mat_in1 >= mat_in2;
+    cv::GMat op_mat_mat9  = mat_in1 <  mat_in2;
+    cv::GMat op_mat_mat10 = mat_in1 <= mat_in2;
+    cv::GMat op_mat_mat11 = mat_in1 == mat_in2;
+    cv::GMat op_mat_mat12 = mat_in1 != mat_in2;
+
+    cv::GMat op_mat_sc1  = mat_in1 &  sc;
+    cv::GMat op_mat_sc2  = mat_in1 |  sc;
+    cv::GMat op_mat_sc3  = mat_in1 ^  sc;
+    cv::GMat op_mat_sc4  = mat_in1 +  sc;
+    cv::GMat op_mat_sc5  = mat_in1 -  sc;
+    cv::GMat op_mat_sc6  = mat_in1 *  sc;
+    cv::GMat op_mat_sc7  = mat_in1 /  sc;
+    cv::GMat op_mat_sc8  = mat_in1 >  sc;
+    cv::GMat op_mat_sc9  = mat_in1 >= sc;
+    cv::GMat op_mat_sc10 = mat_in1 <  sc;
+    cv::GMat op_mat_sc11 = mat_in1 <= sc;
+    cv::GMat op_mat_sc12 = mat_in1 == sc;
+    cv::GMat op_mat_sc13 = mat_in1 != sc;
+
+    cv::GMat op_sc_mat1  = sc &  mat_in2;
+    cv::GMat op_sc_mat2  = sc |  mat_in2;
+    cv::GMat op_sc_mat3  = sc ^  mat_in2;
+    cv::GMat op_sc_mat4  = sc +  mat_in2;
+    cv::GMat op_sc_mat5  = sc -  mat_in2;
+    cv::GMat op_sc_mat6  = sc *  mat_in2;
+    cv::GMat op_sc_mat7  = sc /  mat_in2;
+    cv::GMat op_sc_mat8  = sc >  mat_in2;
+    cv::GMat op_sc_mat9  = sc >= mat_in2;
+    cv::GMat op_sc_mat10 = sc <  mat_in2;
+    cv::GMat op_sc_mat11 = sc <= mat_in2;
+    cv::GMat op_sc_mat12 = sc == mat_in2;
+    cv::GMat op_sc_mat13 = sc != mat_in2;
+
+    cv::GMat mul_mat_float1 = mat_in1 * 1.0f;
+    cv::GMat mul_mat_float2 = 1.0f * mat_in2;
+    // No compilation errors expected
+}
+} // for_test
 } // opencv_test
 
 #endif // OPENCV_GAPI_OPERATOR_TESTS_INL_COMMON_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_parsers_tests_common.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_parsers_tests_common.hpp
new file mode 100644 (file)
index 0000000..127a1c5
--- /dev/null
@@ -0,0 +1,397 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_PARSERS_TESTS_COMMON_HPP
+#define OPENCV_GAPI_PARSERS_TESTS_COMMON_HPP
+
+#include "gapi_tests_common.hpp"
+#include "../../include/opencv2/gapi/infer/parsers.hpp"
+
+namespace opencv_test
+{
+class ParserSSDTest
+{
+public:
+    cv::Mat generateSSDoutput(const cv::Size& in_sz)
+    {
+        constexpr int maxN = 200;
+        constexpr int objSize = 7;
+        std::vector<int> dims{ 1, 1, maxN, objSize };
+        cv::Mat mat(dims, CV_32FC1);
+        auto data = mat.ptr<float>();
+
+        for (int i = 0; i < maxN; ++i)
+        {
+            float* it = data + i * objSize;
+            auto ssdIt = generateItem(i, in_sz);
+            it[0] = ssdIt.image_id;
+            it[1] = ssdIt.label;
+            it[2] = ssdIt.confidence;
+            it[3] = ssdIt.rc_left;
+            it[4] = ssdIt.rc_top;
+            it[5] = ssdIt.rc_right;
+            it[6] = ssdIt.rc_bottom;
+        }
+        return mat;
+    }
+
+    void parseSSDref(const cv::Mat& in_ssd_result,
+                     const cv::Size& in_size,
+                     const float confidence_threshold,
+                     const bool alignment_to_square,
+                     const bool filter_out_of_bounds,
+                     std::vector<cv::Rect>& out_boxes)
+    {
+        out_boxes.clear();
+        const auto &in_ssd_dims = in_ssd_result.size;
+        CV_Assert(in_ssd_dims.dims() == 4u);
+
+        const int MAX_PROPOSALS = in_ssd_dims[2];
+        const int OBJECT_SIZE   = in_ssd_dims[3];
+        CV_Assert(OBJECT_SIZE  == 7); // fixed SSD object size
+
+        const float *data = in_ssd_result.ptr<float>();
+        cv::Rect surface({0,0}, in_size), rc;
+        float image_id, confidence;
+        int label;
+        for (int i = 0; i < MAX_PROPOSALS; ++i)
+        {
+            std::tie(rc, image_id, confidence, label)
+                = extract(data + i*OBJECT_SIZE, in_size);
+            if (image_id < 0.f)
+            {
+                break;    // marks end-of-detections
+            }
+
+            if (confidence < confidence_threshold)
+            {
+                continue; // skip objects with low confidence
+            }
+
+            if (alignment_to_square)
+            {
+                adjustBoundingBox(rc);
+            }
+
+            const auto clipped_rc = rc & surface;
+            if (filter_out_of_bounds)
+            {
+                if (clipped_rc.area() != rc.area())
+                {
+                    continue;
+                }
+            }
+            out_boxes.emplace_back(clipped_rc);
+        }
+    }
+
+    void parseSSDBLref(const cv::Mat& in_ssd_result,
+                       const cv::Size& in_size,
+                       const float confidence_threshold,
+                       const int filter_label,
+                       std::vector<cv::Rect>& out_boxes,
+                       std::vector<int>& out_labels)
+    {
+        out_boxes.clear();
+        out_labels.clear();
+        const auto &in_ssd_dims = in_ssd_result.size;
+        CV_Assert(in_ssd_dims.dims() == 4u);
+
+        const int MAX_PROPOSALS = in_ssd_dims[2];
+        const int OBJECT_SIZE   = in_ssd_dims[3];
+        CV_Assert(OBJECT_SIZE  == 7); // fixed SSD object size
+        cv::Rect surface({0,0}, in_size), rc;
+        float image_id, confidence;
+        int label;
+        const float *data = in_ssd_result.ptr<float>();
+        for (int i = 0; i < MAX_PROPOSALS; i++)
+        {
+            std::tie(rc, image_id, confidence, label)
+                = extract(data + i*OBJECT_SIZE, in_size);
+            if (image_id < 0.f)
+            {
+                break;    // marks end-of-detections
+            }
+
+            if (confidence < confidence_threshold ||
+                (filter_label != -1 && label != filter_label))
+            {
+                continue; // filter out object classes if filter is specified
+            }
+
+            out_boxes.emplace_back(rc & surface);
+            out_labels.emplace_back(label);
+        }
+    }
+
+private:
+    void adjustBoundingBox(cv::Rect& boundingBox)
+    {
+        auto w = boundingBox.width;
+        auto h = boundingBox.height;
+
+        boundingBox.x -= static_cast<int>(0.067 * w);
+        boundingBox.y -= static_cast<int>(0.028 * h);
+
+        boundingBox.width += static_cast<int>(0.15 * w);
+        boundingBox.height += static_cast<int>(0.13 * h);
+
+        if (boundingBox.width < boundingBox.height)
+        {
+            auto dx = (boundingBox.height - boundingBox.width);
+            boundingBox.x -= dx / 2;
+            boundingBox.width += dx;
+        }
+        else
+        {
+            auto dy = (boundingBox.width - boundingBox.height);
+            boundingBox.y -= dy / 2;
+            boundingBox.height += dy;
+        }
+    }
+
+    std::tuple<cv::Rect, float, float, int> extract(const float* it,
+                                                    const cv::Size& in_size)
+    {
+        float image_id   = it[0];
+        int   label      = static_cast<int>(it[1]);
+        float confidence = it[2];
+        float rc_left    = it[3];
+        float rc_top     = it[4];
+        float rc_right   = it[5];
+        float rc_bottom  = it[6];
+
+        cv::Rect rc;  // map relative coordinates to the original image scale
+        rc.x      = static_cast<int>(rc_left   * in_size.width);
+        rc.y      = static_cast<int>(rc_top    * in_size.height);
+        rc.width  = static_cast<int>(rc_right  * in_size.width)  - rc.x;
+        rc.height = static_cast<int>(rc_bottom * in_size.height) - rc.y;
+        return std::make_tuple(rc, image_id, confidence, label);
+    }
+
+    int randInRange(const int start, const int end)
+    {
+        GAPI_Assert(start <= end);
+        return start + std::rand() % (end - start + 1);
+    }
+
+    cv::Rect generateBox(const cv::Size& in_sz)
+    {
+        // Generated rectangle can reside outside of the initial image by border pixels
+        constexpr int border = 10;
+        constexpr int minW = 16;
+        constexpr int minH = 16;
+        cv::Rect box;
+        box.width  = randInRange(minW, in_sz.width  + 2*border);
+        box.height = randInRange(minH, in_sz.height + 2*border);
+        box.x = randInRange(-border, in_sz.width  + border - box.width);
+        box.y = randInRange(-border, in_sz.height + border - box.height);
+        return box;
+    }
+
+    struct SSDitem
+    {
+        float image_id = 0.0f;
+        float label = 0.0f;
+        float confidence = 0.0f;
+        float rc_left = 0.0f;
+        float rc_top = 0.0f;
+        float rc_right = 0.0f;
+        float rc_bottom = 0.0f;
+    };
+
+    SSDitem generateItem(const int i, const cv::Size& in_sz)
+    {
+        const auto normalize = [](int v, int range) { return static_cast<float>(v) / range; };
+
+        SSDitem it;
+        it.image_id = static_cast<float>(i);
+        it.label = static_cast<float>(randInRange(0, 9));
+        it.confidence = static_cast<float>(std::rand()) / RAND_MAX;
+        auto box = generateBox(in_sz);
+        it.rc_left   = normalize(box.x, in_sz.width);
+        it.rc_right  = normalize(box.x + box.width, in_sz.width);
+        it.rc_top    = normalize(box.y, in_sz.height);
+        it.rc_bottom = normalize(box.y + box.height, in_sz.height);
+
+        return it;
+    }
+};
+
+class ParserYoloTest
+{
+public:
+    cv::Mat generateYoloOutput(const int num_classes)
+    {
+        std::vector<int> dims = { 1, 13, 13, (num_classes + 5) * 5 };
+        cv::Mat mat(dims, CV_32FC1);
+        auto data = mat.ptr<float>();
+
+        const size_t range = dims[0] * dims[1] * dims[2] * dims[3];
+        for (size_t i = 0; i < range; ++i)
+        {
+            data[i] = static_cast<float>(std::rand()) / RAND_MAX;
+        }
+        return mat;
+    }
+
+    void parseYoloRef(const cv::Mat&  in_yolo_result,
+                      const cv::Size& in_size,
+                      const float confidence_threshold,
+                      const float nms_threshold,
+                      const int num_classes,
+                      const std::vector<float>& anchors,
+                      std::vector<cv::Rect>& out_boxes,
+                      std::vector<int>& out_labels)
+    {
+        YoloParams params;
+        constexpr auto side_square = 13 * 13;
+        this->m_out = in_yolo_result.ptr<float>();
+        this->m_side = 13;
+        this->m_lcoords = params.coords;
+        this->m_lclasses = num_classes;
+
+        std::vector<Detection> detections;
+
+        for (int i = 0; i < side_square; ++i)
+        {
+            for (int b = 0; b < params.num; ++b)
+            {
+                float scale = this->scale(i, b);
+                if (scale < confidence_threshold)
+                {
+                    continue;
+                }
+                double x = this->x(i, b);
+                double y = this->y(i, b);
+                double height = this->height(i, b, anchors[2 * b + 1]);
+                double width = this->width(i, b, anchors[2 * b]);
+
+                for (int label = 0; label < num_classes; ++label)
+                {
+                    float prob = scale * classConf(i,b,label);
+                    if (prob < confidence_threshold)
+                    {
+                        continue;
+                    }
+                    auto box = toBox(x, y, height, width, in_size);
+                    detections.emplace_back(Detection(box, prob, label));
+                }
+            }
+        }
+        std::stable_sort(std::begin(detections), std::end(detections),
+                         [](const Detection& a, const Detection& b)
+                         {
+                             return a.conf > b.conf;
+                         });
+
+        if (nms_threshold < 1.0f)
+        {
+            for (const auto& d : detections)
+            {
+                if (std::end(out_boxes) ==
+                    std::find_if(std::begin(out_boxes), std::end(out_boxes),
+                                 [&d, nms_threshold](const cv::Rect& r)
+                                 {
+                                     float rectOverlap = 1.f - static_cast<float>(jaccardDistance(r, d.rect));
+                                     return rectOverlap > nms_threshold;
+                                 }))
+                {
+                    out_boxes. emplace_back(d.rect);
+                    out_labels.emplace_back(d.label);
+                }
+            }
+        }
+        else
+        {
+            for (const auto& d: detections)
+            {
+                out_boxes. emplace_back(d.rect);
+                out_labels.emplace_back(d.label);
+            }
+        }
+    }
+
+private:
+    struct Detection
+    {
+        Detection(const cv::Rect& in_rect, const float in_conf, const int in_label)
+            : rect(in_rect), conf(in_conf), label(in_label)
+        {}
+        cv::Rect rect;
+        float    conf = 0.0f;
+        int      label = 0;
+    };
+
+    struct YoloParams
+    {
+        int    num = 5;
+        int coords = 4;
+    };
+
+    float scale(const int i, const int b)
+    {
+        int obj_index = index(i, b, m_lcoords);
+        return m_out[obj_index];
+    }
+
+    double x(const int i, const int b)
+    {
+        int box_index = index(i, b, 0);
+        int col = i % m_side;
+        return (col + m_out[box_index]) / m_side;
+    }
+
+    double y(const int i, const int b)
+    {
+        int box_index = index(i, b, 0);
+        int row = i / m_side;
+        return (row + m_out[box_index + m_side * m_side]) / m_side;
+    }
+
+    double width(const int i, const int b, const float anchor)
+    {
+        int box_index = index(i, b, 0);
+        return std::exp(m_out[box_index + 2 * m_side * m_side]) * anchor / m_side;
+    }
+
+    double height(const int i, const int b, const float anchor)
+    {
+        int box_index = index(i, b, 0);
+        return std::exp(m_out[box_index + 3 * m_side * m_side]) * anchor / m_side;
+    }
+
+    float classConf(const int i, const int b, const int label)
+    {
+         int class_index = index(i, b, m_lcoords + 1 + label);
+         return m_out[class_index];
+    }
+
+    cv::Rect toBox(const double x, const double y, const double h, const double w, const cv::Size& in_sz)
+    {
+        auto h_scale = in_sz.height;
+        auto w_scale = in_sz.width;
+        cv::Rect r;
+        r.x = static_cast<int>((x - w / 2) * w_scale);
+        r.y = static_cast<int>((y - h / 2) * h_scale);
+        r.width = static_cast<int>(w * w_scale);
+        r.height = static_cast<int>(h * h_scale);
+        return r;
+    }
+
+    int index(const int i, const int b, const int entry)
+    {
+        return b * m_side * m_side * (m_lcoords + m_lclasses + 1) + entry * m_side * m_side + i;
+    }
+
+    const float* m_out = nullptr;
+    int m_side = 0, m_lcoords = 0, m_lclasses = 0;
+};
+
+} // namespace opencv_test
+
+#endif // OPENCV_GAPI_PARSERS_TESTS_COMMON_HPP
index 232616d..113f3c7 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018-2019 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 #ifndef OPENCV_GAPI_TESTS_COMMON_HPP
 #define OPENCV_GAPI_TESTS_COMMON_HPP
@@ -10,6 +10,7 @@
 #include <iostream>
 #include <tuple>
 #include <type_traits>
+#include <time.h>
 
 #include <opencv2/ts.hpp>
 #include <opencv2/gapi.hpp>
@@ -56,7 +57,24 @@ namespace
 
         return o;
     }
-}
+
+    inline void initTestDataPath()
+    {
+#ifndef WINRT
+        static bool initialized = false;
+        if (!initialized)
+        {
+            // Since G-API has no own test data (yet), it is taken from the common space
+            const char* testDataPath = getenv("OPENCV_TEST_DATA_PATH");
+            GAPI_Assert(testDataPath != nullptr &&
+            "OPENCV_TEST_DATA_PATH environment variable is either not set or set incorrectly.");
+
+            cvtest::addDataSearchPath(testDataPath);
+            initialized = true;
+        }
+#endif // WINRT
+    }
+} // namespace
 
 namespace opencv_test
 {
@@ -71,16 +89,28 @@ public:
 
     cv::Scalar sc;
 
+    // integral Scalar initialization
     cv::Scalar initScalarRandU(unsigned upper)
     {
-        auto& rng = cv::theRNG();
-        double s1 = rng(upper);  // FIXIT: RNG result is 'int', not double
+        cv::RNG rng(time(nullptr));
+        double s1 = rng(upper);
         double s2 = rng(upper);
         double s3 = rng(upper);
         double s4 = rng(upper);
         return cv::Scalar(s1, s2, s3, s4);
     }
 
+    // floating-point Scalar initialization (cv::core)
+    cv::Scalar initScalarRandU()
+    {
+        cv::RNG rng(time(nullptr));
+        double s1 = exp(rng.uniform(-1, 6) * 3.0 * CV_LOG2) * (rng.uniform(0, 2) ? 1. : -1.);
+        double s2 = exp(rng.uniform(-1, 6) * 3.0 * CV_LOG2) * (rng.uniform(0, 2) ? 1. : -1.);
+        double s3 = exp(rng.uniform(-1, 6) * 3.0 * CV_LOG2) * (rng.uniform(0, 2) ? 1. : -1.);
+        double s4 = exp(rng.uniform(-1, 6) * 3.0 * CV_LOG2) * (rng.uniform(0, 2) ? 1. : -1.);
+        return cv::Scalar(s1, s2, s3, s4);
+    }
+
     void initOutMats(cv::Size sz_in, int dtype)
     {
         if (dtype != -1)
@@ -95,7 +125,32 @@ public:
         in_mat1 = cv::Mat(sz_in, type);
         in_mat2 = cv::Mat(sz_in, type);
 
-        sc = initScalarRandU(100);
+        int sdepth = CV_MAT_DEPTH(type);
+        int ddepth = (dtype >= 0) ? CV_MAT_DEPTH(dtype)
+                                  : sdepth;             // dtype == -1 <=> dtype == SAME_TYPE
+
+        if ((sdepth >= CV_32F) || (ddepth >= CV_32F))
+        {
+            sc = initScalarRandU(); // initializing by floating-points
+        }
+        else
+        {
+            switch (sdepth)
+            {
+            case CV_8U:
+                sc = initScalarRandU(UCHAR_MAX + 1U);
+                break;
+            case CV_16U:
+                sc = initScalarRandU(USHRT_MAX + 1U);
+                break;
+            case CV_16S:
+                sc = initScalarRandU(SHRT_MAX + 1U);
+                break;
+            default:
+                sc = initScalarRandU(SCHAR_MAX + 1U);
+                break;
+            }
+        }
 
         // Details: https://github.com/opencv/opencv/pull/16083
         //if (CV_MAT_DEPTH(type) < CV_32F)
@@ -125,7 +180,33 @@ public:
     {
         in_mat1 = cv::Mat(sz_in, type);
 
-        sc = initScalarRandU(100);
+        int sdepth = CV_MAT_DEPTH(type);
+        int ddepth = (dtype >= 0) ? CV_MAT_DEPTH(dtype)
+                                  : sdepth;             // dtype == -1 <=> dtype == SAME_TYPE
+
+        if ((sdepth >= CV_32F) || (ddepth >= CV_32F))
+        {
+            sc = initScalarRandU();
+        }
+        else
+        {
+            switch (sdepth)
+            {
+            case CV_8U:
+                sc = initScalarRandU(UCHAR_MAX + 1U);
+                break;
+            case CV_16U:
+                sc = initScalarRandU(USHRT_MAX + 1U);
+                break;
+            case CV_16S:
+                sc = initScalarRandU(SHRT_MAX + 1U);
+                break;
+            default:
+                sc = initScalarRandU(SCHAR_MAX + 1U);
+                break;
+            }
+        }
+
         if (CV_MAT_DEPTH(type) < CV_32F)
         {
             cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
@@ -155,20 +236,56 @@ public:
         }
     }
 
+    void initMatFromImage(int type, const std::string& fileName)
+    {
+        initTestDataPath();
+
+        int channels = (type >> CV_CN_SHIFT) + 1;
+        GAPI_Assert(channels == 1 || channels == 3 || channels == 4);
+        const int readFlags = (channels == 1) ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR;
+        cv::Mat mat = cv::imread(findDataFile(fileName), readFlags);
+        if (channels == 4)
+        {
+            cv::cvtColor(mat, in_mat1, cv::COLOR_BGR2BGRA);
+        }
+        else
+        {
+            in_mat1 = mat;
+        }
+
+        int depth = CV_MAT_DEPTH(type);
+        if (in_mat1.depth() != depth)
+        {
+            in_mat1.convertTo(in_mat1, depth);
+        }
+    }
+
+    void initMatsFromImages(int channels, const std::string& pattern, int imgNum)
+    {
+        initTestDataPath();
+        GAPI_Assert(channels == 1 || channels == 3 || channels == 4);
+        const int flags = (channels == 1) ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR;
+
+        cv::Mat m1 = cv::imread(findDataFile(cv::format(pattern.c_str(), imgNum)), flags);
+        cv::Mat m2 = cv::imread(findDataFile(cv::format(pattern.c_str(), imgNum + 1)), flags);
+        if (channels == 4)
+        {
+            cvtColor(m1, in_mat1, cv::COLOR_BGR2BGRA);
+            cvtColor(m2, in_mat2, cv::COLOR_BGR2BGRA);
+        }
+        else
+        {
+            std::tie(in_mat1, in_mat2) = std::make_tuple(m1, m2);
+        }
+    }
+
     // empty function intended to show that nothing is to be initialized via TestFunctional methods
     void initNothing(int, cv::Size, int, bool = true) {}
 };
 
 template<class T>
-class TestParams: public TestFunctional, public TestWithParam<T>{};
-
-template<class T>
 class TestPerfParams: public TestFunctional, public perf::TestBaseWithParam<T>{};
 
-using compare_f = std::function<bool(const cv::Mat &a, const cv::Mat &b)>;
-
-using compare_scalar_f = std::function<bool(const cv::Scalar &a, const cv::Scalar &b)>;
-
 // FIXME: re-use MatType. current problem: "special values" interpreted incorrectly (-1 is printed
 //        as 16FC512)
 struct MatType2
@@ -189,14 +306,16 @@ private:
 };
 
 // Universal parameter wrapper for common (pre-defined) and specific (user-defined) parameters
-template<typename ...SpecificParams>
-struct Params
+template<typename CommonParams, typename SpecificParams>
+struct ParamsBase;
+
+template<typename... CommonParams, typename... SpecificParams>
+struct ParamsBase<std::tuple<CommonParams...>, std::tuple<SpecificParams...>>
 {
-    using gcomp_args_function_t = cv::GCompileArgs(*)();
-    using common_params_t = std::tuple<MatType2, cv::Size, MatType2, gcomp_args_function_t>;
+    using common_params_t   = std::tuple<CommonParams...>;
     using specific_params_t = std::tuple<SpecificParams...>;
-    using params_t = std::tuple<MatType2, cv::Size, MatType2, gcomp_args_function_t, SpecificParams...>;
-    static constexpr const size_t common_params_size = std::tuple_size<common_params_t>::value;
+    using params_t          = std::tuple<CommonParams..., SpecificParams...>;
+    static constexpr const size_t common_params_size   = std::tuple_size<common_params_t>::value;
     static constexpr const size_t specific_params_size = std::tuple_size<specific_params_t>::value;
 
     template<size_t I>
@@ -218,17 +337,24 @@ struct Params
     }
 };
 
-// Base class for test fixtures
-template<typename ...SpecificParams>
-struct TestWithParamBase : TestFunctional,
-    TestWithParam<typename Params<SpecificParams...>::params_t>
+template<typename... SpecificParams>
+struct Params : public ParamsBase<std::tuple<MatType2,cv::Size,MatType2,cv::GCompileArgs(*)()>,
+                                  std::tuple<SpecificParams...>>
 {
-    using AllParams = Params<SpecificParams...>;
+    static constexpr const size_t compile_args_num = 3;
+};
 
-    MatType2 type = getCommonParam<0>();
-    cv::Size sz = getCommonParam<1>();
-    MatType2 dtype = getCommonParam<2>();
+template<typename ...SpecificParams>
+struct ParamsSpecific : public ParamsBase<std::tuple<cv::GCompileArgs(*)()>,
+                                          std::tuple<SpecificParams...>>
+{
+    static constexpr const size_t compile_args_num = 0;
+};
 
+// Base class for test fixtures
+template<typename AllParams>
+struct TestWithParamsBase : TestFunctional, TestWithParam<typename AllParams::params_t>
+{
     // Get common (pre-defined) parameter value by index
     template<size_t I>
     inline auto getCommonParam() const
@@ -248,13 +374,30 @@ struct TestWithParamBase : TestFunctional,
     // Return G-API compile arguments specified for test fixture
     inline cv::GCompileArgs getCompileArgs() const
     {
-        return getCommonParam<3>()();
+        return getCommonParam<AllParams::compile_args_num>()();
     }
 };
 
+template<typename... SpecificParams>
+struct TestWithParams : public TestWithParamsBase<Params<SpecificParams...>>
+{
+    using AllParams = Params<SpecificParams...>;
+
+    MatType2 type  = this->template getCommonParam<0>();
+    cv::Size sz    = this->template getCommonParam<1>();
+    MatType2 dtype = this->template getCommonParam<2>();
+};
+
+template<typename... SpecificParams>
+struct TestWithParamsSpecific : public TestWithParamsBase<ParamsSpecific<SpecificParams...>>
+{
+    using AllParams = ParamsSpecific<SpecificParams...>;
+};
+
+
 /**
  * @private
- * @brief Create G-API test fixture with TestWithParamBase base class
+ * @brief Create G-API test fixture with TestWithParams base class
  * @param Fixture   test fixture name
  * @param InitF     callable that will initialize default available members (from TestFunctional)
  * @param API       base class API. Specifies types of user-defined parameters. If there are no such
@@ -265,17 +408,66 @@ struct TestWithParamBase : TestFunctional,
  *                  must be empty.
  */
 #define GAPI_TEST_FIXTURE(Fixture, InitF, API, Number, ...) \
-    struct Fixture : public TestWithParamBase API { \
+    struct Fixture : public TestWithParams API { \
+        static_assert(Number == AllParams::specific_params_size, \
+            "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \
+        __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \
+        Fixture() { InitF(type, sz, dtype); } \
+    };
+
+/**
+ * @private
+ * @brief Create G-API test fixture with TestWithParams base class and additional base class.
+ * @param Fixture   test fixture name.
+   @param ExtBase   additional base class.
+ * @param InitF     callable that will initialize default available members (from TestFunctional)
+ * @param API       base class API. Specifies types of user-defined parameters. If there are no such
+ *                  parameters, empty angle brackets ("<>") must be specified.
+ * @param Number    number of user-defined parameters (corresponds to the number of types in API).
+ *                  if there are no such parameters, 0 must be specified.
+ * @param ...       list of names of user-defined parameters. if there are no parameters, the list
+ *                  must be empty.
+ */
+#define GAPI_TEST_EXT_BASE_FIXTURE(Fixture, ExtBase, InitF, API, Number, ...) \
+    struct Fixture : public TestWithParams API, public ExtBase { \
         static_assert(Number == AllParams::specific_params_size, \
             "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \
         __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \
         Fixture() { InitF(type, sz, dtype); } \
     };
 
+/**
+ * @private
+ * @brief Create G-API test fixture with TestWithParamsSpecific base class
+ *        This fixture has reduced number of common parameters and no initialization;
+ *        it should be used if you don't need common parameters of GAPI_TEST_FIXTURE.
+ * @param Fixture   test fixture name
+ * @param API       base class API. Specifies types of user-defined parameters. If there are no such
+ *                  parameters, empty angle brackets ("<>") must be specified.
+ * @param Number    number of user-defined parameters (corresponds to the number of types in API).
+ *                  if there are no such parameters, 0 must be specified.
+ * @param ...       list of names of user-defined parameters. if there are no parameters, the list
+ *                  must be empty.
+ */
+#define GAPI_TEST_FIXTURE_SPEC_PARAMS(Fixture, API, Number, ...) \
+    struct Fixture : public TestWithParamsSpecific API { \
+        static_assert(Number == AllParams::specific_params_size, \
+            "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \
+        __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \
+    };
+
 // Wrapper for test fixture API. Use to specify multiple types.
 // Example: FIXTURE_API(int, bool) expands to <int, bool>
 #define FIXTURE_API(...) <__VA_ARGS__>
 
+
+using compare_f = std::function<bool(const cv::Mat &a, const cv::Mat &b)>;
+using compare_scalar_f = std::function<bool(const cv::Scalar &a, const cv::Scalar &b)>;
+
+template<typename Elem>
+using compare_vector_f = std::function<bool(const std::vector<Elem> &a,
+                                            const std::vector<Elem> &b)>;
+
 template<typename T1, typename T2>
 struct CompareF
 {
@@ -298,6 +490,9 @@ private:
 using CompareMats = CompareF<cv::Mat, cv::Mat>;
 using CompareScalars = CompareF<cv::Scalar, cv::Scalar>;
 
+template<typename Elem>
+using CompareVectors = CompareF<std::vector<Elem>, std::vector<Elem>>;
+
 template<typename T>
 struct Wrappable
 {
@@ -340,6 +535,28 @@ struct WrappableScalar
     }
 };
 
+template<typename T, typename Elem>
+struct WrappableVector
+{
+    compare_vector_f<Elem> to_compare_f()
+    {
+        T t = *static_cast<T* const>(this);
+        return [t](const std::vector<Elem>& a,
+                   const std::vector<Elem>& b)
+        {
+            return t(a, b);
+        };
+    }
+
+    CompareVectors<Elem> to_compare_obj()
+    {
+        T t = *static_cast<T* const>(this);
+        std::stringstream ss;
+        ss << t;
+        return CompareVectors<Elem>(to_compare_f(), ss.str());
+    }
+};
+
 
 class AbsExact : public Wrappable<AbsExact>
 {
@@ -547,6 +764,31 @@ public:
 private:
     double _tol;
 };
+
+template<typename Elem>
+class AbsExactVector : public WrappableVector<AbsExactVector<Elem>, Elem>
+{
+public:
+    AbsExactVector() {}
+    bool operator() (const std::vector<Elem>& in1,
+                     const std::vector<Elem>& in2) const
+    {
+        if (cv::norm(in1, in2, NORM_INF, cv::noArray()) != 0)
+        {
+            std::cout << "AbsExact error: G-API output and reference output vectors are not"
+                         " bitexact equal." << std::endl;
+            return false;
+        }
+        else
+        {
+            return true;
+        }
+    }
+    friend std::ostream& operator<<(std::ostream& os, const AbsExactVector<Elem>&)
+    {
+        return os << "AbsExactVector()";
+    }
+};
 } // namespace opencv_test
 
 namespace
@@ -560,6 +802,12 @@ inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_sca
 {
     return os << "compare_scalar_f";
 }
+
+template<typename Elem>
+inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_vector_f<Elem>&)
+{
+    return os << "compare_vector_f";
+}
 }  // anonymous namespace
 
 // Note: namespace must match the namespace of the type of the printed object
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests.cpp
new file mode 100644 (file)
index 0000000..3501b05
--- /dev/null
@@ -0,0 +1,9 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+#include "gapi_video_tests_inl.hpp"
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests.hpp
new file mode 100644 (file)
index 0000000..df57bf4
--- /dev/null
@@ -0,0 +1,34 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_VIDEO_TESTS_HPP
+#define OPENCV_GAPI_VIDEO_TESTS_HPP
+
+#include "gapi_video_tests_common.hpp"
+
+namespace opencv_test
+{
+GAPI_TEST_FIXTURE_SPEC_PARAMS(BuildOptFlowPyramidTest,
+                              FIXTURE_API(std::string,int,int,bool,int,int,bool), 7,
+                              fileName, winSize, maxLevel, withDerivatives, pyrBorder,
+                              derivBorder, tryReuseInputImage)
+
+GAPI_TEST_FIXTURE_SPEC_PARAMS(OptFlowLKTest, FIXTURE_API(std::string,int,tuple<int,int>,int,
+                                                         cv::TermCriteria),
+                              5, fileNamePattern, channels, pointsNum, winSize, criteria)
+
+GAPI_TEST_FIXTURE_SPEC_PARAMS(OptFlowLKTestForPyr, FIXTURE_API(std::string,int,tuple<int,int>,int,
+                                                               cv::TermCriteria,bool),
+                              6, fileNamePattern, channels, pointsNum, winSize, criteria,withDeriv)
+
+GAPI_TEST_FIXTURE_SPEC_PARAMS(BuildPyr_CalcOptFlow_PipelineTest,
+                              FIXTURE_API(std::string,int,int,bool), 4,
+                              fileNamePattern, winSize, maxLevel, withDerivatives)
+
+} // opencv_test
+
+
+#endif // OPENCV_GAPI_VIDEO_TESTS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests_common.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests_common.hpp
new file mode 100644 (file)
index 0000000..c12a817
--- /dev/null
@@ -0,0 +1,414 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_VIDEO_TESTS_COMMON_HPP
+#define OPENCV_GAPI_VIDEO_TESTS_COMMON_HPP
+
+#include "gapi_tests_common.hpp"
+#include "../../include/opencv2/gapi/video.hpp"
+
+#ifdef HAVE_OPENCV_VIDEO
+#include <opencv2/video.hpp>
+#endif // HAVE_OPENCV_VIDEO
+
+
+
+namespace opencv_test
+{
+namespace
+{
+G_TYPED_KERNEL(GMinScalar, <GScalar(GScalar,GScalar)>, "custom.MinScalar") {
+    static GScalarDesc outMeta(GScalarDesc,GScalarDesc) { return empty_scalar_desc(); }
+};
+GAPI_OCV_KERNEL(GCPUMinScalar, GMinScalar) {
+    static void run(const Scalar &sc1, const Scalar &sc2, Scalar &scOut) {
+        scOut = Scalar(std::min(sc1[0], sc2[0]));
+    }
+};
+
+inline void initTrackingPointsArray(std::vector<cv::Point2f>& points, int width, int height,
+                                    int nPointsX, int nPointsY)
+{
+    if (nPointsX > width || nPointsY > height)
+    {
+        FAIL() << "Specified points number is too big";
+    }
+
+    int stepX = width  / nPointsX;
+    int stepY = height / nPointsY;
+
+
+    points.clear();
+    GAPI_Assert((nPointsX >= 0) && (nPointsY) >= 0);
+    points.reserve(nPointsX * nPointsY);
+
+    for (int x = stepX / 2; x < width; x += stepX)
+    {
+        for (int y = stepY / 2; y < height; y += stepY)
+        {
+            Point2f pt(static_cast<float>(x), static_cast<float>(y));
+            points.push_back(pt);
+        }
+    }
+}
+
+struct BuildOpticalFlowPyramidTestOutput
+{
+    BuildOpticalFlowPyramidTestOutput(std::vector<Mat> &pyr, int maxLvl) :
+                                      pyramid(pyr), maxLevel(maxLvl) { }
+    std::vector<Mat> &pyramid;
+    int               maxLevel = 0;
+};
+
+template<typename Type>
+struct OptFlowLKTestInput
+{
+    Type& prevData;
+    Type& nextData;
+    std::vector<cv::Point2f>& prevPoints;
+};
+
+struct OptFlowLKTestOutput
+{
+    std::vector<cv::Point2f> &nextPoints;
+    std::vector<uchar>       &statuses;
+    std::vector<float>       &errors;
+};
+
+struct BuildOpticalFlowPyramidTestParams
+{
+    BuildOpticalFlowPyramidTestParams() = default;
+
+    BuildOpticalFlowPyramidTestParams(const std::string& name, int winSz, int maxLvl,
+                                      bool withDeriv, int pBorder, int dBorder,
+                                      bool tryReuse, const GCompileArgs& compArgs):
+
+                                      fileName(name), winSize(winSz), maxLevel(maxLvl),
+                                      withDerivatives(withDeriv), pyrBorder(pBorder),
+                                      derivBorder(dBorder), tryReuseInputImage(tryReuse),
+                                      compileArgs(compArgs) { }
+
+    std::string fileName    = "";
+    int winSize             = -1;
+    int maxLevel            = -1;
+    bool withDerivatives    = false;
+    int pyrBorder           = -1;
+    int derivBorder         = -1;
+    bool tryReuseInputImage = false;
+    cv::GCompileArgs compileArgs;
+};
+
+struct OptFlowLKTestParams
+{
+    OptFlowLKTestParams(): fileNamePattern(""), format(1), channels(0), pointsNum{0, 0},
+                           winSize(0), maxLevel(3), minEigThreshold(1e-4), flags(0) { }
+
+    OptFlowLKTestParams(const std::string& namePat, int chans,
+                        const std::tuple<int,int>& ptsNum, int winSz,
+                        const cv::TermCriteria& crit, const cv::GCompileArgs& compArgs,
+                        int flgs = 0, int fmt = 1, int maxLvl = 3, double minEigThresh = 1e-4):
+
+                        fileNamePattern(namePat), format(fmt), channels(chans),
+                        pointsNum(ptsNum), winSize(winSz), maxLevel(maxLvl),
+                        criteria(crit), minEigThreshold(minEigThresh), compileArgs(compArgs),
+                        flags(flgs) { }
+
+    std::string fileNamePattern   = "";
+    int format                    = 1;
+    int channels                  = 0;
+    std::tuple<int,int> pointsNum = std::make_tuple(0, 0);
+    int winSize                   = 0;
+    int maxLevel                  = 3;
+    cv::TermCriteria criteria;
+    double minEigThreshold        = 1e-4;
+    cv::GCompileArgs compileArgs;
+    int flags                     = 0;
+};
+
+#ifdef HAVE_OPENCV_VIDEO
+
+inline GComputation runOCVnGAPIBuildOptFlowPyramid(TestFunctional& testInst,
+                                                   const BuildOpticalFlowPyramidTestParams& params,
+                                                   BuildOpticalFlowPyramidTestOutput& outOCV,
+                                                   BuildOpticalFlowPyramidTestOutput& outGAPI)
+{
+    testInst.initMatFromImage(CV_8UC1, params.fileName);
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        outOCV.maxLevel = cv::buildOpticalFlowPyramid(testInst.in_mat1, outOCV.pyramid,
+                                                      Size(params.winSize, params.winSize),
+                                                      params.maxLevel, params.withDerivatives,
+                                                      params.pyrBorder, params.derivBorder,
+                                                      params.tryReuseInputImage);
+    }
+
+    // G-API code //////////////////////////////////////////////////////////////
+    GMat         in;
+    GArray<GMat> out;
+    GScalar      outMaxLevel;
+    std::tie(out, outMaxLevel) =
+         cv::gapi::buildOpticalFlowPyramid(in, Size(params.winSize, params.winSize),
+                                           params.maxLevel, params.withDerivatives,
+                                           params.pyrBorder, params.derivBorder,
+                                           params.tryReuseInputImage);
+
+    GComputation c(GIn(in), GOut(out, outMaxLevel));
+
+    Scalar outMaxLevelSc;
+    c.apply(gin(testInst.in_mat1), gout(outGAPI.pyramid, outMaxLevelSc),
+            std::move(const_cast<GCompileArgs&>(params.compileArgs)));
+    outGAPI.maxLevel = static_cast<int>(outMaxLevelSc[0]);
+
+    return c;
+}
+
+template<typename GType, typename Type>
+cv::GComputation runOCVnGAPIOptFlowLK(OptFlowLKTestInput<Type>& in,
+                                      int width, int height,
+                                      const OptFlowLKTestParams& params,
+                                      OptFlowLKTestOutput& ocvOut,
+                                      OptFlowLKTestOutput& gapiOut)
+{
+
+    int nPointsX = 0, nPointsY = 0;
+    std::tie(nPointsX, nPointsY) = params.pointsNum;
+
+    initTrackingPointsArray(in.prevPoints, width, height, nPointsX, nPointsY);
+
+    cv::Size winSize(params.winSize, params.winSize);
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::calcOpticalFlowPyrLK(in.prevData, in.nextData, in.prevPoints,
+                                 ocvOut.nextPoints, ocvOut.statuses, ocvOut.errors,
+                                 winSize, params.maxLevel, params.criteria,
+                                 params.flags, params.minEigThreshold);
+    }
+
+    // G-API code //////////////////////////////////////////////////////////////
+    {
+        GType               inPrev,  inNext;
+        GArray<cv::Point2f> prevPts, predPts, nextPts;
+        GArray<uchar>       statuses;
+        GArray<float>       errors;
+        std::tie(nextPts, statuses, errors) = cv::gapi::calcOpticalFlowPyrLK(
+                                                    inPrev, inNext,
+                                                    prevPts, predPts, winSize,
+                                                    params.maxLevel, params.criteria,
+                                                    params.flags, params.minEigThreshold);
+
+        cv::GComputation c(cv::GIn(inPrev, inNext, prevPts, predPts),
+                           cv::GOut(nextPts, statuses, errors));
+
+        c.apply(cv::gin(in.prevData, in.nextData, in.prevPoints, std::vector<cv::Point2f>{ }),
+                cv::gout(gapiOut.nextPoints, gapiOut.statuses, gapiOut.errors),
+                std::move(const_cast<cv::GCompileArgs&>(params.compileArgs)));
+
+        return c;
+    }
+}
+
+inline cv::GComputation runOCVnGAPIOptFlowLK(TestFunctional& testInst,
+                                             std::vector<cv::Point2f>& inPts,
+                                             const OptFlowLKTestParams& params,
+                                             OptFlowLKTestOutput& ocvOut,
+                                             OptFlowLKTestOutput& gapiOut)
+{
+    testInst.initMatsFromImages(params.channels,
+                                params.fileNamePattern,
+                                params.format);
+
+    OptFlowLKTestInput<cv::Mat> in{ testInst.in_mat1, testInst.in_mat2, inPts };
+
+    return runOCVnGAPIOptFlowLK<cv::GMat>(in,
+                                          testInst.in_mat1.cols,
+                                          testInst.in_mat1.rows,
+                                          params,
+                                          ocvOut,
+                                          gapiOut);
+}
+
+inline cv::GComputation runOCVnGAPIOptFlowLKForPyr(TestFunctional& testInst,
+                                                   OptFlowLKTestInput<std::vector<cv::Mat>>& in,
+                                                   const OptFlowLKTestParams& params,
+                                                   bool withDeriv,
+                                                   OptFlowLKTestOutput& ocvOut,
+                                                   OptFlowLKTestOutput& gapiOut)
+{
+    testInst.initMatsFromImages(params.channels,
+                                params.fileNamePattern,
+                                params.format);
+
+    cv::Size winSize(params.winSize, params.winSize);
+
+    OptFlowLKTestParams updatedParams(params);
+    updatedParams.maxLevel = cv::buildOpticalFlowPyramid(testInst.in_mat1, in.prevData,
+                                                         winSize, params.maxLevel, withDeriv);
+    updatedParams.maxLevel = cv::buildOpticalFlowPyramid(testInst.in_mat2, in.nextData,
+                                                         winSize, params.maxLevel, withDeriv);
+
+
+    return runOCVnGAPIOptFlowLK<cv::GArray<cv::GMat>>(in,
+                                                      testInst.in_mat1.cols,
+                                                      testInst.in_mat1.rows,
+                                                      updatedParams,
+                                                      ocvOut,
+                                                      gapiOut);
+}
+
+inline GComputation runOCVnGAPIOptFlowPipeline(TestFunctional& testInst,
+                                               const BuildOpticalFlowPyramidTestParams& params,
+                                               OptFlowLKTestOutput& outOCV,
+                                               OptFlowLKTestOutput& outGAPI,
+                                               std::vector<Point2f>& prevPoints)
+{
+    testInst.initMatsFromImages(3, params.fileName, 1);
+
+    initTrackingPointsArray(prevPoints, testInst.in_mat1.cols, testInst.in_mat1.rows, 15, 15);
+
+    Size winSize = Size(params.winSize, params.winSize);
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        std::vector<Mat> pyr1, pyr2;
+        int maxLevel1 = cv::buildOpticalFlowPyramid(testInst.in_mat1, pyr1, winSize,
+                                                    params.maxLevel, params.withDerivatives,
+                                                    params.pyrBorder, params.derivBorder,
+                                                    params.tryReuseInputImage);
+        int maxLevel2 = cv::buildOpticalFlowPyramid(testInst.in_mat2, pyr2, winSize,
+                                                    params.maxLevel, params.withDerivatives,
+                                                    params.pyrBorder, params.derivBorder,
+                                                    params.tryReuseInputImage);
+        cv::calcOpticalFlowPyrLK(pyr1, pyr2, prevPoints,
+                                 outOCV.nextPoints, outOCV.statuses, outOCV.errors,
+                                 winSize, std::min(maxLevel1, maxLevel2));
+    }
+
+    // G-API code //////////////////////////////////////////////////////////////
+    GMat                in1,        in2;
+    GArray<GMat>        gpyr1,      gpyr2;
+    GScalar             gmaxLevel1, gmaxLevel2;
+    GArray<cv::Point2f> gprevPts, gpredPts, gnextPts;
+    GArray<uchar>       gstatuses;
+    GArray<float>       gerrors;
+
+    std::tie(gpyr1, gmaxLevel1) = cv::gapi::buildOpticalFlowPyramid(
+                                      in1, winSize, params.maxLevel,
+                                      params.withDerivatives, params.pyrBorder,
+                                      params.derivBorder, params.tryReuseInputImage);
+
+    std::tie(gpyr2, gmaxLevel2) = cv::gapi::buildOpticalFlowPyramid(
+                                      in2, winSize, params.maxLevel,
+                                      params.withDerivatives, params.pyrBorder,
+                                      params.derivBorder, params.tryReuseInputImage);
+
+    GScalar gmaxLevel = GMinScalar::on(gmaxLevel1, gmaxLevel2);
+
+    std::tie(gnextPts, gstatuses, gerrors) = cv::gapi::calcOpticalFlowPyrLK(
+                                              gpyr1, gpyr2, gprevPts, gpredPts, winSize,
+                                              gmaxLevel);
+
+    cv::GComputation c(GIn(in1, in2, gprevPts, gpredPts), cv::GOut(gnextPts, gstatuses, gerrors));
+
+    c.apply(cv::gin(testInst.in_mat1, testInst.in_mat2, prevPoints, std::vector<cv::Point2f>{ }),
+            cv::gout(outGAPI.nextPoints, outGAPI.statuses, outGAPI.errors),
+            std::move(const_cast<cv::GCompileArgs&>(params.compileArgs)));
+
+    return c;
+}
+
+#else // !HAVE_OPENCV_VIDEO
+
+inline cv::GComputation runOCVnGAPIBuildOptFlowPyramid(TestFunctional&,
+                                                       const BuildOpticalFlowPyramidTestParams&,
+                                                       BuildOpticalFlowPyramidTestOutput&,
+                                                       BuildOpticalFlowPyramidTestOutput&)
+{
+    GAPI_Assert(0 && "This function shouldn't be called without opencv_video");
+}
+
+inline cv::GComputation runOCVnGAPIOptFlowLK(TestFunctional&,
+                                             std::vector<cv::Point2f>&,
+                                             const OptFlowLKTestParams&,
+                                             OptFlowLKTestOutput&,
+                                             OptFlowLKTestOutput&)
+{
+    GAPI_Assert(0 && "This function shouldn't be called without opencv_video");
+}
+
+inline cv::GComputation runOCVnGAPIOptFlowLKForPyr(TestFunctional&,
+                                                   OptFlowLKTestInput<std::vector<cv::Mat>>&,
+                                                   const OptFlowLKTestParams&,
+                                                   bool,
+                                                   OptFlowLKTestOutput&,
+                                                   OptFlowLKTestOutput&)
+{
+    GAPI_Assert(0 && "This function shouldn't be called without opencv_video");
+}
+
+inline GComputation runOCVnGAPIOptFlowPipeline(TestFunctional&,
+                                               const BuildOpticalFlowPyramidTestParams&,
+                                               OptFlowLKTestOutput&,
+                                               OptFlowLKTestOutput&,
+                                               std::vector<Point2f>&)
+{
+    GAPI_Assert(0 && "This function shouldn't be called without opencv_video");
+}
+
+#endif // HAVE_OPENCV_VIDEO
+
+inline void compareOutputPyramids(const BuildOpticalFlowPyramidTestOutput& outOCV,
+                                  const BuildOpticalFlowPyramidTestOutput& outGAPI)
+{
+    GAPI_Assert(outGAPI.maxLevel == outOCV.maxLevel);
+    GAPI_Assert(outOCV.maxLevel >= 0);
+    size_t maxLevel = static_cast<size_t>(outOCV.maxLevel);
+    for (size_t i = 0; i <= maxLevel; i++)
+    {
+        EXPECT_TRUE(AbsExact().to_compare_f()(outOCV.pyramid[i], outGAPI.pyramid[i]));
+    }
+}
+
+template <typename Elem>
+inline bool compareVectorsAbsExactForOptFlow(std::vector<Elem> outOCV, std::vector<Elem> outGAPI)
+{
+    return AbsExactVector<Elem>().to_compare_f()(outOCV, outGAPI);
+}
+
+inline void compareOutputsOptFlow(const OptFlowLKTestOutput& outOCV,
+                                  const OptFlowLKTestOutput& outGAPI)
+{
+    EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.nextPoints, outOCV.nextPoints));
+    EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.statuses,   outOCV.statuses));
+    EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.errors,     outOCV.errors));
+}
+
+inline std::ostream& operator<<(std::ostream& os, const cv::TermCriteria& criteria)
+{
+    os << "{";
+    switch (criteria.type) {
+    case cv::TermCriteria::COUNT:
+        os << "COUNT; ";
+        break;
+    case cv::TermCriteria::EPS:
+        os << "EPS; ";
+        break;
+    case cv::TermCriteria::COUNT | cv::TermCriteria::EPS:
+        os << "COUNT | EPS; ";
+        break;
+    default:
+        os << "TypeUndefined; ";
+        break;
+    };
+
+    return os << criteria.maxCount << "; " << criteria.epsilon <<"}";
+}
+} // namespace
+} // namespace opencv_test
+
+
+#endif // OPENCV_GAPI_VIDEO_TESTS_COMMON_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests_inl.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_video_tests_inl.hpp
new file mode 100644 (file)
index 0000000..965c06a
--- /dev/null
@@ -0,0 +1,93 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_VIDEO_TESTS_INL_HPP
+#define OPENCV_GAPI_VIDEO_TESTS_INL_HPP
+
+#include "gapi_video_tests.hpp"
+
+namespace opencv_test
+{
+
+TEST_P(BuildOptFlowPyramidTest, AccuracyTest)
+{
+    std::vector<Mat> outPyrOCV,          outPyrGAPI;
+    int              outMaxLevelOCV = 0, outMaxLevelGAPI = 0;
+
+    BuildOpticalFlowPyramidTestParams params { fileName, winSize, maxLevel,
+                                              withDerivatives, pyrBorder, derivBorder,
+                                              tryReuseInputImage, getCompileArgs() };
+
+    BuildOpticalFlowPyramidTestOutput outOCV  { outPyrOCV,  outMaxLevelOCV };
+    BuildOpticalFlowPyramidTestOutput outGAPI { outPyrGAPI, outMaxLevelGAPI };
+
+    runOCVnGAPIBuildOptFlowPyramid(*this, params, outOCV, outGAPI);
+
+    compareOutputPyramids(outOCV, outGAPI);
+}
+
+TEST_P(OptFlowLKTest, AccuracyTest)
+{
+    std::vector<cv::Point2f> outPtsOCV,    outPtsGAPI,    inPts;
+    std::vector<uchar>       outStatusOCV, outStatusGAPI;
+    std::vector<float>       outErrOCV,    outErrGAPI;
+
+    OptFlowLKTestParams params { fileNamePattern, channels, pointsNum,
+                                 winSize, criteria, getCompileArgs() };
+
+    OptFlowLKTestOutput outOCV  { outPtsOCV,  outStatusOCV,  outErrOCV };
+    OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
+
+    runOCVnGAPIOptFlowLK(*this, inPts, params, outOCV, outGAPI);
+
+    compareOutputsOptFlow(outOCV, outGAPI);
+}
+
+TEST_P(OptFlowLKTestForPyr, AccuracyTest)
+{
+    std::vector<cv::Mat>     inPyr1, inPyr2;
+    std::vector<cv::Point2f> outPtsOCV,    outPtsGAPI,    inPts;
+    std::vector<uchar>       outStatusOCV, outStatusGAPI;
+    std::vector<float>       outErrOCV,    outErrGAPI;
+
+    OptFlowLKTestParams params { fileNamePattern, channels, pointsNum,
+                                 winSize, criteria, getCompileArgs() };
+
+    OptFlowLKTestInput<std::vector<cv::Mat>> in { inPyr1, inPyr2, inPts };
+    OptFlowLKTestOutput outOCV  { outPtsOCV,  outStatusOCV,  outErrOCV };
+    OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
+
+    runOCVnGAPIOptFlowLKForPyr(*this, in, params, withDeriv, outOCV, outGAPI);
+
+    compareOutputsOptFlow(outOCV, outGAPI);
+}
+
+TEST_P(BuildPyr_CalcOptFlow_PipelineTest, AccuracyTest)
+{
+    std::vector<Point2f> outPtsOCV,    outPtsGAPI,    inPts;
+    std::vector<uchar>   outStatusOCV, outStatusGAPI;
+    std::vector<float>   outErrOCV,    outErrGAPI;
+
+    BuildOpticalFlowPyramidTestParams params { fileNamePattern, winSize, maxLevel,
+                                              withDerivatives, BORDER_DEFAULT, BORDER_DEFAULT,
+                                              true, getCompileArgs() };
+
+    auto customKernel  = gapi::kernels<GCPUMinScalar>();
+    auto kernels       = gapi::combine(customKernel,
+                                       params.compileArgs[0].get<gapi::GKernelPackage>());
+    params.compileArgs = compile_args(kernels);
+
+    OptFlowLKTestOutput outOCV  { outPtsOCV,  outStatusOCV,  outErrOCV };
+    OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
+
+    runOCVnGAPIOptFlowPipeline(*this, params, outOCV, outGAPI, inPts);
+
+    compareOutputsOptFlow(outOCV, outGAPI);
+}
+
+} // opencv_test
+
+#endif // OPENCV_GAPI_VIDEO_TESTS_INL_HPP
index f7e9816..ff98130 100644 (file)
@@ -11,7 +11,7 @@
 
 namespace
 {
-#define CORE_CPU [] () { return cv::compile_args(cv::gapi::core::cpu::kernels()); }
+#define CORE_CPU [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::core::cpu::kernels()}); }
 }  // anonymous namespace
 
 namespace opencv_test
@@ -155,7 +155,8 @@ INSTANTIATE_TEST_CASE_P(CompareTestCPU, CmpTest,
                                 Values(CV_8U),
                                 Values(CORE_CPU),
                                 Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
-                                testing::Bool()));
+                                testing::Bool(),
+                                Values(AbsExact().to_compare_obj())));
 
 INSTANTIATE_TEST_CASE_P(BitwiseTestCPU, BitwiseTest,
                         Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
@@ -164,7 +165,8 @@ INSTANTIATE_TEST_CASE_P(BitwiseTestCPU, BitwiseTest,
                                        cv::Size(128, 128)),
                                 Values(-1),
                                 Values(CORE_CPU),
-                                Values(AND, OR, XOR)));
+                                Values(AND, OR, XOR),
+                                testing::Bool()));
 
 INSTANTIATE_TEST_CASE_P(BitwiseNotTestCPU, NotTest,
                         Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
@@ -496,4 +498,43 @@ INSTANTIATE_TEST_CASE_P(ReInitOutTestCPU, ReInitOutTest,
                                 Values(cv::Size(640, 400),
                                        cv::Size(10, 480))));
 
+INSTANTIATE_TEST_CASE_P(ParseTestCPU, ParseSSDBLTest,
+                        Combine(Values(CV_8UC1, CV_8UC3, CV_32FC1),
+                                Values(cv::Size(1920, 1080)),
+                                Values(-1),
+                                Values(CORE_CPU),
+                                Values(0.3f, 0.5f, 0.7f),
+                                Values(-1, 0, 1)));
+
+INSTANTIATE_TEST_CASE_P(ParseTestCPU, ParseSSDTest,
+                        Combine(Values(CV_8UC1, CV_8UC3, CV_32FC1),
+                                Values(cv::Size(1920, 1080)),
+                                Values(-1),
+                                Values(CORE_CPU),
+                                Values(0.3f, 0.5f, 0.7f),
+                                testing::Bool(),
+                                testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(ParseTestCPU, ParseYoloTest,
+                        Combine(Values(CV_8UC1, CV_8UC3, CV_32FC1),
+                                Values(cv::Size(1920, 1080)),
+                                Values(-1),
+                                Values(CORE_CPU),
+                                Values(0.3f, 0.5f, 0.7f),
+                                Values(0.5f, 1.0f),
+                                Values(80, 7)));
+
+INSTANTIATE_TEST_CASE_P(SizeTestCPU, SizeTest,
+                        Combine(Values(CV_8UC1, CV_8UC3, CV_32FC1),
+                                Values(cv::Size(32, 32),
+                                       cv::Size(640, 320)),
+                                Values(-1),
+                                Values(CORE_CPU)));
+
+INSTANTIATE_TEST_CASE_P(SizeRTestCPU, SizeRTest,
+                        Combine(Values(CV_8UC1, CV_8UC3, CV_32FC1),
+                                Values(cv::Size(32, 32),
+                                       cv::Size(640, 320)),
+                                Values(-1),
+                                Values(CORE_CPU)));
 }
index e20fb11..8162e01 100644 (file)
 
 namespace
 {
-#define CORE_FLUID [] () { return cv::compile_args(cv::gapi::core::fluid::kernels()); }
+#define CORE_FLUID [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::core::fluid::kernels()}); }
 }  // anonymous namespace
 
 namespace opencv_test
 {
-
 // FIXME: Windows accuracy problems after recent update!
 INSTANTIATE_TEST_CASE_P(MathOpTestFluid, MathOpTest,
                         Combine(Values(CV_8UC3, CV_8UC1, CV_16SC1, CV_32FC1),
@@ -25,11 +24,46 @@ INSTANTIATE_TEST_CASE_P(MathOpTestFluid, MathOpTest,
                                        cv::Size(128, 128)),
                                 Values(-1, CV_8U, CV_32F),
                                 Values(CORE_FLUID),
-                                Values(ADD, SUB, DIV, MUL),
+                                Values(DIV, MUL),
+                                testing::Bool(),
+                                Values(1.0),
+                                testing::Bool()));
+
+// FIXME: Accuracy test for SUB math operation fails on FullHD and HD CV_16SC1 input cv::Mat,
+//        double-presicion input cv::Scalar and CV_32FC1 output cv::Mat on Mac.
+//        Accuracy test for ADD math operation fails on HD CV_16SC1 input cv::Mat,
+//        double-presicion input cv::Scalar and CV_32FC1 output cv::Mat on Mac.
+//        As failures are sporadic, disabling all instantiation cases for SUB and ADD.
+//        Github ticket: https://github.com/opencv/opencv/issues/18373.
+INSTANTIATE_TEST_CASE_P(DISABLED_MathOpTestFluid, MathOpTest,
+                        Combine(Values(CV_8UC3, CV_8UC1, CV_16SC1, CV_32FC1),
+                                Values(cv::Size(1920, 1080),
+                                       cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1, CV_8U, CV_32F),
+                                Values(CORE_FLUID),
+                                Values(ADD, SUB),
                                 testing::Bool(),
                                 Values(1.0),
                                 testing::Bool()));
 
+// FIXME: Accuracy test for SUB math operation fails on CV_16SC1 input cv::Mat, double-presicion
+//        input cv::Scalar and CV_32FC1 output cv::Mat on Mac.
+//        As failures are sporadic, disabling all instantiation cases for SUB operation.
+//        Github ticket: https://github.com/opencv/opencv/issues/18373.
+INSTANTIATE_TEST_CASE_P(DISABLED_SubTestFluid, MathOpTest,
+                        Combine(Values(CV_8UC1, CV_16SC1 , CV_32FC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1, CV_8U, CV_32F),
+                                Values(CORE_FLUID),
+                                Values(SUB),
+                                testing::Bool(),
+                                Values (1.0),
+                                testing::Bool()));
+
 INSTANTIATE_TEST_CASE_P(MulSTestFluid, MulDoubleTest,
                         Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
                                 Values(cv::Size(1280, 720),
@@ -46,6 +80,22 @@ INSTANTIATE_TEST_CASE_P(DivCTestFluid, DivCTest,
                                 Values(CV_8U, CV_32F),
                                 Values(CORE_FLUID)));
 
+INSTANTIATE_TEST_CASE_P(DISABLED_MeanTestFluid, MeanTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID)));
+
+INSTANTIATE_TEST_CASE_P(MaskTestFluid, MaskTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID)));
+
 INSTANTIATE_TEST_CASE_P(AbsDiffTestFluid, AbsDiffTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
                                 Values(cv::Size(1280, 720),
@@ -70,7 +120,8 @@ INSTANTIATE_TEST_CASE_P(BitwiseTestFluid, BitwiseTest,
                                        cv::Size(128, 128)),
                                 Values(-1),
                                 Values(CORE_FLUID),
-                                Values(AND, OR, XOR)));
+                                Values(AND, OR, XOR),
+                                testing::Bool()));
 
 INSTANTIATE_TEST_CASE_P(BitwiseNotTestFluid, NotTest,
                         Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1),
@@ -99,6 +150,15 @@ INSTANTIATE_TEST_CASE_P(MaxTestFluid, MaxTest,
                                 Values(-1),
                                 Values(CORE_FLUID)));
 
+INSTANTIATE_TEST_CASE_P(DISABLED_SumTestFluid, SumTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID),
+                                Values(AbsToleranceScalar(1e-5).to_compare_obj())));
+
 INSTANTIATE_TEST_CASE_P(CompareTestFluid, CmpTest,
                         Combine(Values(CV_8UC3, CV_8UC1, CV_16SC1, CV_32FC1),
                                 Values(cv::Size(1920, 1080),
@@ -108,7 +168,21 @@ INSTANTIATE_TEST_CASE_P(CompareTestFluid, CmpTest,
                                 Values(CV_8U),
                                 Values(CORE_FLUID),
                                 Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
-                                testing::Bool()));
+                                Values(false),
+                                Values(AbsExact().to_compare_obj())));
+
+// FIXME: solve comparison error to unite with the test above
+INSTANTIATE_TEST_CASE_P(CompareTestFluidScalar, CmpTest,
+                        Combine(Values(CV_8UC3, CV_8UC1, CV_16SC1, CV_32FC1),
+                                Values(cv::Size(1920, 1080),
+                                       cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(CV_8U),
+                                Values(CORE_FLUID),
+                                Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+                                Values(true),
+                                Values(AbsSimilarPoints(1, 0.01).to_compare_obj())));
 
 INSTANTIATE_TEST_CASE_P(AddWeightedTestFluid, AddWeightedTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
@@ -119,6 +193,24 @@ INSTANTIATE_TEST_CASE_P(AddWeightedTestFluid, AddWeightedTest,
                                 Values(CORE_FLUID),
                                 Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_obj())));
 
+INSTANTIATE_TEST_CASE_P(DISABLED_NormTestFluid, NormTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID),
+                                Values(AbsToleranceScalar(1e-5).to_compare_obj()),
+                                Values(NORM_INF, NORM_L1, NORM_L2)));
+
+INSTANTIATE_TEST_CASE_P(DISABLED_IntegralTestFluid, IntegralTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID)));
+
 INSTANTIATE_TEST_CASE_P(LUTTestFluid, LUTTest,
                         Combine(Values(CV_8UC1, CV_8UC3),
                                 Values(cv::Size(1920, 1080),
@@ -129,17 +221,32 @@ INSTANTIATE_TEST_CASE_P(LUTTestFluid, LUTTest,
                                 Values(CORE_FLUID)));
 
 INSTANTIATE_TEST_CASE_P(ConvertToFluid, ConvertToTest,
-                        Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
-                                Values(cv::Size(1920, 1080),
-                                       cv::Size(1280, 720),
+                        Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
+                                Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
                                        cv::Size(128, 128)),
-                                Values(CV_8U, CV_16U, CV_32F),
+                                Values(CV_8U, CV_16U, CV_16S, CV_32F),
                                 Values(CORE_FLUID),
                                 Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_obj()),
                                 Values(2.5, 1.0, -1.0),
                                 Values(250.0, 0.0, -128.0)));
 
+INSTANTIATE_TEST_CASE_P(DISABLED_ConcatHorTestFluid, ConcatHorTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID)));
+
+INSTANTIATE_TEST_CASE_P(DISABLED_ConcatVertTestFluid, ConcatVertTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID)));
+
 INSTANTIATE_TEST_CASE_P(Split3TestFluid, Split3Test,
                         Combine(Values(CV_8UC3),
                                 Values(cv::Size(1280, 720),
@@ -174,6 +281,32 @@ INSTANTIATE_TEST_CASE_P(Merge4TestFluid, Merge4Test,
                                 Values(CV_8UC4),
                                 Values(CORE_FLUID)));
 
+INSTANTIATE_TEST_CASE_P(DISABLED_RemapTestFluid, RemapTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID)));
+
+INSTANTIATE_TEST_CASE_P(DISABLED_FlipTestFluid, FlipTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID),
+                                Values(0,1,-1)));
+
+INSTANTIATE_TEST_CASE_P(DISABLED_CropTestFluid, CropTest,
+                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID),
+                                Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50))));
+
 INSTANTIATE_TEST_CASE_P(SelectTestFluid, SelectTest,
                         Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1),
                                 Values(cv::Size(1920, 1080),
@@ -231,6 +364,15 @@ INSTANTIATE_TEST_CASE_P(ThresholdTestFluid, ThresholdTest,
                                        cv::Scalar(100, 100, 100, 100),
                                        cv::Scalar(255, 255, 255, 255))));
 
+INSTANTIATE_TEST_CASE_P(DISABLED_ThresholdTestFluid, ThresholdOTTest,
+                        Combine(Values(CV_8UC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID),
+                                Values(cv::THRESH_OTSU, cv::THRESH_TRIANGLE)));
+
 INSTANTIATE_TEST_CASE_P(InRangeTestFluid, InRangeTest,
                         Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
                                 Values(cv::Size(1920, 1080),
@@ -257,6 +399,20 @@ INSTANTIATE_TEST_CASE_P(ResizeTestFluid, ResizeTest,
                                        cv::Size(64, 64),
                                        cv::Size(30, 30))));
 
+INSTANTIATE_TEST_CASE_P(ResizeTestFxFyFluid, ResizeTestFxFy,
+                        Combine(Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128),
+                                       cv::Size(64, 64),
+                                       cv::Size(30, 30)),
+                                Values(-1),
+                                Values(CORE_FLUID),
+                                Values(AbsExact().to_compare_obj()),
+                                Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
+                                Values(0.5, 1, 2),
+                                Values(0.5, 1, 2)));
+
 INSTANTIATE_TEST_CASE_P(BackendOutputAllocationTestFluid, BackendOutputAllocationTest,
                         Combine(Values(CV_8UC3, CV_16SC2, CV_32FC1),
                                 Values(cv::Size(50, 50)),
@@ -285,260 +441,4 @@ INSTANTIATE_TEST_CASE_P(CopyTestFluid, CopyTest,
                                        cv::Size(128, 128)),
                                 Values(-1),
                                 Values(CORE_FLUID)));
-
-//----------------------------------------------------------------------
-// FIXME: Clean-up test configurations which are enabled already
-#if 0
-INSTANTIATE_TEST_CASE_P(MathOpTestCPU, MathOpTest,
-                        Combine(Values(ADD, DIV, MUL),
-                                testing::Bool(),
-                                Values(CV_8UC1, CV_16SC1, CV_32FC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-                                Values(-1, CV_8U, CV_32F),
-/*init output matrices or not*/ testing::Bool(),
-                                Values(false)));
-
-INSTANTIATE_TEST_CASE_P(SubTestCPU, MathOpTest,
-                        Combine(Values(SUB),
-                                testing::Bool(),
-                                Values(CV_8UC1, CV_16SC1 , CV_32FC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-                                Values(-1, CV_8U, CV_32F),
-/*init output matrices or not*/ testing::Bool(),
-                                testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(MulSTestCPU, MulSTest,
-                        Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(DivCTestCPU, DivCTest,
-                        Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-                                Values(CV_8U, CV_32F),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(MeanTestCPU, MeanTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(SelectTestCPU, SelectTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(Polar2CartCPU, Polar2CartTest,
-                        Combine(Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(Cart2PolarCPU, Cart2PolarTest,
-                        Combine(Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(CompareTestCPU, CmpTest,
-                        Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
-                                testing::Bool(),
-                                Values(CV_8UC1, CV_16SC1, CV_32FC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(BitwiseTestCPU, BitwiseTest,
-                        Combine(Values(AND, OR, XOR),
-                                Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(BitwiseNotTestCPU, NotTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
- /*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(MinTestCPU, MinTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(MaxTestCPU, MaxTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(SumTestCPU, SumTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool())
-                                Values(0.0),
-                       );
-
-INSTANTIATE_TEST_CASE_P(AbsDiffTestCPU, AbsDiffTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(AbsDiffCTestCPU, AbsDiffCTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(AddWeightedTestCPU, AddWeightedTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-                                Values(-1, CV_8U, CV_32F),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(NormTestCPU, NormTest,
-                        Combine(Values(NORM_INF, NORM_L1, NORM_L2),
-                                Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128))),
-                                Values(0.0));
-
-INSTANTIATE_TEST_CASE_P(IntegralTestCPU, IntegralTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128))));
-
-INSTANTIATE_TEST_CASE_P(ThresholdTestCPU, ThresholdTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-                                Values(cv::THRESH_BINARY, cv::THRESH_BINARY_INV, cv::THRESH_TRUNC, cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(ThresholdTestCPU, ThresholdOTTest,
-                        Combine(Values(CV_8UC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-                                Values(cv::THRESH_OTSU, cv::THRESH_TRIANGLE),
-/*init output matrices or not*/ testing::Bool()));
-
-
-INSTANTIATE_TEST_CASE_P(InRangeTestCPU, InRangeTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(Split3TestCPU, Split3Test,
-                        (Values(cv::Size(1280, 720),
-                                cv::Size(640, 480),
-                                cv::Size(128, 128))));
-
-INSTANTIATE_TEST_CASE_P(Split4TestCPU, Split4Test,
-                        (Values(cv::Size(1280, 720),
-                                cv::Size(640, 480),
-                                cv::Size(128, 128))));
-
-INSTANTIATE_TEST_CASE_P(Merge3TestCPU, Merge3Test,
-                        (Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128))));
-
-INSTANTIATE_TEST_CASE_P(Merge4TestCPU, Merge4Test,
-                        (Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128))));
-
-INSTANTIATE_TEST_CASE_P(RemapTestCPU, RemapTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(FlipTestCPU, FlipTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(0,1,-1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(CropTestCPU, CropTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50)),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ testing::Bool()));
-
-INSTANTIATE_TEST_CASE_P(LUTTestCPU, LUTTest,
-                        Combine(Values(CV_8UC1, CV_8UC3),
-                                Values(CV_8UC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ Values(true)));
-
-INSTANTIATE_TEST_CASE_P(LUTTestCustomCPU, LUTTest,
-                        Combine(Values(CV_8UC3),
-                                Values(CV_8UC3),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128)),
-/*init output matrices or not*/ Values(true)));
-
-// PLEASE DO NOT PUT NEW ACCURACY TESTS BELOW THIS POINT! //////////////////////
-
-INSTANTIATE_TEST_CASE_P(ConvertToCPU, ConvertToTest,
-                        Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
-                                Values(CV_8U, CV_16U, CV_32F),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128))));
-
-INSTANTIATE_TEST_CASE_P(ConcatHorTestCPU, ConcatHorTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128))));
-INSTANTIATE_TEST_CASE_P(ConcatVertTestCPU, ConcatVertTest,
-                        Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
-                                Values(cv::Size(1280, 720),
-                                       cv::Size(640, 480),
-                                       cv::Size(128, 128))));
-
-//----------------------------------------------------------------------
-#endif // 0
-
 }
index e3e90ce..8a94583 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018-2019 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 #include "../test_precomp.hpp"
@@ -12,7 +12,7 @@
 
 namespace
 {
-#define IMGPROC_CPU [] () { return cv::compile_args(cv::gapi::imgproc::cpu::kernels()); }
+#define IMGPROC_CPU [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::imgproc::cpu::kernels()}); }
 }  // anonymous namespace
 
 namespace opencv_test
@@ -176,6 +176,29 @@ INSTANTIATE_TEST_CASE_P(SobelXYTestCPU32F, SobelXYTest,
                                 Values(BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT),
                                 Values(0, 1, 255)));
 
+INSTANTIATE_TEST_CASE_P(LaplacianTestCPU, LaplacianTest,
+                        Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480)),
+                                Values(-1),
+                                Values(IMGPROC_CPU),
+                                Values(AbsExact().to_compare_obj()),
+                                Values(1, 3),
+                                Values(0.2, 1.0),
+                                Values(BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT)));
+
+INSTANTIATE_TEST_CASE_P(BilateralFilterTestCPU, BilateralFilterTest,
+                        Combine(Values(CV_32FC1, CV_32FC3, CV_8UC1, CV_8UC3),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480)),
+                                Values(-1),
+                                Values(IMGPROC_CPU),
+                                Values(AbsExact().to_compare_obj()),
+                                Values(3, 5),
+                                Values(20),
+                                Values(10),
+                                Values(BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT)));
+
 INSTANTIATE_TEST_CASE_P(EqHistTestCPU, EqHistTest,
                         Combine(Values(CV_8UC1),
                                 Values(cv::Size(1280, 720),
@@ -196,6 +219,29 @@ INSTANTIATE_TEST_CASE_P(CannyTestCPU, CannyTest,
                                 Values(3, 5),
                                 testing::Bool()));
 
+INSTANTIATE_TEST_CASE_P(GoodFeaturesTestCPU, GoodFeaturesTest,
+                        Combine(Values(IMGPROC_CPU),
+                                Values(AbsExactVector<cv::Point2f>().to_compare_obj()),
+                                Values("cv/shared/fruits.png"),
+                                Values(CV_32FC1, CV_8UC1),
+                                Values(50, 100),
+                                Values(0.01),
+                                Values(10.0),
+                                Values(3),
+                                testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(GoodFeaturesInternalTestCPU, GoodFeaturesTest,
+                        Combine(Values(IMGPROC_CPU),
+                                Values(AbsExactVector<cv::Point2f>().to_compare_obj()),
+                                Values("cv/cascadeandhog/images/audrybt1.png"),
+                                Values(CV_32FC1, CV_8UC1),
+                                Values(100),
+                                Values(0.0000001),
+                                Values(5.0),
+                                Values(3),
+                                Values(true)));
+
+
 INSTANTIATE_TEST_CASE_P(RGB2GrayTestCPU, RGB2GrayTest,
                         Combine(Values(CV_8UC3),
                                 Values(cv::Size(1280, 720),
index 282241f..4e84782 100644 (file)
@@ -10,7 +10,7 @@
 
 namespace
 {
-#define IMGPROC_FLUID [] () { return cv::compile_args(cv::gapi::imgproc::fluid::kernels()); }
+#define IMGPROC_FLUID [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::imgproc::fluid::kernels()}); }
 }  // anonymous namespace
 
 namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_test_utils.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_test_utils.hpp
new file mode 100644 (file)
index 0000000..040e628
--- /dev/null
@@ -0,0 +1,47 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#ifndef OPENCV_GAPI_OCV_STATEFUL_KERNEL_TESTS_UTILS_HPP
+#define OPENCV_GAPI_OCV_STATEFUL_KERNEL_TESTS_UTILS_HPP
+
+#include "../test_precomp.hpp"
+
+// TODO: Reuse Anatoliy's logic for support of types with commas in macro.
+//       Retrieve the common part from Anatoliy's logic to the separate place.
+#define DEFINE_INITIALIZER(Name, StateType, ...) \
+struct Name                                      \
+{                                                \
+    static StateType value()                     \
+    {                                            \
+       return __VA_ARGS__;                       \
+    }                                            \
+}                                                \
+
+namespace opencv_test
+{
+namespace
+{
+struct UserStruct
+{
+    UserStruct() = default;
+    UserStruct(short myShortVal, float myFloatVal):
+    _myShortVal(myShortVal),
+    _myFloatVal(myFloatVal) { }
+
+    bool operator==(const UserStruct& rhs) const
+    {
+        return ((_myShortVal == rhs._myShortVal) &&
+                (_myFloatVal == rhs._myFloatVal));
+    }
+
+private:
+    short _myShortVal;
+    float _myFloatVal;
+};
+} // anonymous namespace
+} // opencv_test
+
+#endif // OPENCV_GAPI_OCV_STATEFUL_KERNEL_TESTS_UTILS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp
new file mode 100644 (file)
index 0000000..53d85ce
--- /dev/null
@@ -0,0 +1,422 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include "gapi_ocv_stateful_kernel_test_utils.hpp"
+#include <opencv2/gapi/cpu/core.hpp>
+#include <opencv2/gapi/streaming/cap.hpp>
+
+#include <opencv2/core.hpp>
+#include <opencv2/core/cvstd.hpp>
+#include <opencv2/video.hpp>
+
+
+namespace opencv_test
+{
+    struct BackSubStateParams
+    {
+        std::string method;
+    };
+}
+
+namespace cv
+{
+    namespace detail
+    {
+        template<> struct CompileArgTag<opencv_test::BackSubStateParams>
+        {
+            static const char* tag()
+            {
+                return "org.opencv.test..background_substractor_state_params";
+            }
+        };
+    }
+}
+
+namespace opencv_test
+{
+//TODO: test OT, Background Subtractor, Kalman with 3rd version of API
+//----------------------------------------------- Simple tests ------------------------------------------------
+namespace
+{
+    inline void initTestDataPath()
+    {
+#ifndef WINRT
+        static bool initialized = false;
+        if (!initialized)
+        {
+            // Since G-API has no own test data (yet), it is taken from the common space
+            const char* testDataPath = getenv("OPENCV_TEST_DATA_PATH");
+            GAPI_Assert(testDataPath != nullptr);
+
+            cvtest::addDataSearchPath(testDataPath);
+            initialized = true;
+        }
+#endif // WINRT
+    }
+
+    G_TYPED_KERNEL(GCountCalls, <cv::GOpaque<int>(GMat)>, "org.opencv.test.count_calls")
+    {
+        static GOpaqueDesc outMeta(GMatDesc /* in */) { return empty_gopaque_desc(); }
+    };
+
+    GAPI_OCV_KERNEL_ST(GOCVCountCalls, GCountCalls, int)
+    {
+        static void setup(const cv::GMatDesc &/* in */, std::shared_ptr<int> &state)
+        {
+            state.reset(new int{  });
+        }
+
+        static void run(const cv::Mat &/* in */, int &out, int& state)
+        {
+            out = ++state;
+        }
+    };
+
+    G_TYPED_KERNEL(GIsStateUpToDate, <cv::GOpaque<bool>(GMat)>,
+                   "org.opencv.test.is_state_up-to-date")
+    {
+        static GOpaqueDesc outMeta(GMatDesc /* in */) { return empty_gopaque_desc(); }
+    };
+
+    GAPI_OCV_KERNEL_ST(GOCVIsStateUpToDate, GIsStateUpToDate, cv::Size)
+    {
+        static void setup(const cv::GMatDesc &in, std::shared_ptr<cv::Size> &state)
+        {
+            state.reset(new cv::Size(in.size));
+        }
+
+        static void run(const cv::Mat &in , bool &out, cv::Size& state)
+        {
+            out = in.size() == state;
+        }
+    };
+
+    G_TYPED_KERNEL(GStInvalidResize, <GMat(GMat,Size,double,double,int)>,
+                   "org.opencv.test.st_invalid_resize")
+    {
+         static GMatDesc outMeta(GMatDesc in, Size, double, double, int) { return in; }
+    };
+
+    GAPI_OCV_KERNEL_ST(GOCVStInvalidResize, GStInvalidResize, int)
+    {
+        static void setup(const cv::GMatDesc, cv::Size, double, double, int,
+                          std::shared_ptr<int> &/* state */)
+        {  }
+
+        static void run(const cv::Mat& in, cv::Size sz, double fx, double fy, int interp,
+                        cv::Mat &out, int& /* state */)
+        {
+            cv::resize(in, out, sz, fx, fy, interp);
+        }
+    };
+
+    G_TYPED_KERNEL(GBackSub, <GMat(GMat)>, "org.opencv.test.background_substractor")
+    {
+         static GMatDesc outMeta(GMatDesc in) { return in.withType(CV_8U, 1); }
+    };
+
+    GAPI_OCV_KERNEL_ST(GOCVBackSub, GBackSub, cv::BackgroundSubtractor)
+    {
+        static void setup(const cv::GMatDesc &/* desc */,
+                          std::shared_ptr<BackgroundSubtractor> &state,
+                          const cv::GCompileArgs &compileArgs)
+        {
+            auto sbParams = cv::gapi::getCompileArg<BackSubStateParams>(compileArgs)
+                                .value_or(BackSubStateParams { });
+
+            if (sbParams.method == "knn")
+                state = createBackgroundSubtractorKNN();
+            else if (sbParams.method == "mog2")
+                state = createBackgroundSubtractorMOG2();
+
+            GAPI_Assert(state);
+        }
+
+        static void run(const cv::Mat& in, cv::Mat &out, BackgroundSubtractor& state)
+        {
+            state.apply(in, out, -1);
+        }
+    };
+};
+
+TEST(StatefulKernel, StateIsMutableInRuntime)
+{
+    constexpr int expectedCallsCount = 10;
+
+    cv::Mat dummyIn { 1, 1, CV_8UC1 };
+    int actualCallsCount = 0;
+
+    // Declaration of G-API expression
+    GMat in;
+    GOpaque<int> out = GCountCalls::on(in);
+    cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+
+    const auto pkg = cv::gapi::kernels<GOCVCountCalls>();
+
+    // Compilation of G-API expression
+    auto callsCounter = comp.compile(cv::descr_of(dummyIn), cv::compile_args(pkg));
+
+    // Simulating video stream: call GCompiled multiple times
+    for (int i = 0; i < expectedCallsCount; i++)
+    {
+        callsCounter(cv::gin(dummyIn), cv::gout(actualCallsCount));
+        EXPECT_EQ(i + 1, actualCallsCount);
+    }
+
+    // End of "video stream"
+    EXPECT_EQ(expectedCallsCount, actualCallsCount);
+
+    // User asks G-API to prepare for a new stream
+    callsCounter.prepareForNewStream();
+    callsCounter(cv::gin(dummyIn), cv::gout(actualCallsCount));
+    EXPECT_EQ(1, actualCallsCount);
+
+}
+
+TEST(StatefulKernel, StateIsAutoResetForNewStream)
+{
+    initTestDataPath();
+
+    cv::GMat in;
+    cv::GOpaque<bool> out = GIsStateUpToDate::on(in);
+    cv::GComputation c(cv::GIn(in), cv::GOut(out));
+
+    const auto pkg = cv::gapi::kernels<GOCVIsStateUpToDate>();
+
+    // Compilation & testing
+    auto ccomp = c.compileStreaming(cv::compile_args(pkg));
+
+    ccomp.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>
+                               (findDataFile("cv/video/768x576.avi")));
+    ccomp.start();
+    EXPECT_TRUE(ccomp.running());
+
+    // Process the full video
+    bool isStateUpToDate = false;
+    while (ccomp.pull(cv::gout(isStateUpToDate))) {
+        EXPECT_TRUE(isStateUpToDate);
+    }
+    EXPECT_FALSE(ccomp.running());
+
+    ccomp.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>
+                               (findDataFile("cv/video/1920x1080.avi")));
+    ccomp.start();
+    EXPECT_TRUE(ccomp.running());
+
+    while (ccomp.pull(cv::gout(isStateUpToDate))) {
+        EXPECT_TRUE(isStateUpToDate);
+    }
+    EXPECT_FALSE(ccomp.running());
+}
+
+TEST(StatefulKernel, InvalidReallocatingKernel)
+{
+    cv::GMat in, out;
+    cv::Mat in_mat(500, 500, CV_8UC1), out_mat;
+    out = GStInvalidResize::on(in, cv::Size(300, 300), 0.0, 0.0, cv::INTER_LINEAR);
+
+    const auto pkg = cv::gapi::kernels<GOCVStInvalidResize>();
+    cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+
+    EXPECT_THROW(comp.apply(in_mat, out_mat, cv::compile_args(pkg)), std::logic_error);
+}
+
+namespace
+{
+    void compareBackSubResults(const cv::Mat &actual, const cv::Mat &expected,
+                               const int diffPercent)
+    {
+        GAPI_Assert(actual.size() == expected.size());
+        int allowedNumDiffPixels = actual.size().area() * diffPercent / 100;
+
+        cv::Mat diff;
+        cv::absdiff(actual, expected, diff);
+
+        cv::Mat hist(256, 1, CV_32FC1, cv::Scalar(0));
+        const float range[] { 0, 256 };
+        const float *histRange { range };
+        calcHist(&diff, 1, 0, Mat(), hist, 1, &hist.rows, &histRange, true, false);
+        for (int i = 2; i < hist.rows; ++i)
+        {
+            hist.at<float>(i) += hist.at<float>(i - 1);
+        }
+
+        int numDiffPixels = static_cast<int>(hist.at<float>(255));
+
+        EXPECT_GT(allowedNumDiffPixels, numDiffPixels);
+    }
+} // anonymous namespace
+
+TEST(StatefulKernel, StateIsInitViaCompArgs)
+{
+    cv::Mat frame(1080, 1920, CV_8UC3),
+            gapiForeground,
+            ocvForeground;
+
+    cv::randu(frame, cv::Scalar(0, 0, 0), cv::Scalar(255, 255, 255));
+
+    // G-API code
+    cv::GMat in;
+    cv::GMat out = GBackSub::on(in);
+    cv::GComputation c(cv::GIn(in), cv::GOut(out));
+
+    const auto pkg = cv::gapi::kernels<GOCVBackSub>();
+
+    auto gapiBackSub = c.compile(cv::descr_of(frame),
+                                 cv::compile_args(pkg, BackSubStateParams { "knn" }));
+
+    gapiBackSub(cv::gin(frame), cv::gout(gapiForeground));
+
+    // OpenCV code
+    auto pOcvBackSub = createBackgroundSubtractorKNN();
+    pOcvBackSub->apply(frame, ocvForeground);
+
+    // Comparison
+    // Allowing 1% difference of all pixels between G-API and OpenCV results
+    compareBackSubResults(gapiForeground, ocvForeground, 1);
+
+    // Additionally, test the case where state is resetted
+    gapiBackSub.prepareForNewStream();
+    gapiBackSub(cv::gin(frame), cv::gout(gapiForeground));
+    pOcvBackSub->apply(frame, ocvForeground);
+    compareBackSubResults(gapiForeground, ocvForeground, 1);
+}
+
+namespace
+{
+    void testBackSubInStreaming(cv::GStreamingCompiled gapiBackSub, const int diffPercent)
+    {
+        cv::Mat frame,
+                gapiForeground,
+                ocvForeground;
+
+        gapiBackSub.start();
+        EXPECT_TRUE(gapiBackSub.running());
+
+        // OpenCV reference substractor
+        auto pOCVBackSub = createBackgroundSubtractorKNN();
+
+        // Comparison of G-API and OpenCV substractors
+        std::size_t frames = 0u;
+        while (gapiBackSub.pull(cv::gout(frame, gapiForeground))) {
+            pOCVBackSub->apply(frame, ocvForeground, -1);
+
+            compareBackSubResults(gapiForeground, ocvForeground, diffPercent);
+
+            frames++;
+        }
+        EXPECT_LT(0u, frames);
+        EXPECT_FALSE(gapiBackSub.running());
+    }
+} // anonymous namespace
+
+TEST(StatefulKernel, StateIsInitViaCompArgsInStreaming)
+{
+    initTestDataPath();
+
+    // G-API graph declaration
+    cv::GMat in;
+    cv::GMat out = GBackSub::on(in);
+    // Preserving 'in' in output to have possibility to compare with OpenCV reference
+    cv::GComputation c(cv::GIn(in), cv::GOut(cv::gapi::copy(in), out));
+
+    // G-API compilation of graph for streaming mode
+    const auto pkg = cv::gapi::kernels<GOCVBackSub>();
+    auto gapiBackSub = c.compileStreaming(
+                           cv::compile_args(pkg, BackSubStateParams { "knn" }));
+
+    // Testing G-API Background Substractor in streaming mode
+    gapiBackSub.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>
+                               (findDataFile("cv/video/768x576.avi")));
+    // Allowing 1% difference of all pixels between G-API and reference OpenCV results
+    testBackSubInStreaming(gapiBackSub, 1);
+
+    // Additionally, test the case when the new stream happens
+    gapiBackSub.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>
+                               (findDataFile("cv/video/1920x1080.avi")));
+    // Allowing 5% difference of all pixels between G-API and reference OpenCV results
+    testBackSubInStreaming(gapiBackSub, 5);
+}
+//-------------------------------------------------------------------------------------------------------------
+
+
+//------------------------------------------- Typed tests on setup() ------------------------------------------
+namespace
+{
+template<typename Tuple>
+struct SetupStateTypedTest : public ::testing::Test
+{
+    using StateT = typename std::tuple_element<0, Tuple>::type;
+    using SetupT = typename std::tuple_element<1, Tuple>::type;
+
+    G_TYPED_KERNEL(GReturnState, <cv::GOpaque<StateT>(GMat)>, "org.opencv.test.return_state")
+    {
+        static GOpaqueDesc outMeta(GMatDesc /* in */) { return empty_gopaque_desc(); }
+    };
+
+    GAPI_OCV_KERNEL_ST(GOCVReturnState, GReturnState, StateT)
+    {
+        static void setup(const cv::GMatDesc &/* in */, std::shared_ptr<StateT> &state)
+        {
+            // Don't use input cv::GMatDesc intentionally
+            state.reset(new StateT(SetupT::value()));
+        }
+
+        static void run(const cv::Mat &/* in */, StateT &out, StateT& state)
+        {
+            out = state;
+        }
+    };
+};
+
+TYPED_TEST_CASE_P(SetupStateTypedTest);
+} // namespace
+
+
+TYPED_TEST_P(SetupStateTypedTest, ReturnInitializedState)
+{
+    using StateType = typename TestFixture::StateT;
+    using SetupType = typename TestFixture::SetupT;
+
+    cv::Mat dummyIn { 1, 1, CV_8UC1 };
+    StateType retState { };
+
+    GMat in;
+    auto out = TestFixture::GReturnState::on(in);
+    cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+
+    const auto pkg = cv::gapi::kernels<typename TestFixture::GOCVReturnState>();
+    comp.apply(cv::gin(dummyIn), cv::gout(retState), cv::compile_args(pkg));
+
+    EXPECT_EQ(SetupType::value(), retState);
+}
+
+REGISTER_TYPED_TEST_CASE_P(SetupStateTypedTest,
+                           ReturnInitializedState);
+
+
+DEFINE_INITIALIZER(CharValue, char, 'z');
+DEFINE_INITIALIZER(IntValue, int, 7);
+DEFINE_INITIALIZER(FloatValue, float, 42.f);
+DEFINE_INITIALIZER(UcharPtrValue, uchar*, nullptr);
+namespace
+{
+using Std3IntArray = std::array<int, 3>;
+}
+DEFINE_INITIALIZER(StdArrayValue, Std3IntArray, { 1, 2, 3 });
+DEFINE_INITIALIZER(UserValue, UserStruct, { 5, 7.f });
+
+using TypesToVerify = ::testing::Types<std::tuple<char, CharValue>,
+                                       std::tuple<int, IntValue>,
+                                       std::tuple<float, FloatValue>,
+                                       std::tuple<uchar*, UcharPtrValue>,
+                                       std::tuple<std::array<int, 3>, StdArrayValue>,
+                                       std::tuple<UserStruct, UserValue>>;
+
+INSTANTIATE_TYPED_TEST_CASE_P(SetupStateTypedInst, SetupStateTypedTest, TypesToVerify);
+//-------------------------------------------------------------------------------------------------------------
+
+} // opencv_test
index 1481755..df74a04 100644 (file)
@@ -11,7 +11,7 @@
 
 namespace
 {
-#define CORE_CPU [] () { return cv::compile_args(cv::gapi::core::cpu::kernels()); }
+#define CORE_CPU [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::core::cpu::kernels()}); }
 }  // anonymous namespace
 
 namespace opencv_test
@@ -23,23 +23,24 @@ INSTANTIATE_TEST_CASE_P(MathOperatorTestCPU, MathOperatorMatMatTest,
                             Values(cv::Size(1280, 720),
                                    cv::Size(640, 480),
                                    cv::Size(128, 128)),
-                            Values(-1, CV_8U, CV_32F),
+                            Values(-1),
                             Values(CORE_CPU),
                             Values(AbsExact().to_compare_obj()),
-                            Values( opPlusM, opMinusM, opDivM,
-                                    opGreater, opLess, opGreaterEq, opLessEq, opEq, opNotEq)));
+                            Values( ADD, SUB, DIV,
+                                    GT, LT, GE, LE, EQ, NE)));
 
 INSTANTIATE_TEST_CASE_P(MathOperatorTestCPU, MathOperatorMatScalarTest,
                         Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
                                        cv::Size(128, 128)),
-                                Values(-1, CV_8U, CV_32F),
+                                Values(-1),
                                 Values(CORE_CPU),
                                 Values(AbsExact().to_compare_obj()),
-                                Values( opPlus, opPlusR, opMinus, opMinusR, opMul, opMulR,  // FIXIT avoid division by values near zero: opDiv, opDivR,
-                                        opGT, opLT, opGE, opLE, opEQ, opNE,
-                                        opGTR, opLTR, opGER, opLER, opEQR, opNER)));
+                                Values( ADD,  SUB,  MUL,  DIV,
+                                        ADDR, SUBR, MULR, DIVR,
+                                        GT,  LT,  GE,  LE,  EQ,  NE,
+                                        GTR, LTR, GER, LER, EQR, NER)));
 
 INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestCPU, MathOperatorMatMatTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
@@ -49,7 +50,7 @@ INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestCPU, MathOperatorMatMatTest,
                                 Values(-1),
                                 Values(CORE_CPU),
                                 Values(AbsExact().to_compare_obj()),
-                                Values( opAnd, opOr, opXor )));
+                                Values( AND, OR, XOR )));
 
 INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestCPU, MathOperatorMatScalarTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
@@ -59,7 +60,8 @@ INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestCPU, MathOperatorMatScalarTest,
                                 Values(-1),
                                 Values(CORE_CPU),
                                 Values(AbsExact().to_compare_obj()),
-                                Values( opAND, opOR, opXOR, opANDR, opORR, opXORR )));
+                                Values( AND,  OR,  XOR,
+                                        ANDR, ORR, XORR )));
 
 INSTANTIATE_TEST_CASE_P(BitwiseNotOperatorTestCPU, NotOperatorTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
index 45c8e18..d076ecd 100644 (file)
@@ -10,7 +10,7 @@
 
 namespace
 {
-#define CORE_FLUID [] () { return cv::compile_args(cv::gapi::core::fluid::kernels()); }
+#define CORE_FLUID [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::core::fluid::kernels()}); }
 }  // anonymous namespace
 
 namespace opencv_test
@@ -21,24 +21,34 @@ INSTANTIATE_TEST_CASE_P(MathOperatorTestFluid, MathOperatorMatMatTest,
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
                                        cv::Size(128, 128)),
-                                Values(-1, CV_8U, CV_32F),
+                                Values(-1),
                                 Values(CORE_FLUID),
                                 Values(AbsExact().to_compare_obj()),
-                                Values( opPlusM, opMinusM, opDivM,
-                                        opGreater, opLess, opGreaterEq, opLessEq, opEq, opNotEq)));
+                                Values( ADD, SUB, DIV,
+                                        GT, LT, GE, LE, EQ, NE)));
 
-//FIXME: Some Mat/Scalar Fluid kernels are not there yet!
-INSTANTIATE_TEST_CASE_P(DISABLED_MathOperatorTestFluid, MathOperatorMatScalarTest,
+INSTANTIATE_TEST_CASE_P(MathOperatorArithmeticTestFluid, MathOperatorMatScalarTest,
                         Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
                                        cv::Size(128, 128)),
-                                Values(-1, CV_8U, CV_32F),
+                                Values(-1),
                                 Values(CORE_FLUID),
                                 Values(AbsExact().to_compare_obj()),
-                                Values( opPlus, opPlusR, opMinus, opMinusR, opMul, opMulR,  // FIXIT avoid division by values near zero: opDiv, opDivR,
-                                        opGT, opLT, opGE, opLE, opEQ, opNE,
-                                        opGTR, opLTR, opGER, opLER, opEQR, opNER)));
+                                Values( ADD,  SUB,  MUL,  DIV,
+                                        ADDR, SUBR, MULR, DIVR)));
+
+  // FIXME: solve comparison error
+INSTANTIATE_TEST_CASE_P(MathOperatorCompareTestFluid, MathOperatorMatScalarTest,
+                        Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480),
+                                       cv::Size(128, 128)),
+                                Values(-1),
+                                Values(CORE_FLUID),
+                                Values(AbsSimilarPoints(1, 0.01).to_compare_obj()),
+                                Values( GT,  LT,  GE,  LE,  EQ,  NE,
+                                        GTR, LTR, GER, LER, EQR, NER)));
 
 INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestFluid, MathOperatorMatMatTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
@@ -48,10 +58,9 @@ INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestFluid, MathOperatorMatMatTest,
                                 Values(-1),
                                 Values(CORE_FLUID),
                                 Values(AbsExact().to_compare_obj()),
-                                Values( opAnd, opOr, opXor )));
+                                Values( AND, OR, XOR )));
 
-//FIXME: Some Mat/Scalar Fluid kernels are not there yet!
-INSTANTIATE_TEST_CASE_P(DISABLED_BitwiseOperatorTestFluid, MathOperatorMatScalarTest,
+INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestFluid, MathOperatorMatScalarTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
@@ -59,7 +68,8 @@ INSTANTIATE_TEST_CASE_P(DISABLED_BitwiseOperatorTestFluid, MathOperatorMatScalar
                                 Values(-1),
                                 Values(CORE_FLUID),
                                 Values(AbsExact().to_compare_obj()),
-                                Values( opAND, opOR, opXOR, opANDR, opORR, opXORR )));
+                                Values( AND,  OR,  XOR,
+                                        ANDR, ORR, XORR )));
 
 INSTANTIATE_TEST_CASE_P(BitwiseNotOperatorTestFluid, NotOperatorTest,
                     Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_video_tests_cpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_video_tests_cpu.cpp
new file mode 100644 (file)
index 0000000..c4659ad
--- /dev/null
@@ -0,0 +1,100 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+
+#include "../common/gapi_video_tests.hpp"
+#include <opencv2/gapi/cpu/video.hpp>
+
+namespace
+{
+#define VIDEO_CPU [] () { return cv::compile_args(cv::gapi::video::cpu::kernels()); }
+
+#ifdef HAVE_OPENCV_VIDEO
+#define WITH_VIDEO(X) X
+#else
+#define WITH_VIDEO(X) DISABLED_##X
+#endif // HAVE_OPENCV_VIDEO
+
+#define INSTANTIATE_TEST_CASE_MACRO_P(prefix, test_case_name, generator, ...) \
+    INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, __VA_ARGS__)
+}  // anonymous namespace
+
+namespace opencv_test
+{
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidTestCPU), BuildOptFlowPyramidTest,
+                              Combine(Values(VIDEO_CPU),
+                                      Values("cv/optflow/rock_1.bmp",
+                                             "cv/optflow/frames/1080p_01.png"),
+                                      Values(7, 11),
+                                      Values(1000),
+                                      testing::Bool(),
+                                      Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
+                                      Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
+                                      testing::Bool()));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidInternalTestCPU),
+                              BuildOptFlowPyramidTest,
+                              Combine(Values(VIDEO_CPU),
+                                      Values("cv/optflow/rock_1.bmp"),
+                                      Values(15),
+                                      Values(3),
+                                      Values(true),
+                                      Values(BORDER_REFLECT_101),
+                                      Values(BORDER_CONSTANT),
+                                      Values(true)));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKTestCPU), OptFlowLKTest,
+                              Combine(Values(VIDEO_CPU),
+                                      Values("cv/optflow/rock_%01d.bmp",
+                                             "cv/optflow/frames/1080p_%02d.png"),
+                                      Values(1, 3, 4),
+                                      Values(std::make_tuple(9, 9), std::make_tuple(15, 15)),
+                                      Values(7, 11),
+                                      Values(cv::TermCriteria(cv::TermCriteria::COUNT |
+                                                              cv::TermCriteria::EPS,
+                                                              30, 0.01))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKTestForPyrCPU), OptFlowLKTestForPyr,
+                              Combine(Values(VIDEO_CPU),
+                                      Values("cv/optflow/rock_%01d.bmp",
+                                             "cv/optflow/frames/1080p_%02d.png"),
+                                      Values(1, 3, 4),
+                                      Values(std::make_tuple(9, 9), std::make_tuple(15, 15)),
+                                      Values(7, 11),
+                                      Values(cv::TermCriteria(cv::TermCriteria::COUNT |
+                                                              cv::TermCriteria::EPS,
+                                                              30, 0.01)),
+                                      testing::Bool()));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKInternalTestCPU), OptFlowLKTestForPyr,
+                              Combine(Values(VIDEO_CPU),
+                                      Values("cv/optflow/rock_%01d.bmp"),
+                                      Values(1),
+                                      Values(std::make_tuple(10, 10)),
+                                      Values(15),
+                                      Values(cv::TermCriteria(cv::TermCriteria::COUNT |
+                                                              cv::TermCriteria::EPS,
+                                                              21, 0.05)),
+                                      Values(true)));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelineTestCPU),
+                              BuildPyr_CalcOptFlow_PipelineTest,
+                              Combine(Values(VIDEO_CPU),
+                                      Values("cv/optflow/frames/1080p_%02d.png"),
+                                      Values(7, 11),
+                                      Values(1000),
+                                      testing::Bool()));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelineInternalTestCPU),
+                              BuildPyr_CalcOptFlow_PipelineTest,
+                              Combine(Values(VIDEO_CPU),
+                                      Values("cv/optflow/rock_%01d.bmp"),
+                                      Values(15),
+                                      Values(3),
+                                      Values(true)));
+} // opencv_test
index 922a2eb..2faf538 100644 (file)
@@ -28,6 +28,10 @@ G_TYPED_KERNEL(CountCorners,   <GScalar(GPointArray)>,  "test.array.in")
 {
     static GScalarDesc outMeta(const GArrayDesc &) { return empty_scalar_desc(); }
 };
+G_TYPED_KERNEL(PointIncrement, <GPointArray(GMat, GPointArray)>, "test.point_increment")
+{
+    static GArrayDesc outMeta(const GMatDesc&, const GArrayDesc&) { return empty_array_desc(); }
+};
 } // namespace ThisTest
 
 namespace
@@ -57,6 +61,15 @@ GAPI_OCV_KERNEL(OCVCountCorners, ThisTest::CountCorners)
     }
 };
 
+GAPI_OCV_KERNEL(OCVPointIncrement, ThisTest::PointIncrement)
+{
+    static void run(const cv::Mat&, const std::vector<cv::Point>& in, std::vector<cv::Point>& out)
+    {
+        for (const auto& el : in)
+            out.emplace_back(el + Point(1,1));
+    }
+};
+
 cv::Mat cross(int w, int h)
 {
     cv::Mat mat = cv::Mat::eye(h, w, CV_8UC1)*255;
@@ -164,6 +177,45 @@ TEST(GArray, TestIntermediateOutput)
     EXPECT_EQ(10,  out_count[0]);
 }
 
+TEST(GArray, GArrayConstValInitialization)
+{
+    std::vector<cv::Point> initial_vec {Point(0,0), Point(1,1), Point(2,2)};
+    std::vector<cv::Point> ref_vec     {Point(1,1), Point(2,2), Point(3,3)};
+    std::vector<cv::Point> out_vec;
+    cv::Mat in_mat;
+
+    cv::GComputationT<ThisTest::GPointArray(cv::GMat)> c([&](cv::GMat in)
+    {
+        // Initialization
+        ThisTest::GPointArray test_garray(initial_vec);
+        return ThisTest::PointIncrement::on(in, test_garray);
+    });
+    auto cc = c.compile(cv::descr_of(in_mat),
+                        cv::compile_args(cv::gapi::kernels<OCVPointIncrement>()));
+    cc(in_mat, out_vec);
+
+    EXPECT_EQ(ref_vec, out_vec);
+}
+
+TEST(GArray, GArrayRValInitialization)
+{
+    std::vector<cv::Point> ref_vec {Point(1,1), Point(2,2), Point(3,3)};
+    std::vector<cv::Point> out_vec;
+    cv::Mat in_mat;
+
+    cv::GComputationT<ThisTest::GPointArray(cv::GMat)> c([&](cv::GMat in)
+    {
+        // Rvalue initialization
+        ThisTest::GPointArray test_garray({Point(0,0), Point(1,1), Point(2,2)});
+        return ThisTest::PointIncrement::on(in, test_garray);
+    });
+    auto cc = c.compile(cv::descr_of(in_mat),
+                        cv::compile_args(cv::gapi::kernels<OCVPointIncrement>()));
+    cc(in_mat, out_vec);
+
+    EXPECT_EQ(ref_vec, out_vec);
+}
+
 TEST(GArray_VectorRef, TestMov)
 {
     // Warning: this test is testing some not-very-public APIs
@@ -187,4 +239,48 @@ TEST(GArray_VectorRef, TestMov)
     EXPECT_EQ(V{}, vref.rref<I>());
     EXPECT_EQ(V{}, vtest);
 }
+
+TEST(GArray_VectorRef, Kind)
+{
+    cv::detail::VectorRef v1(std::vector<cv::Rect>{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_RECT, v1.getKind());
+
+    cv::detail::VectorRef v2(std::vector<cv::Mat>{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_MAT,  v2.getKind());
+
+    cv::detail::VectorRef v3(std::vector<int>{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, v3.getKind());
+
+    cv::detail::VectorRef v4(std::vector<double>{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_DOUBLE, v4.getKind());
+
+    cv::detail::VectorRef v5(std::vector<cv::Scalar>{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_SCALAR, v5.getKind());
+
+    cv::detail::VectorRef v6(std::vector<cv::Point>{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_POINT, v6.getKind());
+
+    cv::detail::VectorRef v7(std::vector<cv::Size>{});
+    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());
+}
+
+TEST(GArray_VectorRef, TestRvalue)
+{
+    // Warning: this test is testing some not-very-public APIs
+    cv::detail::VectorRef vref(std::vector<int>{3, 5, -4});
+    auto v = std::vector<int>{3, 5, -4};
+    EXPECT_EQ(vref.rref<int>(), v);
+}
+
+TEST(GArray_VectorRef, TestReset)
+{
+    // Warning: this test is testing some not-very-public APIs
+    cv::detail::VectorRef vref(std::vector<int>{3, 5, -4});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, vref.getKind());
+    vref.reset<int>();
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, vref.getKind());
+}
 } // namespace opencv_test
index 3e5bec9..66b8be4 100644 (file)
@@ -386,11 +386,8 @@ namespace {
         for (auto&& arg : args){
             //FIXME: replace this switch with use of visit() on variant, when it will be available
             switch (arg.index()){
-    #if !defined(GAPI_STANDALONE)
-                case GRunArgP::index_of<cv::Mat*>()                 :   result.emplace_back(*util::get<cv::Mat*>(arg));     break;
                 case GRunArgP::index_of<cv::UMat*>()                :   result.emplace_back(*util::get<cv::UMat*>(arg));    break;
-    #endif // !defined(GAPI_STANDALONE)
-                case GRunArgP::index_of<cv::gapi::own::Mat*>()      :   result.emplace_back(*util::get<cv::gapi::own::Mat*>   (arg));   break;
+                case GRunArgP::index_of<cv::Mat*>()                 :   result.emplace_back(*util::get<cv::Mat*>(arg));     break;
                 case GRunArgP::index_of<cv::Scalar*>()              :   result.emplace_back(*util::get<cv::Scalar*>           (arg));   break;
                 case GRunArgP::index_of<cv::detail::VectorRef>()    :   result.emplace_back(util::get<cv::detail::VectorRef>  (arg));   break;
                 default : ;
@@ -403,11 +400,8 @@ namespace {
         GRunArgsP result; result.reserve(args.size());
         for (auto&& arg : args){
             switch (arg.index()){
-    #if !defined(GAPI_STANDALONE)
                 case GRunArg::index_of<cv::Mat>()                 :   result.emplace_back(&util::get<cv::Mat>(arg));     break;
                 case GRunArg::index_of<cv::UMat>()                :   result.emplace_back(&util::get<cv::UMat>(arg));    break;
-    #endif // !defined(GAPI_STANDALONE)
-                case GRunArg::index_of<cv::gapi::own::Mat>()      :   result.emplace_back(&util::get<cv::gapi::own::Mat>   (arg));   break;
                 case GRunArg::index_of<cv::Scalar>()              :   result.emplace_back(&util::get<cv::Scalar>           (arg));   break;
                 case GRunArg::index_of<cv::detail::VectorRef>()   :   result.emplace_back(util::get<cv::detail::VectorRef> (arg));   break;
                 default : ;
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_compile_args_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_compile_args_tests.cpp
new file mode 100644 (file)
index 0000000..bea1b9b
--- /dev/null
@@ -0,0 +1,75 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+namespace opencv_test
+{
+    struct CustomArg
+    {
+        int number;
+    };
+}
+
+namespace cv
+{
+    namespace detail
+    {
+        template<> struct CompileArgTag<opencv_test::CustomArg>
+        {
+            static const char* tag() { return "org.opencv.test.custom_arg"; }
+        };
+    }
+}
+
+
+namespace opencv_test
+{
+namespace
+{
+G_TYPED_KERNEL(GTestOp, <GMat(GMat)>, "org.opencv.test.test_op")
+{
+    static GMatDesc outMeta(GMatDesc in) { return in; }
+};
+
+GAPI_OCV_KERNEL(GOCVTestOp, GTestOp)
+{
+    static void run(const cv::Mat &/* in */, cv::Mat &/* out */) { }
+};
+} // anonymous namespace
+
+TEST(GetCompileArgTest, PredefinedArgs)
+{
+    cv::gapi::GKernelPackage pkg = cv::gapi::kernels<GOCVTestOp>();
+    cv::GCompileArg arg0 { pkg },
+                    arg1 { cv::gapi::use_only { pkg } },
+                    arg2 { cv::graph_dump_path { "fake_path" } };
+
+    GCompileArgs compArgs { arg0, arg1, arg2 };
+
+    auto kernelPkgOpt = cv::gapi::getCompileArg<cv::gapi::GKernelPackage>(compArgs);
+    GAPI_Assert(kernelPkgOpt.has_value());
+    EXPECT_NO_THROW(kernelPkgOpt.value().lookup("org.opencv.test.test_op"));
+
+    auto hasUseOnlyOpt = cv::gapi::getCompileArg<cv::gapi::use_only>(compArgs);
+    GAPI_Assert(hasUseOnlyOpt.has_value());
+    EXPECT_NO_THROW(hasUseOnlyOpt.value().pkg.lookup("org.opencv.test.test_op"));
+
+    auto dumpInfoOpt = cv::gapi::getCompileArg<cv::graph_dump_path>(compArgs);
+    GAPI_Assert(dumpInfoOpt.has_value());
+    EXPECT_EQ("fake_path", dumpInfoOpt.value().m_dump_path);
+}
+
+TEST(GetCompileArg, CustomArgs)
+{;
+    cv::GCompileArgs compArgs{ GCompileArg { CustomArg { 7 } } };
+
+    auto customArgOpt = cv::gapi::getCompileArg<CustomArg>(compArgs);
+    GAPI_Assert(customArgOpt.has_value());
+    EXPECT_EQ(7, customArgOpt.value().number);
+}
+} // namespace opencv_test
index 65d66d6..1eae722 100644 (file)
@@ -23,23 +23,30 @@ namespace
     };
 }
 
-TEST(GAPI_MetaDesc, MatDesc)
-{
-    cv::Mat m1(240, 320, CV_8U);
-    const auto desc1 = cv::descr_of(m1);
-    EXPECT_EQ(CV_8U, desc1.depth);
-    EXPECT_EQ(1,     desc1.chan);
-    EXPECT_EQ(320,   desc1.size.width);
-    EXPECT_EQ(240,   desc1.size.height);
-    EXPECT_FALSE(desc1.isND());
-
-    cv::Mat m2(480, 640, CV_8UC3);
-    const auto desc2 = cv::descr_of(m2);
-    EXPECT_EQ(CV_8U, desc2.depth);
-    EXPECT_EQ(3,       desc2.chan);
-    EXPECT_EQ(640,     desc2.size.width);
-    EXPECT_EQ(480,     desc2.size.height);
-    EXPECT_FALSE(desc2.isND());
+TEST(GAPI_MetaDesc, MatDescOneCh)
+{
+    cv::Mat mat(240, 320, CV_8U);
+
+    const auto desc = cv::descr_of(mat);
+
+    EXPECT_EQ(CV_8U, desc.depth);
+    EXPECT_EQ(1,     desc.chan);
+    EXPECT_EQ(320,   desc.size.width);
+    EXPECT_EQ(240,   desc.size.height);
+    EXPECT_FALSE(desc.isND());
+}
+
+TEST(GAPI_MetaDesc, MatDescThreeCh)
+{
+    cv::Mat mat(480, 640, CV_8UC3);
+
+    const auto desc = cv::descr_of(mat);
+
+    EXPECT_EQ(CV_8U,   desc.depth);
+    EXPECT_EQ(3,       desc.chan);
+    EXPECT_EQ(640,     desc.size.width);
+    EXPECT_EQ(480,     desc.size.height);
+    EXPECT_FALSE(desc.isND());
 }
 
 TEST(GAPI_MetaDesc, MatDescND)
@@ -71,6 +78,65 @@ TEST(GAPI_MetaDesc, VecMatDesc)
     EXPECT_EQ((GMatDesc{CV_8U, 3, {640, 480}}), get<GMatDesc>(desc2[0]));
 }
 
+TEST(GAPI_MetaDesc, CanDescribe)
+{
+    constexpr int w = 15;
+    constexpr int h = 7;
+    cv::Mat m0(h, w, CV_8UC3);
+    cv::GMatDesc md0{CV_8U,3,{w,h},false};
+
+    cv::Mat m1(h*3, w, CV_8UC1);
+    cv::GMatDesc md10{CV_8U,3,{w,h},true};
+    cv::GMatDesc md11{CV_8U,1,{w,h*3},false};
+
+    EXPECT_TRUE (md0 .canDescribe(m0));
+    EXPECT_FALSE(md0 .canDescribe(m1));
+    EXPECT_TRUE (md10.canDescribe(m1));
+    EXPECT_TRUE (md11.canDescribe(m1));
+}
+
+TEST(GAPI_MetaDesc, OwnMatDescOneCh)
+{
+    cv::gapi::own::Mat mat(240, 320, CV_8U, nullptr);
+
+    const auto desc = cv::gapi::own::descr_of(mat);
+
+    EXPECT_EQ(CV_8U, desc.depth);
+    EXPECT_EQ(1,     desc.chan);
+    EXPECT_EQ(320,   desc.size.width);
+    EXPECT_EQ(240,   desc.size.height);
+    EXPECT_FALSE(desc.isND());
+}
+
+TEST(GAPI_MetaDesc, OwnMatDescThreeCh)
+{
+    cv::gapi::own::Mat mat(480, 640, CV_8UC3, nullptr);
+
+    const auto desc = cv::gapi::own::descr_of(mat);
+
+    EXPECT_EQ(CV_8U,   desc.depth);
+    EXPECT_EQ(3,       desc.chan);
+    EXPECT_EQ(640,     desc.size.width);
+    EXPECT_EQ(480,     desc.size.height);
+    EXPECT_FALSE(desc.isND());
+}
+
+TEST(GAPI_MetaDesc, OwnMatDescND)
+{
+    std::vector<int> dims = {1,3,224,224};
+    cv::gapi::own::Mat m(dims, CV_32F, nullptr);
+
+    const auto desc = cv::gapi::own::descr_of(m);
+
+    EXPECT_EQ(CV_32F, desc.depth);
+    EXPECT_EQ(-1,     desc.chan);
+    EXPECT_EQ(1,      desc.dims[0]);
+    EXPECT_EQ(3,      desc.dims[1]);
+    EXPECT_EQ(224,    desc.dims[2]);
+    EXPECT_EQ(224,    desc.dims[3]);
+    EXPECT_TRUE(desc.isND());
+}
+
 TEST(GAPI_MetaDesc, VecOwnMatDesc)
 {
     std::vector<cv::gapi::own::Mat> vec = {
@@ -78,6 +144,7 @@ TEST(GAPI_MetaDesc, VecOwnMatDesc)
     cv::gapi::own::Mat(480, 640, CV_8UC3, nullptr)};
 
     const auto desc = cv::gapi::own::descrs_of(vec);
+
     EXPECT_EQ((GMatDesc{CV_8U, 1, {320, 240}}), get<GMatDesc>(desc[0]));
     EXPECT_EQ((GMatDesc{CV_8U, 3, {640, 480}}), get<GMatDesc>(desc[1]));
 }
@@ -89,6 +156,7 @@ TEST(GAPI_MetaDesc, AdlVecOwnMatDesc)
     cv::gapi::own::Mat(480, 640, CV_8UC3, nullptr)};
 
     const auto desc = descrs_of(vec);
+
     EXPECT_EQ((GMatDesc{CV_8U, 1, {320, 240}}), get<GMatDesc>(desc[0]));
     EXPECT_EQ((GMatDesc{CV_8U, 3, {640, 480}}), get<GMatDesc>(desc[1]));
 }
@@ -333,21 +401,4 @@ TEST(GAPI_MetaDesc, Compare_asPlanarTransform)
     EXPECT_TRUE(desc1.asPlanar(3) == desc0);
 }
 
-TEST(GAPI_MetaDesc, CanDescribe)
-{
-    constexpr int w = 15;
-    constexpr int h = 7;
-    cv::Mat m0(h, w, CV_8UC3);
-    cv::GMatDesc md0{CV_8U,3,{w,h},false};
-
-    cv::Mat m1(h*3, w, CV_8UC1);
-    cv::GMatDesc md10{CV_8U,3,{w,h},true};
-    cv::GMatDesc md11{CV_8U,1,{w,h*3},false};
-
-    EXPECT_TRUE (md0 .canDescribe(m0));
-    EXPECT_FALSE(md0 .canDescribe(m1));
-    EXPECT_TRUE (md10.canDescribe(m1));
-    EXPECT_TRUE (md11.canDescribe(m1));
-}
-
 } // namespace opencv_test
index 07646e0..1178223 100644 (file)
@@ -50,7 +50,7 @@ TEST(FluidBuffer, InputTest)
     const cv::Size buffer_size = {8,8};
     cv::Mat in_mat = cv::Mat::eye(buffer_size, CV_8U);
 
-    cv::gapi::fluid::Buffer buffer(to_own(in_mat), true);
+    cv::gapi::fluid::Buffer buffer(in_mat, true);
     cv::gapi::fluid::View  view = buffer.mkView(0, false);
     view.priv().allocate(1, {});
     view.priv().reset(1);
@@ -155,7 +155,7 @@ TEST(FluidBuffer, OutputTest)
     const cv::Size buffer_size = {8,16};
     cv::Mat out_mat = cv::Mat(buffer_size, CV_8U);
 
-    cv::gapi::fluid::Buffer buffer(to_own(out_mat), false);
+    cv::gapi::fluid::Buffer buffer(out_mat, false);
     int num_writes = 0;
     while (num_writes < buffer_size.height)
     {
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_frame_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_frame_tests.cpp
new file mode 100644 (file)
index 0000000..04fa21e
--- /dev/null
@@ -0,0 +1,56 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include "test_precomp.hpp"
+
+#include <opencv2/gapi/cpu/gcpukernel.hpp>
+
+namespace opencv_test
+{
+
+G_API_OP(GBlurFrame, <GMat(GFrame)>, "test.blur_frame") {
+    static GMatDesc outMeta(GMatDesc in) {
+        return in;
+    }
+};
+
+GAPI_OCV_KERNEL(OCVBlurFrame, GBlurFrame) {
+    static void run(const cv::Mat& in, cv::Mat& out) {
+        cv::blur(in, out, cv::Size{3,3});
+    }
+};
+
+struct GFrameTest : public ::testing::Test {
+    cv::Size sz{32,32};
+    cv::Mat in_mat;
+    cv::Mat out_mat;
+    cv::Mat out_mat_ocv;
+
+    GFrameTest()
+        : in_mat(cv::Mat(sz, CV_8UC1))
+        , out_mat(cv::Mat::zeros(sz, CV_8UC1))
+        , out_mat_ocv(cv::Mat::zeros(sz, CV_8UC1)) {
+        cv::randn(in_mat, cv::Scalar::all(127.0f), cv::Scalar::all(40.f));
+        cv::blur(in_mat, out_mat_ocv, cv::Size{3,3});
+    }
+
+    void check() {
+        EXPECT_EQ(0, cvtest::norm(out_mat, out_mat_ocv, NORM_INF));
+    }
+};
+
+TEST_F(GFrameTest, Input) {
+    cv::GFrame in;
+    auto out = GBlurFrame::on(in);
+    cv::GComputation c(cv::GIn(in), cv::GOut(out));
+
+    auto pkg = cv::gapi::kernels<OCVBlurFrame>();
+    c.apply(cv::gin(in_mat), cv::gout(out_mat), cv::compile_args(pkg));
+
+    check();
+}
+
+} // namespace opencv_test
index 21c6208..d57e251 100644 (file)
@@ -100,7 +100,7 @@ namespace
         GAPI_FLUID_KERNEL(GClone, I::GClone, false)
         {
             static const int Window = 1;
-            static void run(const cv::gapi::fluid::View&, cv::gapi::fluid::Buffer)
+            static void run(const cv::gapi::fluid::View&, cv::gapi::fluid::Buffer&)
             {
                 HeteroGraph::registerCallKernel(KernelTags::FLUID_CUSTOM_CLONE);
             }
index 07e483f..c76c97a 100644 (file)
@@ -146,6 +146,26 @@ TEST(GOpaque, TestOpaqueBetween)
     EXPECT_EQ(painted, 77);
 }
 
+TEST(GOpaque, TestOpaqueBetweenIslands)
+{
+    cv::Size sz = {50, 50};
+    int depth = CV_8U;
+    int chan = 1;
+    cv::Mat mat_in = cv::Mat::zeros(sz, CV_MAKETYPE(depth, chan));
+    cv::Mat mat_out = cv::Mat::zeros(sz, CV_MAKETYPE(depth, chan));
+
+    cv::GMat in, out;
+    auto betw = ThisTest::GeneratePoint::on(in);
+    out = ThisTest::PaintPoint::on(betw, depth, chan, sz);
+
+    cv::gapi::island("test", cv::GIn(in), cv::GOut(betw));
+    cv::GComputation c(cv::GIn(in), cv::GOut(out));
+    c.apply(cv::gin(mat_in), cv::gout(mat_out), cv::compile_args(cv::gapi::kernels<OCVGeneratePoint, OCVPaintPoint>()));
+
+    int painted = mat_out.at<uint8_t>(42, 42);
+    EXPECT_EQ(painted, 77);
+}
+
 TEST(GOpaque, TestOpaqueCustomOut2)
 {
     cv::Mat input1 = cv::Mat(52, 52, CV_8U);
@@ -194,4 +214,34 @@ TEST(GOpaque_OpaqueRef, TestMov)
     EXPECT_EQ(test, ref.rref<I>());         // ref = test
     EXPECT_NE(test, mov.rref<I>());         // ref lost the data
 }
+
+TEST(GOpaque_OpaqueRef, Kind)
+{
+    cv::detail::OpaqueRef v1(cv::Rect{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_RECT, v1.getKind());
+
+    cv::detail::OpaqueRef v3(int{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, v3.getKind());
+
+    cv::detail::OpaqueRef v4(double{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_DOUBLE, v4.getKind());
+
+    cv::detail::OpaqueRef v6(cv::Point{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_POINT, v6.getKind());
+
+    cv::detail::OpaqueRef v7(cv::Size{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_SIZE, v7.getKind());
+
+    cv::detail::OpaqueRef v8(std::string{});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v8.getKind());
+}
+
+TEST(GOpaque_OpaqueRef, TestReset)
+{
+    // Warning: this test is testing some not-very-public APIs
+    cv::detail::OpaqueRef opref(int{42});
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, opref.getKind());
+    opref.reset<int>();
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, opref.getKind());
+}
 } // namespace opencv_test
index a090c99..56306b0 100644 (file)
@@ -5,8 +5,6 @@
 // Copyright (C) 2019 Intel Corporation
 
 
-#ifdef HAVE_PLAIDML
-
 #include "test_precomp.hpp"
 
 #include <stdexcept>
@@ -19,6 +17,8 @@
 namespace opencv_test
 {
 
+#ifdef HAVE_PLAIDML
+
 inline cv::gapi::plaidml::config getConfig()
 {
     auto read_var_from_env = [](const char* env)
@@ -173,6 +173,13 @@ TEST(GAPI_PlaidML_Pipelines, TwoOutputOperations)
     EXPECT_EQ(0, cv::norm(out_mat[1], ref_mat[1]));
 }
 
-} // namespace opencv_test
+#else // HAVE_PLAIDML
+
+TEST(GAPI_PlaidML_Pipelines, ThrowIfPlaidMLNotFound)
+{
+    ASSERT_ANY_THROW(cv::gapi::core::plaidml::kernels());
+}
 
 #endif // HAVE_PLAIDML
+
+} // namespace opencv_test
index c530a01..b4d9f3e 100644 (file)
@@ -327,21 +327,6 @@ TEST(GAPI_Pipeline, PipelineAllocatingKernel)
     EXPECT_THROW(comp.apply(in_mat, out_mat, cv::compile_args(pkg)), std::logic_error);
 }
 
-TEST(GAPI_Pipeline, CanUseOwnMatAsOutput)
-{
-    cv::GMat in;
-    cv::GComputation comp(in, cv::gapi::bitwise_not(in));
-
-    cv::Mat in_mat(3, 3, CV_8UC1);
-    cv::Mat out_mat(3, 3, CV_8UC1);
-
-    cv::gapi::own::Mat in_own_mat(in_mat.rows, in_mat.cols, CV_8UC1, in_mat.data);
-    cv::gapi::own::Mat out_own_mat(out_mat.rows, out_mat.cols, CV_8UC1, out_mat.data);
-
-    // FIXME add overload for apply(cv::gapi::own::Mat in, cv::gapi::own::Mat& out)
-    EXPECT_NO_THROW(comp.apply({in_own_mat}, {out_own_mat}));
-}
-
 TEST(GAPI_Pipeline, CreateKernelImplFromLambda)
 {
     cv::Size size(300, 300);
index ad1a6aa..4077008 100644 (file)
@@ -198,7 +198,7 @@ TEST(KernelPackageTransform, gmat_gsc_garray_in_gmat2_out)
     auto tr = gmat_gsc_garray_in_gmat2_out::transformation();
 
     auto check = [](const cv::GComputation &comp){
-        const auto &p = comp.priv();
+        const auto &p = cv::util::get<cv::GComputation::Priv::Expr>(comp.priv().m_shape);
         EXPECT_EQ(3u, p.m_ins.size());
         EXPECT_EQ(2u, p.m_outs.size());
 
@@ -221,7 +221,7 @@ TEST(KernelPackageTransform, gmat_gsc_gopaque_in_gmat2_out)
     auto tr = gmat_gsc_gopaque_in_gmat2_out::transformation();
 
     auto check = [](const cv::GComputation &comp){
-        const auto &p = comp.priv();
+        const auto &p = cv::util::get<cv::GComputation::Priv::Expr>(comp.priv().m_shape);
         EXPECT_EQ(3u, p.m_ins.size());
         EXPECT_EQ(2u, p.m_outs.size());
 
@@ -270,7 +270,7 @@ namespace
     template<typename InType, typename OutType>
     void args_check(const cv::GComputation &comp)
     {
-        const auto &p = comp.priv();
+        const auto &p = cv::util::get<cv::GComputation::Priv::Expr>(comp.priv().m_shape);
         EXPECT_EQ(1u, p.m_ins.size());
         EXPECT_EQ(1u, p.m_outs.size());
         arg_check<InType>(p.m_ins[0]);
index c811cef..97de39f 100644 (file)
@@ -7,6 +7,45 @@
 
 #include "test_precomp.hpp"
 
+#include "common/gapi_tests_common.hpp"
+
+namespace custom
+{
+G_TYPED_KERNEL(GKernelForGArrayGMatOut, <cv::GArray<cv::GMat>(cv::GMat)>,
+               "custom.test.kernelForGArrayGMatOut")
+{
+    static cv::GArrayDesc outMeta(const cv::GMatDesc&)
+    {
+        return cv::empty_array_desc();
+    }
+};
+
+GAPI_OCV_KERNEL(GCPUKernelForGArrayGMatOut, custom::GKernelForGArrayGMatOut)
+{
+    static void run(const cv::Mat &src, std::vector<cv::Mat> &out)
+    {
+        out[0] = src.clone();
+    }
+};
+
+G_TYPED_KERNEL(GSizeOfVectorGMat, <cv::GOpaque<size_t>(cv::GArray<cv::GMat>)>,
+               "custom.test.sizeOfVectorGMat")
+{
+    static cv::GOpaqueDesc outMeta(const cv::GArrayDesc&)
+    {
+        return cv::empty_gopaque_desc();
+    }
+};
+
+GAPI_OCV_KERNEL(GCPUSizeOfVectorGMat, custom::GSizeOfVectorGMat)
+{
+    static void run(const std::vector<cv::Mat> &src, size_t &out)
+    {
+        out = src.size();
+    }
+};
+}
+
 namespace opencv_test
 {
 
@@ -94,7 +133,6 @@ TEST(GAPI_Typed, BinaryOp)
     EXPECT_EQ(0, cvtest::norm(out_mat_cv, out_mat_typed2, NORM_INF));
 }
 
-
 TEST(GAPI_Typed, MultipleOuts)
 {
     // Initialization //////////////////////////////////////////////////////////
@@ -147,4 +185,84 @@ TEST(GAPI_Typed, MultipleOuts)
     EXPECT_EQ(0, cvtest::norm(out_mat_cv2, out_mat_comp2, NORM_INF));
 }
 
+TEST(GAPI_Typed, GArrayGMatOut)
+{
+    // Initialization //////////////////////////////////////////////////////////
+    const cv::Size sz(32, 32);
+    cv::Mat in_mat(sz, CV_8UC3);
+    std::vector<cv::Mat> out_vec_mat_untyped(1),
+                         out_vec_mat_typed1 (1),
+                         out_vec_mat_typed2 (1),
+                         out_vec_mat_cv     (1);
+    cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar::all(255));
+
+    auto customKernel = cv::gapi::kernels<custom::GCPUKernelForGArrayGMatOut>();
+    auto absExactCompare = AbsExact().to_compare_f();
+
+    // Untyped G-API ///////////////////////////////////////////////////////////
+    cv::GComputation cptU([]()
+    {
+        cv::GMat in;
+        cv::GArray<cv::GMat> out = custom::GKernelForGArrayGMatOut::on(in);
+        return cv::GComputation(cv::GIn(in), cv::GOut(out));
+    });
+    cptU.apply(cv::gin(in_mat), cv::gout(out_vec_mat_untyped), cv::compile_args(customKernel));
+
+    // Typed G-API /////////////////////////////////////////////////////////////
+    cv::GComputationT<cv::GArray<cv::GMat> (cv::GMat)> cptT(custom::GKernelForGArrayGMatOut::on);
+    auto cplT = cptT.compile(cv::descr_of(in_mat), cv::compile_args(customKernel));
+
+    cptT.apply(in_mat, out_vec_mat_typed1, cv::compile_args(customKernel));
+    cplT(in_mat, out_vec_mat_typed2);
+
+    // Plain OpenCV ////////////////////////////////////////////////////////////
+    out_vec_mat_cv[0] = in_mat.clone();
+
+    // Comparison //////////////////////////////////////////////////////////////
+    EXPECT_TRUE(absExactCompare(out_vec_mat_cv[0], out_vec_mat_untyped[0]));
+    EXPECT_TRUE(absExactCompare(out_vec_mat_cv[0], out_vec_mat_typed1 [0]));
+    EXPECT_TRUE(absExactCompare(out_vec_mat_cv[0], out_vec_mat_typed2 [0]));
+}
+
+TEST(GAPI_Typed, GArrayGMatIn)
+{
+    // Initialization //////////////////////////////////////////////////////////
+    const cv::Size sz(32, 32);
+    size_t vectorSize = 5;
+
+    cv::Mat in_mat (sz, CV_8UC3);
+    size_t out_size_t_untyped, out_size_t_typed1, out_size_t_typed2, out_size_t_cv;
+
+    cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar::all(255));
+    std::vector<cv::Mat> in_vec(vectorSize);
+    for (size_t i = 0; i < vectorSize; i++)
+        in_vec[i] = in_mat.clone();
+
+    auto customKernel = cv::gapi::kernels<custom::GCPUSizeOfVectorGMat>();
+
+    // Untyped G-API ///////////////////////////////////////////////////////////
+    cv::GComputation cptU([]()
+    {
+        cv::GArray<cv::GMat> in;
+        cv::GOpaque<size_t> out = custom::GSizeOfVectorGMat::on(in);
+        return cv::GComputation(cv::GIn(in), cv::GOut(out));
+    });
+    cptU.apply(cv::gin(in_vec), cv::gout(out_size_t_untyped), cv::compile_args(customKernel));
+
+    // Typed G-API /////////////////////////////////////////////////////////////
+    cv::GComputationT<cv::GOpaque<size_t> (cv::GArray<cv::GMat>)> cptT(custom::GSizeOfVectorGMat::on);
+    auto cplT = cptT.compile(cv::descr_of(in_vec), cv::compile_args(customKernel));
+
+    cptT.apply(in_vec, out_size_t_typed1, cv::compile_args(customKernel));
+    cplT(in_vec, out_size_t_typed2);
+
+    // Plain OpenCV ////////////////////////////////////////////////////////////
+    out_size_t_cv = in_vec.size();
+
+    // Comparison //////////////////////////////////////////////////////////////
+    EXPECT_TRUE(out_size_t_cv      == vectorSize);
+    EXPECT_TRUE(out_size_t_untyped == vectorSize);
+    EXPECT_TRUE(out_size_t_typed1  == vectorSize);
+    EXPECT_TRUE(out_size_t_typed2  == vectorSize);
+}
 } // opencv_test
index eec93ea..35daed7 100644 (file)
@@ -10,7 +10,7 @@
 
 namespace
 {
-#define CORE_GPU [] () { return cv::compile_args(cv::gapi::core::gpu::kernels()); }
+#define CORE_GPU [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::core::gpu::kernels()}); }
 }  // anonymous namespace
 
 namespace opencv_test
@@ -53,7 +53,17 @@ INSTANTIATE_TEST_CASE_P(SubTestGPU, MathOpTest,
                                 Values (1.0),
                                 testing::Bool()));
 
-INSTANTIATE_TEST_CASE_P(DivTestGPU, MathOpTest,
+// FIXME: Accuracy test for DIV math operation fails on CV_8UC3 HD input cv::Mat, double-presicion
+//        input cv::Scalar and CV_16U output cv::Mat when we also test reverse operation on Mac.
+//        Accuracy test for DIV math operation fails on CV_8UC3 VGA input cv::Mat, double-presicion
+//        input cv::Scalar and output cv::Mat having the SAME depth as input one when we also test
+//        reverse operation on Mac.
+//        It is oddly, but test doesn't fail if we have VGA CV_8UC3 input cv::Mat, double-precision
+//        input cv::Scalar and output cv::Mat having explicitly specified CV_8U depth when we also
+//        test reverse operation on Mac.
+//        As failures are sporadic, disabling all instantiation cases for DIV operation.
+//        Github ticket: https://github.com/opencv/opencv/issues/18373.
+INSTANTIATE_TEST_CASE_P(DISABLED_DivTestGPU, MathOpTest,
                         Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
@@ -98,14 +108,13 @@ INSTANTIATE_TEST_CASE_P(MeanTestGPU, MeanTest,
                                 Values(CORE_GPU)));
 
 //TODO: mask test doesn't work
-#if 0
-INSTANTIATE_TEST_CASE_P(MaskTestGPU, MaskTest,
+INSTANTIATE_TEST_CASE_P(DISABLED_MaskTestGPU, MaskTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
                                        cv::Size(128, 128)),
+                                Values(-1),
                                 Values(CORE_GPU)));
-#endif
 
 INSTANTIATE_TEST_CASE_P(SelectTestGPU, SelectTest,
                         Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
@@ -139,7 +148,8 @@ INSTANTIATE_TEST_CASE_P(CompareTestGPU, CmpTest,
                                 Values(CV_8U),
                                 Values(CORE_GPU),
                                 Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
-                                testing::Bool()));
+                                testing::Bool(),
+                                Values(AbsExact().to_compare_obj())));
 
 INSTANTIATE_TEST_CASE_P(BitwiseTestGPU, BitwiseTest,
                         Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
@@ -148,7 +158,8 @@ INSTANTIATE_TEST_CASE_P(BitwiseTestGPU, BitwiseTest,
                                        cv::Size(128, 128)),
                                 Values(-1),
                                 Values(CORE_GPU),
-                                Values(AND, OR, XOR)));
+                                Values(AND, OR, XOR),
+                                testing::Bool()));
 
 INSTANTIATE_TEST_CASE_P(BitwiseNotTestGPU, NotTest,
                         Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
@@ -158,7 +169,7 @@ INSTANTIATE_TEST_CASE_P(BitwiseNotTestGPU, NotTest,
                                 Values(-1),
                                 Values(CORE_GPU)));
 
-INSTANTIATE_TEST_CASE_P(MinTestGPU, MinTest,
+INSTANTIATE_TEST_CASE_P(DISABLED_MinTestGPU, MinTest,
                         Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
@@ -166,7 +177,7 @@ INSTANTIATE_TEST_CASE_P(MinTestGPU, MinTest,
                                 Values(-1),
                                 Values(CORE_GPU)));
 
-INSTANTIATE_TEST_CASE_P(MaxTestGPU, MaxTest,
+INSTANTIATE_TEST_CASE_P(DISABLED_MaxTestGPU, MaxTest,
                         Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
@@ -415,19 +426,19 @@ INSTANTIATE_TEST_CASE_P(ReInitOutTestGPU, ReInitOutTest,
                                        cv::Size(10, 480))));
 
 //TODO: fix this backend to allow ConcatVertVec ConcatHorVec
-#if 0
-INSTANTIATE_TEST_CASE_P(ConcatVertVecTestGPU, ConcatVertVecTest,
+INSTANTIATE_TEST_CASE_P(DISABLED_ConcatVertVecTestGPU, ConcatVertVecTest,
                         Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
                                        cv::Size(128, 128)),
+                                Values(-1),
                                 Values(CORE_GPU)));
 
-INSTANTIATE_TEST_CASE_P(ConcatHorVecTestGPU, ConcatHorVecTest,
+INSTANTIATE_TEST_CASE_P(DISABLED_ConcatHorVecTestGPU, ConcatHorVecTest,
                         Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
                                        cv::Size(128, 128)),
+                                Values(-1),
                                 Values(CORE_GPU)));
-#endif
 }
index 7f99e74..7d9bd76 100644 (file)
@@ -11,7 +11,7 @@
 
 namespace
 {
-#define IMGPROC_GPU [] () { return cv::compile_args(cv::gapi::imgproc::gpu::kernels()); }
+#define IMGPROC_GPU [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::imgproc::gpu::kernels()}); }
 }  // anonymous namespace
 
 namespace opencv_test
@@ -152,6 +152,29 @@ INSTANTIATE_TEST_CASE_P(SobelTestGPU32F, SobelTest,
                                 Values(0, 1),
                                 Values(1, 2)));
 
+INSTANTIATE_TEST_CASE_P(LaplacianTestGPU, LaplacianTest,
+                        Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480)),
+                                Values(-1),
+                                Values(IMGPROC_GPU),
+                                Values(Tolerance_FloatRel_IntAbs(1e-4, 2).to_compare_obj()),
+                                Values(5),
+                                Values(3.0),
+                                Values(BORDER_DEFAULT)));
+
+INSTANTIATE_TEST_CASE_P(BilateralFilterTestGPU, BilateralFilterTest,
+                        Combine(Values(CV_32FC1, CV_32FC3, CV_8UC1, CV_8UC3),
+                                Values(cv::Size(1280, 720),
+                                       cv::Size(640, 480)),
+                                Values(-1),
+                                Values(IMGPROC_GPU),
+                                Values(Tolerance_FloatRel_IntAbs(1e-4, 2).to_compare_obj()),
+                                Values(9),
+                                Values(100),
+                                Values(40),
+                                Values(BORDER_DEFAULT)));
+
 INSTANTIATE_TEST_CASE_P(EqHistTestGPU, EqHistTest,
                         Combine(Values(CV_8UC1),
                                 Values(cv::Size(1280, 720),
index a939d32..46a2155 100644 (file)
@@ -10,7 +10,7 @@
 
 namespace
 {
-#define CORE_GPU [] () { return cv::compile_args(cv::gapi::core::gpu::kernels()); }
+#define CORE_GPU [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::core::gpu::kernels()}); }
 }  // anonymous namespace
 
 namespace opencv_test
@@ -21,23 +21,24 @@ INSTANTIATE_TEST_CASE_P(MathOperatorTestGPU, MathOperatorMatMatTest,
                             Values(cv::Size(1280, 720),
                                    cv::Size(640, 480),
                                    cv::Size(128, 128)),
-                            Values(-1, CV_8U, CV_32F),
+                            Values(-1),
                             Values(CORE_GPU),
                             Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_obj()),
-                            Values( opPlusM, opMinusM, opDivM,
-                                    opGreater, opLess, opGreaterEq, opLessEq, opEq, opNotEq)));
+                            Values( ADD, SUB, DIV,
+                                    GT, LT, GE, LE, EQ, NE)));
 
 INSTANTIATE_TEST_CASE_P(MathOperatorTestGPU, MathOperatorMatScalarTest,
                         Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
                                 Values(cv::Size(1280, 720),
                                        cv::Size(640, 480),
                                        cv::Size(128, 128)),
-                                Values(-1, CV_8U, CV_32F),
+                                Values(-1),
                                 Values(CORE_GPU),
                                 Values(Tolerance_FloatRel_IntAbs(1e-4, 2).to_compare_obj()),
-                                Values( opPlus, opPlusR, opMinus, opMinusR, opMul, opMulR,  // FIXIT avoid division by values near zero: opDiv, opDivR,
-                                        opGT, opLT, opGE, opLE, opEQ, opNE,
-                                        opGTR, opLTR, opGER, opLER, opEQR, opNER)));
+                                Values( ADD,  SUB,  MUL,  DIV,
+                                        ADDR, SUBR, MULR, DIVR,
+                                        GT,  LT,  GE,  LE,  EQ,  NE,
+                                        GTR, LTR, GER, LER, EQR, NER)));
 
 INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestGPU, MathOperatorMatMatTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
@@ -47,7 +48,7 @@ INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestGPU, MathOperatorMatMatTest,
                                 Values(-1),
                                 Values(CORE_GPU),
                                 Values(AbsExact().to_compare_obj()),
-                                Values( opAnd, opOr, opXor )));
+                                Values( AND, OR, XOR )));
 
 INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestGPU, MathOperatorMatScalarTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
@@ -57,7 +58,8 @@ INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestGPU, MathOperatorMatScalarTest,
                                 Values(-1),
                                 Values(CORE_GPU),
                                 Values(AbsExact().to_compare_obj()),
-                                Values( opAND, opOR, opXOR, opANDR, opORR, opXORR )));
+                                Values( AND,  OR,  XOR,
+                                        ANDR, ORR, XORR )));
 
 INSTANTIATE_TEST_CASE_P(BitwiseNotOperatorTestGPU, NotOperatorTest,
                         Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
index d81285f..b584f5b 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2019 Intel Corporation
+// Copyright (C) 2019-2020 Intel Corporation
 
 #include "../test_precomp.hpp"
 
 
 #include <stdexcept>
 
-////////////////////////////////////////////////////////////////////////////////
-// FIXME: Suppress deprecation warnings for OpenVINO 2019R2+
-// BEGIN {{{
-#if defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-#ifdef _MSC_VER
-#pragma warning(disable: 4996)  // was declared deprecated
-#endif
-
-#if defined(__GNUC__)
-#pragma GCC visibility push(default)
-#endif
-
 #include <inference_engine.hpp>
 
-#if defined(__GNUC__)
-#pragma GCC visibility pop
-#endif
-// END }}}
-////////////////////////////////////////////////////////////////////////////////
-
 #include <ade/util/iota_range.hpp>
 
 #include <opencv2/gapi/infer/ie.hpp>
 
 #include "backends/ie/util.hpp"
+#include "backends/ie/giebackend/giewrapper.hpp"
 
 namespace opencv_test
 {
@@ -75,6 +56,53 @@ void normAssert(cv::InputArray ref, cv::InputArray test,
     EXPECT_LE(normInf, lInf) << comment;
 }
 
+std::vector<std::string> modelPathByName(const std::string &model_name) {
+    // Handle OMZ model layout changes among OpenVINO versions here
+    static const std::unordered_multimap<std::string, std::string> map = {
+#if INF_ENGINE_RELEASE >= 2019040000  // >= 2019.R4
+        {"age-gender-recognition-retail-0013",
+         "2020.3.0/intel/age-gender-recognition-retail-0013/FP32"},
+#endif // INF_ENGINE_RELEASE >= 2019040000
+        {"age-gender-recognition-retail-0013",
+         "Retail/object_attributes/age_gender/dldt"},
+    };
+    const auto range = map.equal_range(model_name);
+    std::vector<std::string> result;
+    for (auto it = range.first; it != range.second; ++it) {
+        result.emplace_back(it->second);
+    }
+    return result;
+}
+
+std::tuple<std::string, std::string> findModel(const std::string &model_name) {
+    const auto candidates = modelPathByName(model_name);
+    CV_Assert(!candidates.empty() && "No model path candidates found at all");
+
+    for (auto &&path : candidates) {
+        std::string model_xml, model_bin;
+        try {
+            model_xml = findDataFile(path + "/" + model_name + ".xml", false);
+            model_bin = findDataFile(path + "/" + model_name + ".bin", false);
+            // Return the first file which actually works
+            return std::make_tuple(model_xml, model_bin);
+        } catch (SkipTestException&) {
+            // This is quite ugly but it is a way for OpenCV to let us know
+            // this file wasn't found.
+            continue;
+        }
+    }
+
+    // Default behavior if reached here.
+    throw SkipTestException("Files for " + model_name + " were not found");
+}
+
+namespace IE = InferenceEngine;
+
+void setNetParameters(IE::CNNNetwork& net) {
+    auto &ii = net.getInputsInfo().at("data");
+    ii->setPrecision(IE::Precision::U8);
+    ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
+}
 } // anonymous namespace
 
 // TODO: Probably DNN/IE part can be further parametrized with a template
@@ -83,31 +111,26 @@ TEST(TestAgeGenderIE, InferBasicTensor)
 {
     initDLDTDataPath();
 
-    const std::string path = "Retail/object_attributes/age_gender/dldt/age-gender-recognition-retail-0013";
-    const auto topology_path = findDataFile(path + ".xml", false);
-    const auto weights_path  = findDataFile(path + ".bin", false);
+    cv::gapi::ie::detail::ParamDesc params;
+    std::tie(params.model_path, params.weights_path) = findModel("age-gender-recognition-retail-0013");
+    params.device_id = "CPU";
 
     // Load IE network, initialize input data using that.
-    namespace IE = InferenceEngine;
     cv::Mat in_mat;
     cv::Mat gapi_age, gapi_gender;
 
     IE::Blob::Ptr ie_age, ie_gender;
     {
-        IE::CNNNetReader reader;
-        reader.ReadNetwork(topology_path);
-        reader.ReadWeights(weights_path);
-        auto net = reader.getNetwork();
+        auto plugin        = cv::gimpl::ie::wrap::getPlugin(params);
+        auto net           = cv::gimpl::ie::wrap::readNetwork(params);
+        auto this_network  = cv::gimpl::ie::wrap::loadNetwork(plugin, net, params);
+        auto infer_request = this_network.CreateInferRequest();
 
         const auto &iedims = net.getInputsInfo().begin()->second->getTensorDesc().getDims();
               auto  cvdims = cv::gapi::ie::util::to_ocv(iedims);
         in_mat.create(cvdims, CV_32F);
         cv::randu(in_mat, -1, 1);
 
-        auto plugin = IE::PluginDispatcher().getPluginByDevice("CPU");
-        auto plugin_net = plugin.LoadNetwork(net, {});
-        auto infer_request = plugin_net.CreateInferRequest();
-
         infer_request.SetBlob("data", cv::gapi::ie::util::to_ie(in_mat));
         infer_request.Infer();
         ie_age    = infer_request.GetBlob("age_conv3");
@@ -124,7 +147,7 @@ TEST(TestAgeGenderIE, InferBasicTensor)
     cv::GComputation comp(cv::GIn(in), cv::GOut(age, gender));
 
     auto pp = cv::gapi::ie::Params<AgeGender> {
-        topology_path, weights_path, "CPU"
+        params.model_path, params.weights_path, params.device_id
     }.cfgOutputLayers({ "age_conv3", "prob" });
     comp.apply(cv::gin(in_mat), cv::gout(gapi_age, gapi_gender),
                cv::compile_args(cv::gapi::networks(pp)));
@@ -138,9 +161,9 @@ TEST(TestAgeGenderIE, InferBasicImage)
 {
     initDLDTDataPath();
 
-    const std::string path = "Retail/object_attributes/age_gender/dldt/age-gender-recognition-retail-0013";
-    const auto topology_path = findDataFile(path + ".xml", false);
-    const auto weights_path  = findDataFile(path + ".bin", false);
+    cv::gapi::ie::detail::ParamDesc params;
+    std::tie(params.model_path, params.weights_path) = findModel("age-gender-recognition-retail-0013");
+    params.device_id = "CPU";
 
     // FIXME: Ideally it should be an image from disk
     // cv::Mat in_mat = cv::imread(findDataFile("grace_hopper_227.png"));
@@ -150,22 +173,13 @@ TEST(TestAgeGenderIE, InferBasicImage)
     cv::Mat gapi_age, gapi_gender;
 
     // Load & run IE network
-    namespace IE = InferenceEngine;
     IE::Blob::Ptr ie_age, ie_gender;
     {
-        IE::CNNNetReader reader;
-        reader.ReadNetwork(topology_path);
-        reader.ReadWeights(weights_path);
-        auto net = reader.getNetwork();
-        auto &ii = net.getInputsInfo().at("data");
-        ii->setPrecision(IE::Precision::U8);
-        ii->setLayout(IE::Layout::NHWC);
-        ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
-
-        auto plugin = IE::PluginDispatcher().getPluginByDevice("CPU");
-        auto plugin_net = plugin.LoadNetwork(net, {});
-        auto infer_request = plugin_net.CreateInferRequest();
-
+        auto plugin        = cv::gimpl::ie::wrap::getPlugin(params);
+        auto net           = cv::gimpl::ie::wrap::readNetwork(params);
+        setNetParameters(net);
+        auto this_network  = cv::gimpl::ie::wrap::loadNetwork(plugin, net, params);
+        auto infer_request = this_network.CreateInferRequest();
         infer_request.SetBlob("data", cv::gapi::ie::util::to_ie(in_mat));
         infer_request.Infer();
         ie_age    = infer_request.GetBlob("age_conv3");
@@ -182,7 +196,7 @@ TEST(TestAgeGenderIE, InferBasicImage)
     cv::GComputation comp(cv::GIn(in), cv::GOut(age, gender));
 
     auto pp = cv::gapi::ie::Params<AgeGender> {
-        topology_path, weights_path, "CPU"
+        params.model_path, params.weights_path, params.device_id
     }.cfgOutputLayers({ "age_conv3", "prob" });
     comp.apply(cv::gin(in_mat), cv::gout(gapi_age, gapi_gender),
                cv::compile_args(cv::gapi::networks(pp)));
@@ -192,90 +206,180 @@ TEST(TestAgeGenderIE, InferBasicImage)
     normAssert(cv::gapi::ie::util::to_ocv(ie_gender), gapi_gender, "Test gender output");
 }
 
-TEST(TestAgeGenderIE, InferROIList)
+struct ROIList: public ::testing::Test {
+    cv::gapi::ie::detail::ParamDesc params;
+
+    cv::Mat m_in_mat;
+    std::vector<cv::Rect> m_roi_list;
+
+    std::vector<cv::Mat> m_out_ie_ages;
+    std::vector<cv::Mat> m_out_ie_genders;
+
+    std::vector<cv::Mat> m_out_gapi_ages;
+    std::vector<cv::Mat> m_out_gapi_genders;
+
+    using AGInfo = std::tuple<cv::GMat, cv::GMat>;
+    G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
+
+    ROIList() {
+        initDLDTDataPath();
+        std::tie(params.model_path, params.weights_path) = findModel("age-gender-recognition-retail-0013");
+        params.device_id = "CPU";
+
+        // FIXME: it must be cv::imread(findDataFile("../dnn/grace_hopper_227.png", false));
+        m_in_mat = cv::Mat(cv::Size(320, 240), CV_8UC3);
+        cv::randu(m_in_mat, 0, 255);
+
+        // both ROIs point to the same face, with a slightly changed geometry
+        m_roi_list = {
+            cv::Rect(cv::Point{64, 60}, cv::Size{ 96,  96}),
+            cv::Rect(cv::Point{50, 32}, cv::Size{128, 160}),
+        };
+
+        // Load & run IE network
+        {
+            auto plugin        = cv::gimpl::ie::wrap::getPlugin(params);
+            auto net           = cv::gimpl::ie::wrap::readNetwork(params);
+            setNetParameters(net);
+            auto this_network  = cv::gimpl::ie::wrap::loadNetwork(plugin, net, params);
+            auto infer_request = this_network.CreateInferRequest();
+            auto frame_blob = cv::gapi::ie::util::to_ie(m_in_mat);
+
+            for (auto &&rc : m_roi_list) {
+                const auto ie_rc = IE::ROI {
+                    0u
+                    , static_cast<std::size_t>(rc.x)
+                    , static_cast<std::size_t>(rc.y)
+                    , static_cast<std::size_t>(rc.width)
+                    , static_cast<std::size_t>(rc.height)
+                };
+                infer_request.SetBlob("data", IE::make_shared_blob(frame_blob, ie_rc));
+                infer_request.Infer();
+
+                using namespace cv::gapi::ie::util;
+                m_out_ie_ages.push_back(to_ocv(infer_request.GetBlob("age_conv3")).clone());
+                m_out_ie_genders.push_back(to_ocv(infer_request.GetBlob("prob")).clone());
+            }
+        } // namespace IE = ..
+    } // ROIList()
+
+    void validate() {
+        // Validate with IE itself (avoid DNN module dependency here)
+        ASSERT_EQ(2u, m_out_ie_ages.size());
+        ASSERT_EQ(2u, m_out_ie_genders.size());
+        ASSERT_EQ(2u, m_out_gapi_ages.size());
+        ASSERT_EQ(2u, m_out_gapi_genders.size());
+
+        normAssert(m_out_ie_ages   [0], m_out_gapi_ages   [0], "0: Test age output");
+        normAssert(m_out_ie_genders[0], m_out_gapi_genders[0], "0: Test gender output");
+        normAssert(m_out_ie_ages   [1], m_out_gapi_ages   [1], "1: Test age output");
+        normAssert(m_out_ie_genders[1], m_out_gapi_genders[1], "1: Test gender output");
+    }
+}; // ROIList
+
+TEST_F(ROIList, TestInfer)
+{
+    cv::GArray<cv::Rect> rr;
+    cv::GMat in;
+    cv::GArray<cv::GMat> age, gender;
+    std::tie(age, gender) = cv::gapi::infer<AgeGender>(rr, in);
+    cv::GComputation comp(cv::GIn(in, rr), cv::GOut(age, gender));
+
+    auto pp = cv::gapi::ie::Params<AgeGender> {
+        params.model_path, params.weights_path, params.device_id
+    }.cfgOutputLayers({ "age_conv3", "prob" });
+    comp.apply(cv::gin(m_in_mat, m_roi_list),
+               cv::gout(m_out_gapi_ages, m_out_gapi_genders),
+               cv::compile_args(cv::gapi::networks(pp)));
+    validate();
+}
+
+TEST_F(ROIList, TestInfer2)
+{
+    cv::GArray<cv::Rect> rr;
+    cv::GMat in;
+    cv::GArray<cv::GMat> age, gender;
+    std::tie(age, gender) = cv::gapi::infer2<AgeGender>(in, rr);
+    cv::GComputation comp(cv::GIn(in, rr), cv::GOut(age, gender));
+
+    auto pp = cv::gapi::ie::Params<AgeGender> {
+        params.model_path, params.weights_path, params.device_id
+    }.cfgOutputLayers({ "age_conv3", "prob" });
+    comp.apply(cv::gin(m_in_mat, m_roi_list),
+               cv::gout(m_out_gapi_ages, m_out_gapi_genders),
+               cv::compile_args(cv::gapi::networks(pp)));
+    validate();
+}
+
+TEST(DISABLED_TestTwoIENNPipeline, InferBasicImage)
 {
     initDLDTDataPath();
 
-    const std::string path = "Retail/object_attributes/age_gender/dldt/age-gender-recognition-retail-0013";
-    const auto topology_path = findDataFile(path + ".xml", false);
-    const auto weights_path  = findDataFile(path + ".bin", false);
+    cv::gapi::ie::detail::ParamDesc AGparams;
+    std::tie(AGparams.model_path, AGparams.weights_path) = findModel("age-gender-recognition-retail-0013");
+    AGparams.device_id = "MYRIAD";
 
     // FIXME: Ideally it should be an image from disk
     // cv::Mat in_mat = cv::imread(findDataFile("grace_hopper_227.png"));
-    cv::Mat in_mat(cv::Size(640, 480), CV_8UC3);
+    cv::Mat in_mat(cv::Size(320, 240), CV_8UC3);
     cv::randu(in_mat, 0, 255);
 
-    std::vector<cv::Rect> rois = {
-        cv::Rect(cv::Point{ 0,   0}, cv::Size{80, 120}),
-        cv::Rect(cv::Point{50, 100}, cv::Size{96, 160}),
-    };
-
-    std::vector<cv::Mat> gapi_age, gapi_gender;
+    cv::Mat gapi_age1, gapi_gender1, gapi_age2, gapi_gender2;
 
     // Load & run IE network
-    namespace IE = InferenceEngine;
-    std::vector<cv::Mat> ie_age, ie_gender;
+    IE::Blob::Ptr ie_age1, ie_gender1, ie_age2, ie_gender2;
     {
-        IE::CNNNetReader reader;
-        reader.ReadNetwork(topology_path);
-        reader.ReadWeights(weights_path);
-        auto net = reader.getNetwork();
-        auto &ii = net.getInputsInfo().at("data");
-        ii->setPrecision(IE::Precision::U8);
-        ii->setLayout(IE::Layout::NHWC);
-        ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
-
-        auto plugin = IE::PluginDispatcher().getPluginByDevice("CPU");
-        auto plugin_net = plugin.LoadNetwork(net, {});
-        auto infer_request = plugin_net.CreateInferRequest();
-        auto frame_blob = cv::gapi::ie::util::to_ie(in_mat);
-
-        for (auto &&rc : rois) {
-            const auto ie_rc = IE::ROI {
-                  0u
-                , static_cast<std::size_t>(rc.x)
-                , static_cast<std::size_t>(rc.y)
-                , static_cast<std::size_t>(rc.width)
-                , static_cast<std::size_t>(rc.height)
-            };
-            infer_request.SetBlob("data", IE::make_shared_blob(frame_blob, ie_rc));
-            infer_request.Infer();
-
-            using namespace cv::gapi::ie::util;
-            ie_age.push_back(to_ocv(infer_request.GetBlob("age_conv3")).clone());
-            ie_gender.push_back(to_ocv(infer_request.GetBlob("prob")).clone());
-        }
+        auto AGplugin1         = cv::gimpl::ie::wrap::getPlugin(AGparams);
+        auto AGnet1            = cv::gimpl::ie::wrap::readNetwork(AGparams);
+        setNetParameters(AGnet1);
+        auto AGplugin_network1 = cv::gimpl::ie::wrap::loadNetwork(AGplugin1, AGnet1, AGparams);
+        auto AGinfer_request1  = AGplugin_network1.CreateInferRequest();
+        AGinfer_request1.SetBlob("data", cv::gapi::ie::util::to_ie(in_mat));
+        AGinfer_request1.Infer();
+        ie_age1    = AGinfer_request1.GetBlob("age_conv3");
+        ie_gender1 = AGinfer_request1.GetBlob("prob");
+
+        auto AGplugin2         = cv::gimpl::ie::wrap::getPlugin(AGparams);
+        auto AGnet2            = cv::gimpl::ie::wrap::readNetwork(AGparams);
+        setNetParameters(AGnet2);
+        auto AGplugin_network2 = cv::gimpl::ie::wrap::loadNetwork(AGplugin2, AGnet2, AGparams);
+        auto AGinfer_request2     = AGplugin_network2.CreateInferRequest();
+        AGinfer_request2.SetBlob("data", cv::gapi::ie::util::to_ie(in_mat));
+        AGinfer_request2.Infer();
+        ie_age2    = AGinfer_request2.GetBlob("age_conv3");
+        ie_gender2 = AGinfer_request2.GetBlob("prob");
     }
 
     // Configure & run G-API
     using AGInfo = std::tuple<cv::GMat, cv::GMat>;
-    G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
-
-    cv::GArray<cv::Rect> rr;
+    G_API_NET(AgeGender1, <AGInfo(cv::GMat)>,   "test-age-gender1");
+    G_API_NET(AgeGender2, <AGInfo(cv::GMat)>,   "test-age-gender2");
     cv::GMat in;
-    cv::GArray<cv::GMat> age, gender;
-    std::tie(age, gender) = cv::gapi::infer<AgeGender>(rr, in);
-    cv::GComputation comp(cv::GIn(in, rr), cv::GOut(age, gender));
+    cv::GMat age1, gender1;
+    std::tie(age1, gender1) = cv::gapi::infer<AgeGender1>(in);
 
-    auto pp = cv::gapi::ie::Params<AgeGender> {
-        topology_path, weights_path, "CPU"
+    cv::GMat age2, gender2;
+    // FIXME: "Multi-node inference is not supported!", workarounded 'till enabling proper tools
+    std::tie(age2, gender2) = cv::gapi::infer<AgeGender2>(cv::gapi::copy(in));
+    cv::GComputation comp(cv::GIn(in), cv::GOut(age1, gender1, age2, gender2));
+
+    auto age_net1 = cv::gapi::ie::Params<AgeGender1> {
+        AGparams.model_path, AGparams.weights_path, AGparams.device_id
+    }.cfgOutputLayers({ "age_conv3", "prob" });
+    auto age_net2 = cv::gapi::ie::Params<AgeGender2> {
+        AGparams.model_path, AGparams.weights_path, AGparams.device_id
     }.cfgOutputLayers({ "age_conv3", "prob" });
-    comp.apply(cv::gin(in_mat, rois), cv::gout(gapi_age, gapi_gender),
-               cv::compile_args(cv::gapi::networks(pp)));
+
+    comp.apply(cv::gin(in_mat), cv::gout(gapi_age1, gapi_gender1, gapi_age2, gapi_gender2),
+               cv::compile_args(cv::gapi::networks(age_net1, age_net2)));
 
     // Validate with IE itself (avoid DNN module dependency here)
-    ASSERT_EQ(2u, ie_age.size()   );
-    ASSERT_EQ(2u, ie_gender.size());
-    ASSERT_EQ(2u, gapi_age.size()   );
-    ASSERT_EQ(2u, gapi_gender.size());
-
-    normAssert(ie_age   [0], gapi_age   [0], "0: Test age output");
-    normAssert(ie_gender[0], gapi_gender[0], "0: Test gender output");
-    normAssert(ie_age   [1], gapi_age   [1], "1: Test age output");
-    normAssert(ie_gender[1], gapi_gender[1], "1: Test gender output");
+    normAssert(cv::gapi::ie::util::to_ocv(ie_age1),    gapi_age1,    "Test age output 1");
+    normAssert(cv::gapi::ie::util::to_ocv(ie_gender1), gapi_gender1, "Test gender output 1");
+    normAssert(cv::gapi::ie::util::to_ocv(ie_age2),    gapi_age2,    "Test age output 2");
+    normAssert(cv::gapi::ie::util::to_ocv(ie_gender2), gapi_gender2, "Test gender output 2");
 }
 
-
 } // namespace opencv_test
 
 #endif //  HAVE_INF_ENGINE
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/infer/gapi_infer_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/infer/gapi_infer_tests.cpp
new file mode 100644 (file)
index 0000000..8ab7af3
--- /dev/null
@@ -0,0 +1,79 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include "../test_precomp.hpp"
+
+// These tests verify some parts of cv::gapi::infer<> API
+// regardless of the backend used
+
+namespace opencv_test {
+namespace {
+template<class A, class B> using Check = cv::detail::valid_infer2_types<A, B>;
+
+TEST(Infer, ValidInfer2Types)
+{
+    // Compiled == passed!
+
+    // Argument block 1
+    static_assert(Check< std::tuple<cv::GMat>   // Net
+                       , std::tuple<cv::GMat> > // Call
+                  ::value == true, "Must work");
+
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat>   // Net
+                       , std::tuple<cv::GMat, cv::GMat> > // Call
+                  ::value == true, "Must work");
+
+    // Argument block 2
+    static_assert(Check< std::tuple<cv::GMat>             // Net
+                       , std::tuple<cv::Rect> >           // Call
+                  ::value == true, "Must work");
+
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat>   // Net
+                       , std::tuple<cv::Rect, cv::Rect> > // Call
+                  ::value == true, "Must work");
+
+    // Argument block 3 (mixed cases)
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat>   // Net
+                       , std::tuple<cv::GMat, cv::Rect> > // Call
+                  ::value == true, "Must work");
+
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat>   // Net
+                       , std::tuple<cv::Rect, cv::GMat> > // Call
+                  ::value == true, "Must work");
+
+    // Argument block 4 (super-mixed)
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat, cv::GMat>   // Net
+                       , std::tuple<cv::Rect, cv::GMat, cv::Rect> > // Call
+                  ::value == true, "Must work");
+
+    // Argument block 5 (mainly negative)
+    static_assert(Check< std::tuple<cv::GMat>             // Net
+                       , std::tuple<int> >                // Call
+                  ::value == false, "This type(s) shouldn't pass");
+
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat>   // Net
+                       , std::tuple<int, cv::Rect> >      // Call
+                  ::value == false, "This type(s) shouldn't pass");
+
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat>   // Net
+                       , std::tuple<cv::Rect, cv::Point> >// Call
+                  ::value == false, "This type(s) shouldn't pass");
+
+    // Argument block 5 (wrong args length)
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat>   // Net
+                       , std::tuple<cv::GMat> >           // Call
+                  ::value == false, "Should fail -- not enough args");
+
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat>   // Net
+                       , std::tuple<cv::Rect> >           // Call
+                  ::value == false, "Should fail -- not enough args");
+
+    static_assert(Check< std::tuple<cv::GMat, cv::GMat>             // Net
+                       , std::tuple<cv::Rect, cv::Rect, cv::GMat> > // Call
+                  ::value == false, "Should fail -- too much args");
+}
+} // anonymous namespace
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_dynamic_graph.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_dynamic_graph.cpp
new file mode 100644 (file)
index 0000000..75e90d6
--- /dev/null
@@ -0,0 +1,331 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include "../test_precomp.hpp"
+
+#include <opencv2/gapi/cpu/core.hpp>
+#include <opencv2/gapi/cpu/imgproc.hpp>
+
+namespace opencv_test
+{
+    typedef ::testing::Types<cv::GMat, cv::GMatP, cv::GFrame,
+                             cv::GScalar, cv::GOpaque<int>,
+                             cv::GArray<int>> VectorProtoTypes;
+
+    template<typename T> struct DynamicGraphProtoArgs: public ::testing::Test { using Type = T; };
+
+    TYPED_TEST_CASE(DynamicGraphProtoArgs, VectorProtoTypes);
+
+    TYPED_TEST(DynamicGraphProtoArgs, AddProtoInputArgsSmoke)
+    {
+        using T = typename TestFixture::Type;
+        auto ins = GIn();
+        T in;
+        EXPECT_NO_THROW(ins += GIn(in));
+    }
+
+    TYPED_TEST(DynamicGraphProtoArgs, AddProtoInputArgs)
+    {
+        using T = typename TestFixture::Type;
+        T in1, in2;
+
+        auto ins1 = GIn();
+        ins1 += GIn(in1);
+        ins1 += GIn(in2);
+
+        auto ins2 = GIn(in1, in2);
+
+        EXPECT_EQ(ins1.m_args.size(), ins2.m_args.size());
+    }
+
+    TYPED_TEST(DynamicGraphProtoArgs, AddProtoOutputArgsSmoke)
+    {
+        using T = typename TestFixture::Type;
+        auto outs = GOut();
+        T out;
+        EXPECT_NO_THROW(outs += GOut(out));
+    }
+
+    TYPED_TEST(DynamicGraphProtoArgs, AddProtoOutputArgs)
+    {
+        using T = typename TestFixture::Type;
+        T out1, out2;
+
+        auto outs1 = GOut();
+        outs1 += GOut(out1);
+        outs1 += GOut(out2);
+
+        auto outs2 = GOut(out1, out2);
+
+        EXPECT_EQ(outs1.m_args.size(), outs2.m_args.size());
+    }
+
+    typedef ::testing::Types<cv::Mat,
+#if !defined(GAPI_STANDALONE)
+                             cv::UMat,
+#endif // !defined(GAPI_STANDALONE)
+                             cv::Scalar,
+                             cv::detail::VectorRef,
+                             cv::detail::OpaqueRef> VectorRunTypes;
+
+    template<typename T> struct DynamicGraphRunArgs: public ::testing::Test { using Type = T; };
+
+    TYPED_TEST_CASE(DynamicGraphRunArgs, VectorRunTypes);
+
+    TYPED_TEST(DynamicGraphRunArgs, AddRunArgsSmoke)
+    {
+        auto in_vector = cv::gin();
+
+        using T = typename TestFixture::Type;
+        T in;
+        EXPECT_NO_THROW(in_vector += cv::gin(in));
+    }
+
+    TYPED_TEST(DynamicGraphRunArgs, AddRunArgs)
+    {
+        using T = typename TestFixture::Type;
+        T in1, in2;
+
+        auto in_vector1 = cv::gin();
+        in_vector1 += cv::gin(in1);
+        in_vector1 += cv::gin(in2);
+
+        auto in_vector2 = cv::gin(in1, in2);
+
+        EXPECT_EQ(in_vector1.size(), in_vector2.size());
+    }
+
+    TYPED_TEST(DynamicGraphRunArgs, AddRunArgsPSmoke)
+    {
+        auto out_vector = cv::gout();
+
+        using T = typename TestFixture::Type;
+        T out;
+        EXPECT_NO_THROW(out_vector += cv::gout(out));
+    }
+
+    TYPED_TEST(DynamicGraphRunArgs, AddRunArgsP)
+    {
+        using T = typename TestFixture::Type;
+        T out1, out2;
+
+        auto out_vector1 = cv::gout();
+        out_vector1 += cv::gout(out1);
+        out_vector1 += cv::gout(out2);
+
+        auto out_vector2 = cv::gout(out1, out2);
+
+        EXPECT_EQ(out_vector1.size(), out_vector2.size());
+    }
+
+    TEST(DynamicGraph, ProtoInputArgsExecute)
+    {
+        cv::GComputation cc([]() {
+            cv::GMat in1;
+            auto ins = GIn(in1);
+
+            cv::GMat in2;
+            ins += GIn(in2);
+
+            cv::GMat out = cv::gapi::copy(in1 + in2);
+
+            return cv::GComputation(std::move(ins), GOut(out));
+        });
+
+        cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
+        cv::Mat in_mat2 = cv::Mat::eye(32, 32, CV_8UC1);
+        cv::Mat out_mat;
+
+        EXPECT_NO_THROW(cc.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat)));
+    }
+
+    TEST(DynamicGraph, ProtoOutputArgsExecute)
+    {
+        cv::GComputation cc([]() {
+            cv::GMat in;
+            cv::GMat out1 = cv::gapi::copy(in);
+            auto outs = GOut(out1);
+
+            cv::GMat out2 = cv::gapi::copy(in);
+            outs += GOut(out2);
+
+            return cv::GComputation(cv::GIn(in), std::move(outs));
+        });
+
+        cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
+        cv::Mat out_mat1;
+        cv::Mat out_mat2;
+
+        EXPECT_NO_THROW(cc.apply(cv::gin(in_mat1), cv::gout(out_mat1, out_mat1)));
+    }
+
+    TEST(DynamicGraph, ProtoOutputInputArgsExecute)
+    {
+        cv::GComputation cc([]() {
+            cv::GMat in1;
+            auto ins = GIn(in1);
+
+            cv::GMat in2;
+            ins += GIn(in2);
+
+            cv::GMat out1 = cv::gapi::copy(in1 + in2);
+            auto outs = GOut(out1);
+
+            cv::GMat out2 = cv::gapi::copy(in1 + in2);
+            outs += GOut(out2);
+
+            return cv::GComputation(std::move(ins), std::move(outs));
+        });
+
+        cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
+        cv::Mat in_mat2 = cv::Mat::eye(32, 32, CV_8UC1);
+        cv::Mat out_mat1, out_mat2;
+
+        EXPECT_NO_THROW(cc.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat1, out_mat2)));
+    }
+
+    TEST(DynamicGraph, ProtoArgsExecute)
+    {
+        cv::GComputation cc([]() {
+            cv::GMat in1;
+            auto ins = GIn(in1);
+
+            cv::GMat in2;
+            ins += GIn(in2);
+
+            cv::GMat out1 = cv::gapi::copy(in1 + in2);
+            auto outs = GOut(out1);
+
+            cv::GMat out2 = cv::gapi::copy(in1 + in2);
+            outs += GOut(out2);
+
+            return cv::GComputation(std::move(ins), std::move(outs));
+        });
+
+        cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
+        cv::Mat in_mat2 = cv::Mat::eye(32, 32, CV_8UC1);
+        cv::Mat out_mat1, out_mat2;
+
+        EXPECT_NO_THROW(cc.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat1, out_mat2)));
+    }
+
+    TEST(DynamicGraph, ProtoOutputInputArgsAccuracy)
+    {
+        cv::Size szOut(4, 4);
+        cv::GComputation cc([&](){
+            cv::GMat in1;
+            auto ins = GIn(in1);
+
+            cv::GMat in2;
+            ins += GIn(in2);
+
+            cv::GMat out1 = cv::gapi::resize(in1, szOut);
+            auto outs = GOut(out1);
+
+            cv::GMat out2 = cv::gapi::resize(in2, szOut);
+            outs += GOut(out2);
+
+            return cv::GComputation(std::move(ins), std::move(outs));
+        });
+
+        // G-API test code
+        cv::Mat in_mat1( 8,  8, CV_8UC3);
+        cv::Mat in_mat2(16, 16, CV_8UC3);
+        cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+        cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+
+        auto in_vector = cv::gin();
+        in_vector += cv::gin(in_mat1);
+        in_vector += cv::gin(in_mat2);
+
+        cv::Mat out_mat1, out_mat2;
+        auto out_vector = cv::gout();
+        out_vector += cv::gout(out_mat1);
+        out_vector += cv::gout(out_mat2);
+
+        cc.apply(std::move(in_vector), std::move(out_vector));
+
+        // OCV ref code
+        cv::Mat cv_out_mat1, cv_out_mat2;
+        cv::resize(in_mat1, cv_out_mat1, szOut);
+        cv::resize(in_mat2, cv_out_mat2, szOut);
+
+        EXPECT_EQ(0, cvtest::norm(out_mat1, cv_out_mat1, NORM_INF));
+        EXPECT_EQ(0, cvtest::norm(out_mat2, cv_out_mat2, NORM_INF));
+    }
+
+    TEST(DynamicGraph, Streaming)
+    {
+        cv::GComputation cc([&](){
+            cv::Size szOut(4, 4);
+
+            cv::GMat in1;
+            auto ins = GIn(in1);
+
+            cv::GMat in2;
+            ins += GIn(in2);
+
+            cv::GMat out1 = cv::gapi::resize(in1, szOut);
+            auto outs = GOut(out1);
+
+            cv::GMat out2 = cv::gapi::resize(in2, szOut);
+            outs += GOut(out2);
+
+            return cv::GComputation(std::move(ins), std::move(outs));
+        });
+
+        EXPECT_NO_THROW(cc.compileStreaming(cv::compile_args(cv::gapi::core::cpu::kernels())));
+    }
+
+    TEST(DynamicGraph, StreamingAccuracy)
+    {
+        cv::Size szOut(4, 4);
+        cv::GComputation cc([&](){
+            cv::GMat in1;
+            auto ins = GIn(in1);
+
+            cv::GMat in2;
+            ins += GIn(in2);
+
+            cv::GMat out1 = cv::gapi::resize(in1, szOut);
+            cv::GProtoOutputArgs outs = GOut(out1);
+
+            cv::GMat out2 = cv::gapi::resize(in2, szOut);
+            outs += GOut(out2);
+            return cv::GComputation(std::move(ins), std::move(outs));
+        });
+
+        // G-API test code
+        cv::Mat in_mat1( 8,  8, CV_8UC3);
+        cv::Mat in_mat2(16, 16, CV_8UC3);
+        cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+        cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+
+        auto in_vector = cv::gin();
+        in_vector += cv::gin(in_mat1);
+        in_vector += cv::gin(in_mat2);
+
+        cv::Mat out_mat1, out_mat2;
+        auto out_vector = cv::gout();
+        out_vector += cv::gout(out_mat1);
+        out_vector += cv::gout(out_mat2);
+
+        auto stream = cc.compileStreaming(cv::compile_args(cv::gapi::core::cpu::kernels()));
+        stream.setSource(std::move(in_vector));
+
+        stream.start();
+        stream.pull(std::move(out_vector));
+        stream.stop();
+
+        // OCV ref code
+        cv::Mat cv_out_mat1, cv_out_mat2;
+        cv::resize(in_mat1, cv_out_mat1, szOut);
+        cv::resize(in_mat2, cv_out_mat2, szOut);
+
+        EXPECT_EQ(0, cvtest::norm(out_mat1, cv_out_mat1, NORM_INF));
+        EXPECT_EQ(0, cvtest::norm(out_mat2, cv_out_mat2, NORM_INF));
+    }
+} // namespace opencv_test
index aad1123..7c596df 100644 (file)
@@ -8,7 +8,7 @@
 #include "../test_precomp.hpp"
 
 namespace opencv_test {
-// Tests on T/Kind matching ////////////////////////////////////////////////////
+// Tests on T/Spec/Kind matching ///////////////////////////////////////////////
 // {{
 
 template<class T, cv::detail::ArgKind Exp>
@@ -32,6 +32,7 @@ using GArg_Test_Types = ::testing::Types
   // G-API types
      Expected<cv::GMat,                 cv::detail::ArgKind::GMAT>
    , Expected<cv::GMatP,                cv::detail::ArgKind::GMATP>
+   , Expected<cv::GFrame,               cv::detail::ArgKind::GFRAME>
    , Expected<cv::GScalar,              cv::detail::ArgKind::GSCALAR>
    , Expected<cv::GArray<int>,          cv::detail::ArgKind::GARRAY>
    , Expected<cv::GArray<float>,        cv::detail::ArgKind::GARRAY>
@@ -75,7 +76,6 @@ TYPED_TEST(GArgKind, RValue)
     EXPECT_EQ(TestFixture::Kind, arg.kind);
 }
 
-// }}
 ////////////////////////////////////////////////////////////////////////////////
 
 TEST(GArg, HasWrap)
@@ -115,6 +115,4 @@ TEST(GArg, GOpaqueU)
     cv::GArg arg2 = cv::GArg(cv::GOpaque<cv::Point>());
     EXPECT_NO_THROW(arg2.get<cv::detail::GOpaqueU>());
 }
-
-
 } // namespace opencv_test
index 3b4608c..f6543e5 100644 (file)
@@ -10,6 +10,7 @@
 #include <ade/util/zip_range.hpp>   // util::indexed
 
 #include <opencv2/gapi/gkernel.hpp>
+#include <opencv2/gapi/gcommon.hpp>
 #include "compiler/gmodelbuilder.hpp"
 #include "compiler/gmodel.hpp" // RcDesc, GModel::init
 
@@ -21,14 +22,23 @@ namespace test
 
 namespace
 {
+    namespace D = cv::detail;
     cv::GMat unaryOp(cv::GMat m)
     {
-        return cv::GCall(cv::GKernel{"gapi.test.unaryop", "", nullptr, { GShape::GMAT } }).pass(m).yield(0);
+        return cv::GCall(cv::GKernel{ "gapi.test.unaryop"
+                                    , ""
+                                    , nullptr
+                                    , { GShape::GMAT }
+                                    , { D::OpaqueKind::CV_UNKNOWN } }).pass(m).yield(0);
     }
 
     cv::GMat binaryOp(cv::GMat m1, cv::GMat m2)
     {
-        return cv::GCall(cv::GKernel{"gapi.test.binaryOp", "", nullptr, { GShape::GMAT } }).pass(m1, m2).yield(0);
+        return cv::GCall(cv::GKernel{ "gapi.test.binaryOp"
+                                    , ""
+                                    , nullptr
+                                    , { GShape::GMAT }
+                                    , { D::OpaqueKind::CV_UNKNOWN, D::OpaqueKind::CV_UNKNOWN } }).pass(m1, m2).yield(0);
     }
 
     std::vector<ade::NodeHandle> collectOperations(const cv::gimpl::GModel::Graph& gr)
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_proto_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_proto_tests.cpp
new file mode 100644 (file)
index 0000000..1fe9fbb
--- /dev/null
@@ -0,0 +1,34 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+#include "../src/api/gproto_priv.hpp"
+
+namespace opencv_test {
+
+template<typename T>
+struct ProtoPtrTest : public ::testing::Test { using Type = T; };
+
+using ProtoPtrTestTypes = ::testing::Types< cv::Mat
+                                          , cv::UMat
+                                          , cv::gapi::own::Mat
+                                          , cv::Scalar
+                                          , std::vector<int>
+                                          , int
+                                          >;
+
+TYPED_TEST_CASE(ProtoPtrTest, ProtoPtrTestTypes);
+
+TYPED_TEST(ProtoPtrTest, NonZero)
+{
+    typename TestFixture::Type value;
+    const auto arg = cv::gout(value).front();
+    const auto ptr = cv::gimpl::proto::ptr(arg);
+    EXPECT_EQ(ptr, &value);
+}
+
+} // namespace opencv_test
index e71985f..1809a36 100644 (file)
@@ -19,8 +19,8 @@ const char* opencl_symm7x7_src =
 "#endif\n"
 "#define GET_A0(id, x, l_edge, a1) ((x) <= (l_edge + 2) ? GET_BORDER(a1) : (((const __global uchar*)(id))[-3]))\n"
 "#define GET_A1(id, x, l_edge, a2) ((x) <= (l_edge + 1) ? GET_BORDER(a2) : (((const __global uchar*)(id))[-2]))\n"
-"#define GET_A2(id, x, l_edge, b) ((x) <= (l_edge) ? GET_BORDER(b[0]) : (((const __global uchar*)(id))[-1]))\n"
-"#define GET_C0(id, x, r_edge, b) ((x) >= (r_edge) ? GET_BORDER(b[8 - 1]) : (((const __global uchar*)(id))[8]))\n"
+"#define GET_A2(id, x, l_edge, b) ((x) <= (l_edge) ? GET_BORDER(b.s0) : (((const __global uchar*)(id))[-1]))\n"
+"#define GET_C0(id, x, r_edge, b) ((x) >= (r_edge) ? GET_BORDER(b.s7) : (((const __global uchar*)(id))[8]))\n"
 "#define GET_C1(id, x, r_edge, c0) ((x) >= (r_edge - 1) ? GET_BORDER(c0) : (((const __global uchar*)(id))[8 + 1]))\n"
 "#define GET_C2(id, x, r_edge, c1) ((x) >= (r_edge - 2) ? GET_BORDER(c1) : (((const __global uchar*)(id))[8 + 2]))\n"
 "__kernel void symm_7x7_test(\n"
index b063c45..0ddc201 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "../test_precomp.hpp"
 #include <opencv2/gapi/own/mat.hpp>
+#include <opencv2/gapi/own/convert.hpp>
 #include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
 
 namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/rmat/rmat_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/rmat/rmat_tests.cpp
new file mode 100644 (file)
index 0000000..8b93fbe
--- /dev/null
@@ -0,0 +1,171 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include "../test_precomp.hpp"
+#include <opencv2/gapi/rmat.hpp>
+
+namespace opencv_test {
+namespace {
+class RMatAdapterRef : public RMat::Adapter {
+    cv::Mat& m_mat;
+    bool& m_callbackCalled;
+public:
+    RMatAdapterRef(cv::Mat& m, bool& callbackCalled)
+        : m_mat(m), m_callbackCalled(callbackCalled)
+    {}
+    virtual RMat::View access(RMat::Access access) const override {
+        if (access == RMat::Access::W) {
+            return RMat::View(cv::descr_of(m_mat), m_mat.data, m_mat.step,
+                              [this](){
+                                  EXPECT_FALSE(m_callbackCalled);
+                                  m_callbackCalled = true;
+                              });
+        } else {
+            return RMat::View(cv::descr_of(m_mat), m_mat.data, m_mat.step);
+        }
+    }
+    virtual cv::GMatDesc desc() const override { return cv::descr_of(m_mat); }
+};
+
+class RMatAdapterCopy : public RMat::Adapter {
+    cv::Mat& m_deviceMat;
+    cv::Mat  m_hostMat;
+    bool& m_callbackCalled;
+
+public:
+    RMatAdapterCopy(cv::Mat& m, bool& callbackCalled)
+        : m_deviceMat(m), m_hostMat(m.clone()), m_callbackCalled(callbackCalled)
+    {}
+    virtual RMat::View access(RMat::Access access) const override {
+        if (access == RMat::Access::W) {
+            return RMat::View(cv::descr_of(m_hostMat), m_hostMat.data, m_hostMat.step,
+                              [this](){
+                                  EXPECT_FALSE(m_callbackCalled);
+                                  m_callbackCalled = true;
+                                  m_hostMat.copyTo(m_deviceMat);
+                              });
+        } else {
+            m_deviceMat.copyTo(m_hostMat);
+            return RMat::View(cv::descr_of(m_hostMat), m_hostMat.data, m_hostMat.step);
+        }
+    }
+    virtual cv::GMatDesc desc() const override { return cv::descr_of(m_hostMat); }
+};
+
+void randomizeMat(cv::Mat& m) {
+    auto ref = m.clone();
+    while (cv::norm(m, ref, cv::NORM_INF) == 0) {
+        cv::randu(m, cv::Scalar::all(127), cv::Scalar::all(40));
+    }
+}
+
+template <typename RMatAdapterT>
+struct RMatTest {
+    using AdapterT = RMatAdapterT;
+    RMatTest()
+        : m_deviceMat(8,8,CV_8UC1)
+        , m_rmat(make_rmat<RMatAdapterT>(m_deviceMat, m_callbackCalled)) {
+        randomizeMat(m_deviceMat);
+        expectNoCallbackCalled();
+    }
+
+    RMat& rmat() { return m_rmat; }
+    cv::Mat cloneDeviceMat() { return m_deviceMat.clone(); }
+    void expectCallbackCalled() { EXPECT_TRUE(m_callbackCalled); }
+    void expectNoCallbackCalled() { EXPECT_FALSE(m_callbackCalled); }
+
+    void expectDeviceDataEqual(const cv::Mat& mat) {
+        EXPECT_EQ(0, cv::norm(mat, m_deviceMat, NORM_INF));
+    }
+    void expectDeviceDataNotEqual(const cv::Mat& mat) {
+        EXPECT_NE(0, cv::norm(mat, m_deviceMat, NORM_INF));
+    }
+
+private:
+    cv::Mat m_deviceMat;
+    bool m_callbackCalled = false;
+    cv::RMat m_rmat;
+};
+} // anonymous namespace
+
+template<typename T>
+struct RMatTypedTest : public ::testing::Test, public T { using Type = T; };
+
+using RMatTestTypes = ::testing::Types< RMatTest<RMatAdapterRef>
+                                      , RMatTest<RMatAdapterCopy>
+                                      >;
+
+TYPED_TEST_CASE(RMatTypedTest, RMatTestTypes);
+
+TYPED_TEST(RMatTypedTest, Smoke) {
+    auto view = this->rmat().access(RMat::Access::R);
+    auto matFromDevice = cv::Mat(view.size(), view.type(), view.ptr());
+    EXPECT_TRUE(cv::descr_of(this->cloneDeviceMat()) == this->rmat().desc());
+    this->expectDeviceDataEqual(matFromDevice);
+}
+
+static Mat asMat(RMat::View& view) {
+    return Mat(view.size(), view.type(), view.ptr(), view.step());
+}
+
+TYPED_TEST(RMatTypedTest, BasicWorkflow) {
+    {
+        auto view = this->rmat().access(RMat::Access::R);
+        this->expectDeviceDataEqual(asMat(view));
+    }
+    this->expectNoCallbackCalled();
+
+    cv::Mat dataToWrite = this->cloneDeviceMat();
+    randomizeMat(dataToWrite);
+    this->expectDeviceDataNotEqual(dataToWrite);
+    {
+        auto view = this->rmat().access(RMat::Access::W);
+        dataToWrite.copyTo(asMat(view));
+    }
+    this->expectCallbackCalled();
+    this->expectDeviceDataEqual(dataToWrite);
+}
+
+TEST(RMat, TestEmptyAdapter) {
+    RMat rmat;
+    EXPECT_ANY_THROW(rmat.get<RMatAdapterCopy>());
+}
+
+TYPED_TEST(RMatTypedTest, CorrectAdapterCast) {
+    using T = typename TestFixture::Type::AdapterT;
+    EXPECT_NE(nullptr, this->rmat().template get<T>());
+}
+
+class DummyAdapter : public RMat::Adapter {
+    virtual RMat::View access(RMat::Access) const override { return {}; }
+    virtual cv::GMatDesc desc() const override { return {}; }
+};
+
+TYPED_TEST(RMatTypedTest, IncorrectAdapterCast) {
+    EXPECT_EQ(nullptr, this->rmat().template get<DummyAdapter>());
+}
+
+class RMatAdapterForBackend : public RMat::Adapter {
+    int m_i;
+public:
+    RMatAdapterForBackend(int i) : m_i(i) {}
+    virtual RMat::View access(RMat::Access) const override { return {}; }
+    virtual GMatDesc desc() const override { return {}; }
+    int deviceSpecificData() const { return m_i; }
+};
+
+// RMat's usage scenario in the backend:
+// we have some specific data hidden under RMat,
+// test that we can obtain it via RMat.as<T>() method
+TEST(RMat, UsageInBackend) {
+    int i = std::rand();
+    auto rmat = cv::make_rmat<RMatAdapterForBackend>(i);
+
+    auto adapter = rmat.get<RMatAdapterForBackend>();
+    EXPECT_NE(nullptr, adapter);
+    EXPECT_EQ(i, adapter->deviceSpecificData());
+}
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/rmat/rmat_view_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/rmat/rmat_view_tests.cpp
new file mode 100644 (file)
index 0000000..750f5a7
--- /dev/null
@@ -0,0 +1,147 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+#include "../test_precomp.hpp"
+#include <opencv2/gapi/rmat.hpp>
+
+#include <opencv2/gapi/util/compiler_hints.hpp>
+#include "../src/backends/common/gbackend.hpp"
+
+namespace opencv_test
+{
+using cv::GMatDesc;
+using View = cv::RMat::View;
+using cv::Mat;
+using namespace ::testing;
+
+static void expect_eq_desc(const View& view, const GMatDesc& desc) {
+    EXPECT_EQ(view.size(), desc.size);
+    EXPECT_EQ(view.dims(), desc.dims);
+    EXPECT_EQ(view.cols(), desc.size.width);
+    EXPECT_EQ(view.rows(), desc.size.height);
+    EXPECT_EQ(view.type(), CV_MAKE_TYPE(desc.depth,desc.chan));
+    EXPECT_EQ(view.depth(), desc.depth);
+    EXPECT_EQ(view.chan(), desc.chan);
+}
+
+TEST(RMatView, TestDefaultConstruction) {
+    View view;
+    GMatDesc desc{};
+    expect_eq_desc(view, desc);
+    EXPECT_EQ(view.ptr(), nullptr);
+    EXPECT_EQ(view.step(), 0u);
+}
+
+struct RMatViewTest : public TestWithParam<int /*dataType*/>{};
+TEST_P(RMatViewTest, ConstructionFromMat) {
+    auto type = GetParam();
+    Mat mat(8,8,type);
+    const auto desc = cv::descr_of(mat);
+    View view(cv::descr_of(mat), mat.ptr(), mat.step1());
+    expect_eq_desc(view, desc);
+    EXPECT_EQ(view.ptr(), mat.ptr());
+    EXPECT_EQ(view.step(), mat.step1());
+}
+
+TEST(RMatView, TestConstructionFromMatND) {
+    std::vector<int> dims(4, 8);
+    Mat mat(dims, CV_8UC1);
+    const auto desc = cv::descr_of(mat);
+    View view(cv::descr_of(mat), mat.ptr());
+    expect_eq_desc(view, desc);
+    EXPECT_EQ(view.ptr(), mat.ptr());
+}
+
+TEST_P(RMatViewTest, DefaultStep) {
+    auto type = GetParam();
+    GMatDesc desc;
+    desc.chan = CV_MAT_CN(type);
+    desc.depth = CV_MAT_DEPTH(type);
+    desc.size = {8,8};
+    std::vector<unsigned char> data(desc.size.width*desc.size.height*CV_ELEM_SIZE(type));
+    View view(desc, data.data());
+    EXPECT_EQ(view.step(), static_cast<size_t>(desc.size.width)*CV_ELEM_SIZE(type));
+}
+
+static Mat asMat(View& view) {
+    return Mat(view.size(), view.type(), view.ptr(), view.step());
+}
+
+TEST_P(RMatViewTest, NonDefaultStepInput) {
+    auto type = GetParam();
+    Mat bigMat(16,16,type);
+    cv::randn(bigMat, cv::Scalar::all(127), cv::Scalar::all(40));
+    Mat mat = bigMat(cv::Rect{4,4,8,8});
+    View view(cv::descr_of(mat), mat.data, mat.step);
+    const auto viewMat = asMat(view);
+    Mat ref, out;
+    cv::Size ksize{1,1};
+    cv::blur(viewMat, out, ksize);
+    cv::blur(    mat, ref, ksize);
+    EXPECT_EQ(0, cvtest::norm(ref, out, NORM_INF));
+}
+
+TEST_P(RMatViewTest, NonDefaultStepOutput) {
+    auto type = GetParam();
+    Mat mat(8,8,type);
+    cv::randn(mat, cv::Scalar::all(127), cv::Scalar::all(40));
+    Mat bigMat = Mat::zeros(16,16,type);
+    Mat out = bigMat(cv::Rect{4,4,8,8});
+    View view(cv::descr_of(out), out.ptr(), out.step);
+    auto viewMat = asMat(view);
+    Mat ref;
+    cv::Size ksize{1,1};
+    cv::blur(mat, viewMat, ksize);
+    cv::blur(mat, ref,     ksize);
+    EXPECT_EQ(0, cvtest::norm(ref, out, NORM_INF));
+}
+
+INSTANTIATE_TEST_CASE_P(Test, RMatViewTest,
+                        Values(CV_8UC1, CV_8UC3, CV_32FC1));
+
+struct RMatViewCallbackTest : public ::testing::Test {
+    RMatViewCallbackTest()
+        : mat(8,8,CV_8UC1), view(cv::descr_of(mat), mat.ptr(), mat.step1(), [this](){ callbackCalls++; }) {
+        cv::randn(mat, cv::Scalar::all(127), cv::Scalar::all(40));
+    }
+    int callbackCalls = 0;
+    Mat mat;
+    View view;
+};
+
+TEST_F(RMatViewCallbackTest, MoveCopy) {
+    {
+        View copy(std::move(view));
+        cv::util::suppress_unused_warning(copy);
+        EXPECT_EQ(callbackCalls, 0);
+    }
+    EXPECT_EQ(callbackCalls, 1);
+}
+
+static int firstElement(const View& view) { return *view.ptr(); }
+static void setFirstElement(View& view, uchar value) { *view.ptr() = value; }
+
+TEST_F(RMatViewCallbackTest, MagazineInteraction) {
+    cv::gimpl::magazine::Class<View> mag;
+    constexpr int rc = 1;
+    constexpr uchar value = 11;
+    mag.slot<View>()[rc] = std::move(view);
+    {
+        auto& mag_view = mag.slot<View>()[rc];
+        setFirstElement(mag_view, value);
+        auto mag_el = firstElement(mag_view);
+        EXPECT_EQ(mag_el, value);
+    }
+    {
+        const auto& mag_view = mag.slot<View>()[rc];
+        auto mag_el = firstElement(mag_view);
+        EXPECT_EQ(mag_el, value);
+    }
+    EXPECT_EQ(callbackCalls, 0);
+    mag.slot<View>().erase(rc);
+    EXPECT_EQ(callbackCalls, 1);
+}
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/s11n/gapi_s11n_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/s11n/gapi_s11n_tests.cpp
new file mode 100644 (file)
index 0000000..5b5be99
--- /dev/null
@@ -0,0 +1,351 @@
+#include "../test_precomp.hpp"
+
+#include "backends/common/serialization.hpp"
+
+namespace opencv_test {
+
+struct S11N_Basic: public ::testing::Test {
+    template<typename T> void put(T &&t) {
+        cv::gimpl::s11n::ByteMemoryOutStream os;
+        os << t;
+        m_buffer = os.data();
+    }
+
+    template<typename T> T get() {
+        // FIXME: This stream API needs a fix-up
+        cv::gimpl::s11n::ByteMemoryInStream is(m_buffer);
+        T t{};
+        is >> t;
+        return t;
+    }
+
+private:
+    std::vector<char> m_buffer;
+};
+
+namespace
+{
+    template<typename T>
+    bool operator==(const cv::detail::VectorRef& a, const cv::detail::VectorRef& b)
+    {
+        return a.rref<T>() == b.rref<T>();
+    }
+
+    template<typename T>
+    bool operator==(const cv::detail::OpaqueRef& a, const cv::detail::OpaqueRef& b)
+    {
+        return a.rref<T>() == b.rref<T>();
+    }
+}
+
+TEST_F(S11N_Basic, Test_int_pos) {
+    int x = 42;
+    put(x);
+    EXPECT_EQ(x, get<int>());
+}
+
+TEST_F(S11N_Basic, Test_int_neg) {
+    int x = -42;
+    put(x);
+    EXPECT_EQ(x, get<int>());
+}
+
+TEST_F(S11N_Basic, Test_fp32) {
+    float x = 3.14f;
+    put(x);
+    EXPECT_EQ(x, get<float>());
+}
+
+TEST_F(S11N_Basic, Test_fp64) {
+    double x = 3.14;
+    put(x);
+    EXPECT_EQ(x, get<double>());
+}
+
+TEST_F(S11N_Basic, Test_vector_int) {
+    std::vector<int> v = {1,2,3};
+    put(v);
+    EXPECT_EQ(v, get<std::vector<int> >());
+}
+
+TEST_F(S11N_Basic, Test_vector_cvSize) {
+    std::vector<cv::Size> v = {
+        cv::Size(640, 480),
+        cv::Size(1280, 1024),
+    };
+    put(v);
+    EXPECT_EQ(v, get<std::vector<cv::Size> >());
+}
+
+TEST_F(S11N_Basic, Test_vector_string) {
+    std::vector<std::string> v = {
+        "hello",
+        "world",
+        "ok!"
+    };
+    put(v);
+    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> >());
+}
+
+TEST_F(S11N_Basic, Test_variant) {
+    using S = std::string;
+    using V = cv::util::variant<int,S>;
+    V v1{42}, v2{S{"hey"}};
+
+    put(v1);
+    EXPECT_EQ(v1, get<V>());
+
+    put(v2);
+    EXPECT_EQ(v2, get<V>());
+}
+
+TEST_F(S11N_Basic, Test_GArg_int) {
+    const int x = 42;
+    cv::GArg gs(x);
+    put(gs);
+
+    cv::GArg gd = get<cv::GArg>();
+    EXPECT_EQ(cv::detail::ArgKind::OPAQUE_VAL, gd.kind);
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, gd.opaque_kind);
+    EXPECT_EQ(x, gs.get<int>());
+}
+
+TEST_F(S11N_Basic, Test_GArg_Point) {
+    const cv::Point pt{1,2};
+    cv::GArg gs(pt);
+    put(gs);
+
+    cv::GArg gd = get<cv::GArg>();
+    EXPECT_EQ(cv::detail::ArgKind::OPAQUE_VAL, gd.kind);
+    EXPECT_EQ(cv::detail::OpaqueKind::CV_POINT, gd.opaque_kind);
+    EXPECT_EQ(pt, gs.get<cv::Point>());
+}
+
+TEST_F(S11N_Basic, Test_Mat_full) {
+    auto mat = cv::Mat::eye(cv::Size(64,64), CV_8UC3);
+    put(mat);
+    EXPECT_EQ(0, cv::norm(mat, get<cv::Mat>(), cv::NORM_INF));
+}
+
+TEST_F(S11N_Basic, Test_Mat_view) {
+    auto mat  = cv::Mat::eye(cv::Size(320,240), CV_8UC3);
+    auto view = mat(cv::Rect(10,15,123,70));
+    put(view);
+    EXPECT_EQ(0, cv::norm(view, get<cv::Mat>(), cv::NORM_INF));
+}
+
+TEST_F(S11N_Basic, Test_MatDesc) {
+    cv::GMatDesc v = { CV_8U, 1, {320,240} };
+    put(v);
+    EXPECT_EQ(v, get<cv::GMatDesc>());
+}
+
+TEST_F(S11N_Basic, Test_MetaArg_MatDesc) {
+    cv::GMatDesc desc = { CV_8U, 1,{ 320,240 } };
+    auto v = cv::GMetaArg{ desc };
+    put(v);
+    cv::GMetaArg out_v = get<cv::GMetaArg>();
+    cv::GMatDesc out_desc = cv::util::get<cv::GMatDesc>(out_v);
+    EXPECT_EQ(desc, out_desc);
+}
+
+TEST_F(S11N_Basic, Test_MetaArgs_MatDesc) {
+    cv::GMatDesc desc1 = { CV_8U, 1,{ 320,240 } };
+    cv::GMatDesc desc2 = { CV_8U, 1,{ 640,480 } };
+    GMetaArgs v;
+    v.resize(2);
+    v[0] = cv::GMetaArg{ desc1 };
+    v[1] = cv::GMetaArg{ desc2 };
+    put(v);
+    cv::GMetaArgs out_v = get<cv::GMetaArgs>();
+    cv::GMatDesc out_desc1 = cv::util::get<cv::GMatDesc>(out_v[0]);
+    cv::GMatDesc out_desc2 = cv::util::get<cv::GMatDesc>(out_v[1]);
+    EXPECT_EQ(desc1, out_desc1);
+    EXPECT_EQ(desc2, out_desc2);
+}
+
+TEST_F(S11N_Basic, Test_MetaArg_Monostate) {
+    GMetaArg v;
+    put(v);
+    cv::GMetaArg out_v = get<cv::GMetaArg>();
+    if (!util::holds_alternative<util::monostate>(out_v))
+    {
+        GTEST_FAIL();
+    }
+}
+
+TEST_F(S11N_Basic, Test_RunArg_Mat) {
+    cv::Mat mat = cv::Mat::eye(cv::Size(64, 64), CV_8UC3);
+    auto v = cv::GRunArg{ mat };
+    put(v);
+    cv::GRunArg out_v = get<cv::GRunArg>();
+    cv::Mat out_mat = cv::util::get<cv::Mat>(out_v);
+    EXPECT_EQ(0, cv::norm(mat, out_mat, cv::NORM_INF));
+}
+
+TEST_F(S11N_Basic, Test_RunArgs_Mat) {
+    cv::Mat mat1 = cv::Mat::eye(cv::Size(64, 64), CV_8UC3);
+    cv::Mat mat2 = cv::Mat::eye(cv::Size(128, 128), CV_8UC3);
+    GRunArgs v;
+    v.resize(2);
+    v[0] = cv::GRunArg{ mat1 };
+    v[1] = cv::GRunArg{ mat2 };
+    put(v);
+    cv::GRunArgs out_v = get<cv::GRunArgs>();
+    cv::Mat out_mat1 = cv::util::get<cv::Mat>(out_v[0]);
+    cv::Mat out_mat2 = cv::util::get<cv::Mat>(out_v[1]);
+    EXPECT_EQ(0, cv::norm(mat1, out_mat1, cv::NORM_INF));
+    EXPECT_EQ(0, cv::norm(mat2, out_mat2, cv::NORM_INF));
+}
+
+TEST_F(S11N_Basic, Test_RunArg_Scalar) {
+    cv::Scalar scalar = cv::Scalar(128, 33, 53);
+    auto v = cv::GRunArg{ scalar };
+    put(v);
+    cv::GRunArg out_v = get<cv::GRunArg>();
+    cv::Scalar out_scalar = cv::util::get<cv::Scalar>(out_v);
+    EXPECT_EQ(scalar, out_scalar);
+}
+
+TEST_F(S11N_Basic, Test_RunArgs_Scalar) {
+    cv::Scalar scalar1 = cv::Scalar(128, 33, 53);
+    cv::Scalar scalar2 = cv::Scalar(64, 15, 23);
+    GRunArgs v;
+    v.resize(2);
+    v[0] = cv::GRunArg{ scalar1 };
+    v[1] = cv::GRunArg{ scalar2 };
+    put(v);
+    cv::GRunArgs out_v = get<cv::GRunArgs>();
+    cv::Scalar out_scalar1 = cv::util::get<cv::Scalar>(out_v[0]);
+    cv::Scalar out_scalar2 = cv::util::get<cv::Scalar>(out_v[1]);
+    EXPECT_EQ(scalar1, out_scalar1);
+    EXPECT_EQ(scalar2, out_scalar2);
+}
+
+TEST_F(S11N_Basic, Test_RunArg_Opaque) {
+    auto op = cv::detail::OpaqueRef(42);
+    auto v = cv::GRunArg{ op };
+    put(v);
+    cv::GRunArg out_v = get<cv::GRunArg>();
+    cv::detail::OpaqueRef out_op = cv::util::get<cv::detail::OpaqueRef>(out_v);
+    EXPECT_TRUE(operator==<int>(op, out_op));
+}
+
+TEST_F(S11N_Basic, Test_RunArgs_Opaque) {
+    cv::detail::OpaqueRef op1 = cv::detail::OpaqueRef(cv::Point(1, 2));
+    cv::detail::OpaqueRef op2 = cv::detail::OpaqueRef(cv::Size(12, 21));
+    GRunArgs v;
+    v.resize(2);
+    v[0] = cv::GRunArg{ op1 };
+    v[1] = cv::GRunArg{ op2 };
+    put(v);
+    cv::GRunArgs out_v = get<cv::GRunArgs>();
+    cv::detail::OpaqueRef out_op1 = cv::util::get<cv::detail::OpaqueRef>(out_v[0]);
+    cv::detail::OpaqueRef out_op2 = cv::util::get<cv::detail::OpaqueRef>(out_v[1]);
+    EXPECT_TRUE(operator==<cv::Point>(op1, out_op1));
+    EXPECT_TRUE(operator==<cv::Size>(op2, out_op2));
+}
+
+TEST_F(S11N_Basic, Test_RunArg_Array) {
+    auto op = cv::detail::VectorRef(std::vector<cv::Mat>{cv::Mat::eye(3, 3, CV_8UC1), cv::Mat::zeros(5, 5, CV_8UC3)});
+
+    auto v = cv::GRunArg{ op };
+    put(v);
+    cv::GRunArg out_v = get<cv::GRunArg>();
+    cv::detail::VectorRef out_op = cv::util::get<cv::detail::VectorRef>(out_v);
+    auto vec1 = op.rref<cv::Mat>();
+    auto vec2 = out_op.rref<cv::Mat>();
+    EXPECT_EQ(0, cv::norm(vec1[0], vec2[0], cv::NORM_INF));
+    EXPECT_EQ(0, cv::norm(vec1[1], vec2[1], cv::NORM_INF));
+}
+
+TEST_F(S11N_Basic, Test_RunArgs_Array) {
+    auto vec_sc = std::vector<cv::Scalar>{cv::Scalar(11), cv::Scalar(31)};
+    auto vec_d = std::vector<double>{0.4, 1.0, 123.55, 22.08};
+    cv::detail::VectorRef op1 = cv::detail::VectorRef(vec_sc);
+    cv::detail::VectorRef op2 = cv::detail::VectorRef(vec_d);
+    GRunArgs v;
+    v.resize(2);
+    v[0] = cv::GRunArg{ op1 };
+    v[1] = cv::GRunArg{ op2 };
+    put(v);
+    cv::GRunArgs out_v = get<cv::GRunArgs>();
+    cv::detail::VectorRef out_op1 = cv::util::get<cv::detail::VectorRef>(out_v[0]);
+    cv::detail::VectorRef out_op2 = cv::util::get<cv::detail::VectorRef>(out_v[1]);
+    EXPECT_TRUE(operator==<cv::Scalar>(op1, out_op1));
+    EXPECT_TRUE(operator==<double>(op2, out_op2));
+}
+
+TEST_F(S11N_Basic, Test_RunArgs_MatScalar) {
+    cv::Mat mat = cv::Mat::eye(cv::Size(64, 64), CV_8UC3);
+    cv::Scalar scalar = cv::Scalar(128, 33, 53);
+    GRunArgs v;
+    v.resize(2);
+    v[0] = cv::GRunArg{ mat };
+    v[1] = cv::GRunArg{ scalar };
+    put(v);
+    cv::GRunArgs out_v = get<cv::GRunArgs>();
+    unsigned int i = 0;
+    for (auto it : out_v)
+    {
+        using T = cv::GRunArg;
+        switch (it.index())
+        {
+        case T::index_of<cv::Mat>() :
+        {
+            cv::Mat out_mat = cv::util::get<cv::Mat>(out_v[i]);
+            EXPECT_EQ(0, cv::norm(mat, out_mat, cv::NORM_INF));
+        } break;
+        case T::index_of<cv::Scalar>() :
+        {
+            cv::Scalar out_scalar = cv::util::get<cv::Scalar>(out_v[i]);
+            EXPECT_EQ(scalar, out_scalar);
+        } break;
+        default:
+            GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode.
+            break;
+        }
+        i++;
+    }
+}
+
+TEST_F(S11N_Basic, Test_Bind_RunArgs_MatScalar) {
+    cv::Mat mat = cv::Mat::eye(cv::Size(128, 64), CV_8UC3);
+    cv::Scalar scalar = cv::Scalar(128, 33, 53);
+    GRunArgs v;
+    v.resize(2);
+    v[0] = cv::GRunArg{ mat };
+    v[1] = cv::GRunArg{ scalar };
+    GRunArgsP output = cv::gapi::bind(v);
+    unsigned int i = 0;
+    for (auto it : output)
+    {
+        using T = cv::GRunArgP;
+        switch (it.index())
+        {
+        case T::index_of<cv::Mat*>() :
+        {
+            cv::Mat* out_mat = cv::util::get<cv::Mat*>(it);
+            EXPECT_EQ(mat.size(), out_mat->size());
+        } break;
+        case T::index_of<cv::Scalar*>() :
+        {
+            cv::Scalar* out_scalar = cv::util::get<cv::Scalar*>(it);
+            EXPECT_EQ(out_scalar->val[0], scalar.val[0]);
+            EXPECT_EQ(out_scalar->val[1], scalar.val[1]);
+            EXPECT_EQ(out_scalar->val[2], scalar.val[2]);
+        } break;
+        default:
+            GAPI_Assert(false && "This value type is not supported!"); // ...maybe because of STANDALONE mode.
+            break;
+        }
+        i++;
+    }
+}
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp
new file mode 100644 (file)
index 0000000..1d8f751
--- /dev/null
@@ -0,0 +1,710 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2020 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+
+#include <ade/util/iota_range.hpp>
+#include <opencv2/gapi/s11n.hpp>
+#include "api/render_priv.hpp"
+#include "../common/gapi_render_tests.hpp"
+
+namespace opencv_test
+{
+
+TEST(S11N, Pipeline_Crop_Rect)
+{
+    cv::Rect rect_to{ 4,10,37,50 };
+    cv::Size sz_in = cv::Size(1920, 1080);
+    cv::Size sz_out = cv::Size(37, 50);
+    cv::Mat in_mat = cv::Mat::eye(sz_in, CV_8UC1);
+    cv::Mat out_mat_gapi(sz_out, CV_8UC1);
+    cv::Mat out_mat_ocv(sz_out, CV_8UC1);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    auto out = cv::gapi::crop(in, rect_to);
+    auto p = cv::gapi::serialize(cv::GComputation(in, out));
+    auto c = cv::gapi::deserialize<cv::GComputation>(p);
+    c.apply(in_mat, out_mat_gapi);
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        out_mat_ocv = in_mat(rect_to);
+    }
+    // Comparison //////////////////////////////////////////////////////////////
+    {
+        EXPECT_EQ(0, cvtest::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+    }
+}
+
+
+TEST(S11N, Pipeline_Canny_Bool)
+{
+    const cv::Size sz_in(1280, 720);
+    cv::GMat in;
+    double thrLow = 120.0;
+    double thrUp = 240.0;
+    int apSize = 5;
+    bool l2gr = true;
+    cv::Mat in_mat = cv::Mat::eye(1280, 720, CV_8UC1);
+    cv::Mat out_mat_gapi(sz_in, CV_8UC1);
+    cv::Mat out_mat_ocv(sz_in, CV_8UC1);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    auto out = cv::gapi::Canny(in, thrLow, thrUp, apSize, l2gr);
+    auto p = cv::gapi::serialize(cv::GComputation(in, out));
+    auto c = cv::gapi::deserialize<cv::GComputation>(p);
+    c.apply(in_mat, out_mat_gapi);
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::Canny(in_mat, out_mat_ocv, thrLow, thrUp, apSize, l2gr);
+    }
+    // Comparison //////////////////////////////////////////////////////////////
+    EXPECT_EQ(0, cvtest::norm(out_mat_gapi, out_mat_ocv, NORM_INF));
+}
+
+TEST(S11N, Pipeline_Not)
+{
+    cv::GMat in;
+    auto p = cv::gapi::serialize(cv::GComputation(in, cv::gapi::bitwise_not(in)));
+    auto c = cv::gapi::deserialize<cv::GComputation>(p);
+
+    cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
+    cv::Mat ref_mat = ~in_mat;
+
+    cv::Mat out_mat;
+    c.apply(in_mat, out_mat);
+    EXPECT_EQ(0, cvtest::norm(out_mat, ref_mat, NORM_INF));
+
+    out_mat = cv::Mat();
+    auto cc = c.compile(cv::descr_of(in_mat));
+    cc(in_mat, out_mat);
+    EXPECT_EQ(0, cvtest::norm(out_mat, ref_mat, NORM_INF));
+}
+
+TEST(S11N, Pipeline_Sum_Scalar)
+{
+    cv::GMat in;
+    auto p = cv::gapi::serialize(cv::GComputation(in, cv::gapi::sum(in)));
+    auto c = cv::gapi::deserialize<cv::GComputation>(p);
+
+    cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
+    cv::Scalar ref_scl = cv::sum(in_mat);
+
+    cv::Scalar out_scl;
+    c.apply(in_mat, out_scl);
+    EXPECT_EQ(out_scl, ref_scl);
+
+    out_scl = cv::Scalar();
+    auto cc = c.compile(cv::descr_of(in_mat));
+    cc(in_mat, out_scl);
+    EXPECT_EQ(out_scl, ref_scl);
+}
+
+TEST(S11N, Pipeline_BinaryOp)
+{
+    cv::GMat a, b;
+    auto p = cv::gapi::serialize(cv::GComputation(a, b, cv::gapi::add(a, b)));
+    auto c = cv::gapi::deserialize<cv::GComputation>(p);
+
+    cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
+    cv::Mat ref_mat = (in_mat + in_mat);
+
+    cv::Mat out_mat;
+    c.apply(in_mat, in_mat, out_mat);
+    EXPECT_EQ(0, cvtest::norm(out_mat, ref_mat, NORM_INF));
+
+    out_mat = cv::Mat();
+    auto cc = c.compile(cv::descr_of(in_mat), cv::descr_of(in_mat));
+    cc(in_mat, in_mat, out_mat);
+    EXPECT_EQ(0, cvtest::norm(out_mat, ref_mat, NORM_INF));
+}
+
+TEST(S11N, Pipeline_Binary_Sum_Scalar)
+{
+    cv::GMat a, b;
+    auto p = cv::gapi::serialize(cv::GComputation(a, b, cv::gapi::sum(a + b)));
+    auto c = cv::gapi::deserialize<cv::GComputation>(p);
+
+    cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
+    cv::Scalar ref_scl = cv::sum(in_mat + in_mat);
+    cv::Scalar out_scl;
+    c.apply(in_mat, in_mat, out_scl);
+    EXPECT_EQ(out_scl, ref_scl);
+
+    out_scl = cv::Scalar();
+    auto cc = c.compile(cv::descr_of(in_mat), cv::descr_of(in_mat));
+    cc(in_mat, in_mat, out_scl);
+    EXPECT_EQ(out_scl, ref_scl);
+}
+
+TEST(S11N, Pipeline_Sharpen)
+{
+    const cv::Size sz_in (1280, 720);
+    const cv::Size sz_out( 640, 480);
+    cv::Mat in_mat (sz_in,  CV_8UC3);
+    in_mat = cv::Scalar(128, 33, 53);
+
+    cv::Mat out_mat(sz_out, CV_8UC3);
+    cv::Mat out_mat_y;
+    cv::Mat out_mat_ocv(sz_out, CV_8UC3);
+
+    float sharpen_coeffs[] = {
+         0.0f, -1.f,  0.0f,
+        -1.0f,  5.f, -1.0f,
+         0.0f, -1.f,  0.0f
+    };
+    cv::Mat sharpen_kernel(3, 3, CV_32F, sharpen_coeffs);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::GMat in;
+    auto vga     = cv::gapi::resize(in, sz_out);
+    auto yuv     = cv::gapi::RGB2YUV(vga);
+    auto yuv_p   = cv::gapi::split3(yuv);
+    auto y_sharp = cv::gapi::filter2D(std::get<0>(yuv_p), -1, sharpen_kernel);
+    auto yuv_new = cv::gapi::merge3(y_sharp, std::get<1>(yuv_p), std::get<2>(yuv_p));
+    auto out     = cv::gapi::YUV2RGB(yuv_new);
+
+    auto p = cv::gapi::serialize(cv::GComputation(cv::GIn(in), cv::GOut(y_sharp, out)));
+    auto c = cv::gapi::deserialize<cv::GComputation>(p);
+    c.apply(cv::gin(in_mat), cv::gout(out_mat_y, out_mat));
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::Mat smaller;
+        cv::resize(in_mat, smaller, sz_out);
+
+        cv::Mat yuv_mat;
+        cv::cvtColor(smaller, yuv_mat, cv::COLOR_RGB2YUV);
+        std::vector<cv::Mat> yuv_planar(3);
+        cv::split(yuv_mat, yuv_planar);
+        cv::filter2D(yuv_planar[0], yuv_planar[0], -1, sharpen_kernel);
+        cv::merge(yuv_planar, yuv_mat);
+        cv::cvtColor(yuv_mat, out_mat_ocv, cv::COLOR_YUV2RGB);
+    }
+
+    // Comparison //////////////////////////////////////////////////////////////
+    {
+        cv::Mat diff = out_mat_ocv != out_mat;
+        std::vector<cv::Mat> diffBGR(3);
+        cv::split(diff, diffBGR);
+        EXPECT_EQ(0, cvtest::norm(diffBGR[0], NORM_INF));
+        EXPECT_EQ(0, cvtest::norm(diffBGR[1], NORM_INF));
+        EXPECT_EQ(0, cvtest::norm(diffBGR[2], NORM_INF));
+    }
+
+    // Metadata check /////////////////////////////////////////////////////////
+    {
+        auto cc    = c.compile(cv::descr_of(in_mat));
+        auto metas = cc.outMetas();
+        ASSERT_EQ(2u, metas.size());
+
+        auto out_y_meta = cv::util::get<cv::GMatDesc>(metas[0]);
+        auto out_meta   = cv::util::get<cv::GMatDesc>(metas[1]);
+
+        // Y-output
+        EXPECT_EQ(CV_8U,   out_y_meta.depth);
+        EXPECT_EQ(1,       out_y_meta.chan);
+        EXPECT_EQ(640,     out_y_meta.size.width);
+        EXPECT_EQ(480,     out_y_meta.size.height);
+
+        // Final output
+        EXPECT_EQ(CV_8U,   out_meta.depth);
+        EXPECT_EQ(3,       out_meta.chan);
+        EXPECT_EQ(640,     out_meta.size.width);
+        EXPECT_EQ(480,     out_meta.size.height);
+    }
+}
+
+TEST(S11N, Pipeline_CustomRGB2YUV)
+{
+    const cv::Size sz(1280, 720);
+    const int INS = 3;
+    std::vector<cv::Mat> in_mats(INS);
+    for (auto i : ade::util::iota(INS))
+    {
+        in_mats[i].create(sz, CV_8U);
+        cv::randu(in_mats[i], cv::Scalar::all(0), cv::Scalar::all(255));
+    }
+
+    const int OUTS = 3;
+    std::vector<cv::Mat> out_mats_cv(OUTS);
+    std::vector<cv::Mat> out_mats_gapi(OUTS);
+    for (auto i : ade::util::iota(OUTS))
+    {
+        out_mats_cv[i].create(sz, CV_8U);
+        out_mats_gapi[i].create(sz, CV_8U);
+    }
+
+    // G-API code //////////////////////////////////////////////////////////////
+    {
+        cv::GMat r, g, b;
+        cv::GMat y = 0.299f*r + 0.587f*g + 0.114f*b;
+        cv::GMat u = 0.492f*(b - y);
+        cv::GMat v = 0.877f*(r - y);
+
+        auto p = cv::gapi::serialize(cv::GComputation({r, g, b}, {y, u, v}));
+        auto c = cv::gapi::deserialize<cv::GComputation>(p);
+        c.apply(in_mats, out_mats_gapi);
+    }
+
+    // OpenCV code /////////////////////////////////////////////////////////////
+    {
+        cv::Mat r = in_mats[0], g = in_mats[1], b = in_mats[2];
+        cv::Mat y = 0.299f*r + 0.587f*g + 0.114f*b;
+        cv::Mat u = 0.492f*(b - y);
+        cv::Mat v = 0.877f*(r - y);
+
+        out_mats_cv[0] = y;
+        out_mats_cv[1] = u;
+        out_mats_cv[2] = v;
+    }
+
+    // Comparison //////////////////////////////////////////////////////////////
+    {
+        const auto diff = [](cv::Mat m1, cv::Mat m2, int t) {
+            return cv::abs(m1 - m2) > t;
+        };
+
+        // FIXME: Not bit-accurate even now!
+        cv::Mat
+            diff_y = diff(out_mats_cv[0], out_mats_gapi[0], 2),
+            diff_u = diff(out_mats_cv[1], out_mats_gapi[1], 2),
+            diff_v = diff(out_mats_cv[2], out_mats_gapi[2], 2);
+
+        EXPECT_EQ(0, cvtest::norm(diff_y, NORM_INF));
+        EXPECT_EQ(0, cvtest::norm(diff_u, NORM_INF));
+        EXPECT_EQ(0, cvtest::norm(diff_v, NORM_INF));
+    }
+}
+
+namespace ThisTest
+{
+    using GOpBool = GOpaque<bool>;
+    using GOpInt = GOpaque<int>;
+    using GOpDouble = GOpaque<double>;
+    using GOpPoint = GOpaque<cv::Point>;
+    using GOpSize = GOpaque<cv::Size>;
+    using GOpRect = GOpaque<cv::Rect>;
+
+    using GOpOut = std::tuple<GOpPoint, GOpSize, GOpRect>;
+
+    G_TYPED_KERNEL_M(OpGenerate, <GOpOut(GOpBool, GOpInt, GOpDouble)>, "test.s11n.gopaque")
+    {
+        static std::tuple<GOpaqueDesc, GOpaqueDesc, GOpaqueDesc> outMeta(const GOpaqueDesc&, const GOpaqueDesc&, const GOpaqueDesc&) {
+            return std::make_tuple(empty_gopaque_desc(), empty_gopaque_desc(), empty_gopaque_desc());
+        }
+    };
+
+    GAPI_OCV_KERNEL(OCVOpGenerate, OpGenerate)
+    {
+        static void run(const bool& b, const int& i, const double& d,
+                        cv::Point& p, cv::Size& s, cv::Rect& r)
+        {
+            p = cv::Point(i, i*2);
+            s = b ? cv::Size(42, 42) : cv::Size(7, 7);
+            int ii = static_cast<int>(d);
+            r = cv::Rect(ii, ii, ii, ii);
+        }
+    };
+
+    using GArrInt = GArray<int>;
+    using GArrDouble = GArray<double>;
+    using GArrPoint = GArray<cv::Point>;
+    using GArrSize = GArray<cv::Size>;
+    using GArrRect = GArray<cv::Rect>;
+    using GArrMat = GArray<cv::Mat>;
+    using GArrScalar = GArray<cv::Scalar>;
+
+    using GArrOut = std::tuple<GArrPoint, GArrSize, GArrRect, GArrMat>;
+
+    G_TYPED_KERNEL_M(ArrGenerate, <GArrOut(GArrInt, GArrInt, GArrDouble, GArrScalar)>, "test.s11n.garray")
+    {
+        static std::tuple<GArrayDesc, GArrayDesc, GArrayDesc, GArrayDesc> outMeta(const GArrayDesc&, const GArrayDesc&,
+                                                                                  const GArrayDesc&, const GArrayDesc&) {
+            return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc(), empty_array_desc());
+        }
+    };
+
+    GAPI_OCV_KERNEL(OCVArrGenerate, ArrGenerate)
+    {
+        static void run(const std::vector<int>& b, const std::vector<int>& i,
+                        const std::vector<double>& d, const std::vector<cv::Scalar>& sc,
+                        std::vector<cv::Point>& p, std::vector<cv::Size>& s,
+                        std::vector<cv::Rect>& r, std::vector<cv::Mat>& m)
+        {
+            p.clear(); p.resize(b.size());
+            s.clear(); s.resize(b.size());
+            r.clear(); r.resize(b.size());
+            m.clear(); m.resize(b.size());
+
+            for (std::size_t idx = 0; idx < b.size(); ++idx)
+            {
+                p[idx] = cv::Point(i[idx], i[idx]*2);
+                s[idx] = b[idx] == 1 ? cv::Size(42, 42) : cv::Size(7, 7);
+                int ii = static_cast<int>(d[idx]);
+                r[idx] = cv::Rect(ii, ii, ii, ii);
+                m[idx] = cv::Mat(3, 3, CV_8UC1, sc[idx]);
+            }
+        }
+    };
+
+    G_TYPED_KERNEL_M(OpArrK1, <std::tuple<GArrInt,GOpSize>(GOpInt, GArrSize)>, "test.s11n.oparrk1")
+    {
+        static std::tuple<GArrayDesc, GOpaqueDesc> outMeta(const GOpaqueDesc&, const GArrayDesc&) {
+            return std::make_tuple(empty_array_desc(), empty_gopaque_desc());
+        }
+    };
+
+    GAPI_OCV_KERNEL(OCVOpArrK1, OpArrK1)
+    {
+        static void run(const int& i, const std::vector<cv::Size>& vs,
+                        std::vector<int>& vi, cv::Size& s)
+        {
+            vi.clear(); vi.resize(vs.size());
+            s = cv::Size(i, i);
+            for (std::size_t idx = 0; idx < vs.size(); ++ idx)
+                vi[idx] = vs[idx].area();
+        }
+    };
+
+    G_TYPED_KERNEL_M(OpArrK2, <std::tuple<GOpDouble,GArrPoint>(GArrInt, GOpSize)>, "test.s11n.oparrk2")
+    {
+        static std::tuple<GOpaqueDesc, GArrayDesc> outMeta(const GArrayDesc&, const GOpaqueDesc&) {
+            return std::make_tuple(empty_gopaque_desc(), empty_array_desc());
+        }
+    };
+
+    GAPI_OCV_KERNEL(OCVOpArrK2, OpArrK2)
+    {
+        static void run(const std::vector<int>& vi, const cv::Size& s,
+                        double& d, std::vector<cv::Point>& vp)
+        {
+            vp.clear(); vp.resize(vi.size());
+            d = s.area() * 1.5;
+            for (std::size_t idx = 0; idx < vi.size(); ++ idx)
+                vp[idx] = cv::Point(vi[idx], vi[idx]);
+        }
+    };
+} // namespace ThisTest
+
+TEST(S11N, Pipeline_GOpaque)
+{
+    using namespace ThisTest;
+    GOpBool in1;
+    GOpInt in2;
+    GOpDouble in3;
+
+    auto out = OpGenerate::on(in1, in2, in3);
+    cv::GComputation c(cv::GIn(in1, in2, in3), cv::GOut(std::get<0>(out), std::get<1>(out), std::get<2>(out)));
+
+    auto p = cv::gapi::serialize(c);
+    auto dc = cv::gapi::deserialize<cv::GComputation>(p);
+
+    bool b = true;
+    int i = 33;
+    double d = 128.7;
+    cv::Point pp;
+    cv::Size s;
+    cv::Rect r;
+    dc.apply(cv::gin(b, i, d), cv::gout(pp, s, r), cv::compile_args(cv::gapi::kernels<OCVOpGenerate>()));
+
+    EXPECT_EQ(pp, cv::Point(i, i*2));
+    EXPECT_EQ(s, cv::Size(42, 42));
+    int ii = static_cast<int>(d);
+    EXPECT_EQ(r, cv::Rect(ii, ii, ii, ii));
+}
+
+TEST(S11N, Pipeline_GArray)
+{
+    using namespace ThisTest;
+    GArrInt in1, in2;
+    GArrDouble in3;
+    GArrScalar in4;
+
+    auto out = ArrGenerate::on(in1, in2, in3, in4);
+    cv::GComputation c(cv::GIn(in1, in2, in3, in4),
+                       cv::GOut(std::get<0>(out), std::get<1>(out),
+                                std::get<2>(out), std::get<3>(out)));
+
+    auto p = cv::gapi::serialize(c);
+    auto dc = cv::gapi::deserialize<cv::GComputation>(p);
+
+    std::vector<int> b {1, 0, -1};
+    std::vector<int> i {3, 0 , 59};
+    std::vector<double> d {0.7, 120.5, 44.14};
+    std::vector<cv::Scalar> sc {cv::Scalar::all(10), cv::Scalar::all(15), cv::Scalar::all(99)};
+    std::vector<cv::Point> pp;
+    std::vector<cv::Size> s;
+    std::vector<cv::Rect> r;
+    std::vector<cv::Mat> m;
+    dc.apply(cv::gin(b, i, d, sc), cv::gout(pp, s, r, m), cv::compile_args(cv::gapi::kernels<OCVArrGenerate>()));
+
+    for (std::size_t idx = 0; idx < b.size(); ++idx)
+    {
+        EXPECT_EQ(pp[idx], cv::Point(i[idx], i[idx]*2));
+        EXPECT_EQ(s[idx], b[idx] == 1 ? cv::Size(42, 42) : cv::Size(7, 7));
+        int ii = static_cast<int>(d[idx]);
+        EXPECT_EQ(r[idx], cv::Rect(ii, ii, ii, ii));
+    }
+}
+
+TEST(S11N, Pipeline_GArray_GOpaque_Multinode)
+{
+    using namespace ThisTest;
+    GOpInt in1;
+    GArrSize in2;
+
+    auto tmp = OpArrK1::on(in1, in2);
+    auto out = OpArrK2::on(std::get<0>(tmp), std::get<1>(tmp));
+
+    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);
+
+    int i = 42;
+    std::vector<cv::Size> s{cv::Size(11, 22), cv::Size(13, 18)};
+    double d;
+    std::vector<cv::Point> pp;
+
+    dc.apply(cv::gin(i, s), cv::gout(d, pp), cv::compile_args(cv::gapi::kernels<OCVOpArrK1, OCVOpArrK2>()));
+
+    auto st = cv::Size(i ,i);
+    EXPECT_EQ(d, st.area() * 1.5);
+
+    for (std::size_t idx = 0; idx < s.size(); ++idx)
+    {
+        EXPECT_EQ(pp[idx], cv::Point(s[idx].area(), s[idx].area()));
+    }
+}
+
+TEST(S11N, Pipeline_Render_NV12)
+{
+    cv::Size sz (100, 200);
+    int rects_num = 10;
+    int text_num  = 10;
+    int image_num = 10;
+
+    int thick = 2;
+    int lt = LINE_8;
+    cv::Scalar color(111, 222, 77);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+
+    // Rects
+    int shift = 0;
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect rect(200 + i, 200 + i, 200, 200);
+        prims.emplace_back(cv::gapi::wip::draw::Rect(rect, color, thick, lt, shift));
+    }
+
+    // Mosaic
+    int cellsz = 50;
+    int decim = 0;
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect mos(200 + i, 200 + i, 200, 200);
+        prims.emplace_back(cv::gapi::wip::draw::Mosaic(mos, cellsz, decim));
+    }
+
+    // Text
+    std::string text = "Some text";
+    int ff = FONT_HERSHEY_SIMPLEX;
+    double fs = 2.0;
+    bool blo = false;
+    for (int i = 0; i < text_num; ++i) {
+        cv::Point org(200 + i, 200 + i);
+        prims.emplace_back(cv::gapi::wip::draw::Text(text, org, ff, fs, color, thick, lt, blo));
+    }
+
+    // Image
+    double transparency = 1.0;
+    cv::Rect rect_img(0 ,0 , 50, 50);
+    cv::Mat img(rect_img.size(), CV_8UC3, color);
+    cv::Mat alpha(rect_img.size(), CV_32FC1, transparency);
+    auto tl = rect_img.tl();
+    for (int i = 0; i < image_num; ++i) {
+        cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
+
+        prims.emplace_back(cv::gapi::wip::draw::Image({org_img, img, alpha}));
+    }
+
+    // Circle
+    cv::Point center(300, 400);
+    int rad = 25;
+    prims.emplace_back(cv::gapi::wip::draw::Circle({center, rad, color, thick, lt, shift}));
+
+    // Line
+    cv::Point point_next(300, 425);
+    prims.emplace_back(cv::gapi::wip::draw::Line({center, point_next, color, thick, lt, shift}));
+
+    // Poly
+    std::vector<cv::Point> points = {{300, 400}, {290, 450}, {348, 410}, {300, 400}};
+    prims.emplace_back(cv::gapi::wip::draw::Poly({points, color, thick, lt, shift}));
+
+    cv::GMat y_in, uv_in, y_out, uv_out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
+    cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
+
+    auto serialized = cv::gapi::serialize(comp);
+    auto dc = cv::gapi::deserialize<cv::GComputation>(serialized);
+
+    cv::Mat y(1920, 1080, CV_8UC1);
+    cv::Mat uv(960, 540, CV_8UC2);
+    cv::randu(y, cv::Scalar(0), cv::Scalar(255));
+    cv::randu(uv, cv::Scalar::all(0), cv::Scalar::all(255));
+    cv::Mat y_ref_mat = y.clone(), uv_ref_mat = uv.clone();
+    dc.apply(cv::gin(y, uv, prims), cv::gout(y, uv));
+
+    // OpenCV code //////////////////////////////////////////////////////////////
+    cv::Mat yuv;
+    cv::gapi::wip::draw::cvtNV12ToYUV(y_ref_mat, uv_ref_mat, yuv);
+
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect rect(200 + i, 200 + i, 200, 200);
+        cv::rectangle(yuv, rect, cvtBGRToYUVC(color), thick, lt, shift);
+    }
+
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect mos(200 + i, 200 + i, 200, 200);
+         drawMosaicRef(yuv, mos, cellsz);
+    }
+
+    for (int i = 0; i < text_num; ++i) {
+        cv::Point org(200 + i, 200 + i);
+        cv::putText(yuv, text, org, ff, fs, cvtBGRToYUVC(color), thick, lt, blo);
+    }
+
+    for (int i = 0; i < image_num; ++i) {
+        cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
+        cv::Mat yuv_img;
+        cv::cvtColor(img, yuv_img, cv::COLOR_BGR2YUV);
+        blendImageRef(yuv, org_img, yuv_img, alpha);
+    }
+
+    cv::circle(yuv, center, rad, cvtBGRToYUVC(color), thick, lt, shift);
+    cv::line(yuv, center, point_next, cvtBGRToYUVC(color), thick, lt, shift);
+    std::vector<std::vector<cv::Point>> pp{points};
+    cv::fillPoly(yuv, pp, cvtBGRToYUVC(color), lt, shift);
+
+    // YUV -> NV12
+    cv::gapi::wip::draw::cvtYUVToNV12(yuv, y_ref_mat, uv_ref_mat);
+
+    EXPECT_EQ(cv::norm( y,  y_ref_mat), 0);
+    EXPECT_EQ(cv::norm(uv, uv_ref_mat), 0);
+}
+
+TEST(S11N, Pipeline_Render_RGB)
+{
+    cv::Size sz (100, 200);
+    int rects_num = 10;
+    int text_num  = 10;
+    int image_num = 10;
+
+    int thick = 2;
+    int lt = LINE_8;
+    cv::Scalar color(111, 222, 77);
+
+    // G-API code //////////////////////////////////////////////////////////////
+    cv::gapi::wip::draw::Prims prims;
+
+    // Rects
+    int shift = 0;
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect rect(200 + i, 200 + i, 200, 200);
+        prims.emplace_back(cv::gapi::wip::draw::Rect(rect, color, thick, lt, shift));
+    }
+
+    // Mosaic
+    int cellsz = 50;
+    int decim = 0;
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect mos(200 + i, 200 + i, 200, 200);
+        prims.emplace_back(cv::gapi::wip::draw::Mosaic(mos, cellsz, decim));
+    }
+
+    // Text
+    std::string text = "Some text";
+    int ff = FONT_HERSHEY_SIMPLEX;
+    double fs = 2.0;
+    bool blo = false;
+    for (int i = 0; i < text_num; ++i) {
+        cv::Point org(200 + i, 200 + i);
+        prims.emplace_back(cv::gapi::wip::draw::Text(text, org, ff, fs, color, thick, lt, blo));
+    }
+
+    // Image
+    double transparency = 1.0;
+    cv::Rect rect_img(0 ,0 , 50, 50);
+    cv::Mat img(rect_img.size(), CV_8UC3, color);
+    cv::Mat alpha(rect_img.size(), CV_32FC1, transparency);
+    auto tl = rect_img.tl();
+    for (int i = 0; i < image_num; ++i) {
+        cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
+
+        prims.emplace_back(cv::gapi::wip::draw::Image({org_img, img, alpha}));
+    }
+
+    // Circle
+    cv::Point center(300, 400);
+    int rad = 25;
+    prims.emplace_back(cv::gapi::wip::draw::Circle({center, rad, color, thick, lt, shift}));
+
+    // Line
+    cv::Point point_next(300, 425);
+    prims.emplace_back(cv::gapi::wip::draw::Line({center, point_next, color, thick, lt, shift}));
+
+    // Poly
+    std::vector<cv::Point> points = {{300, 400}, {290, 450}, {348, 410}, {300, 400}};
+    prims.emplace_back(cv::gapi::wip::draw::Poly({points, color, thick, lt, shift}));
+
+    cv::GMat in, out;
+    cv::GArray<cv::gapi::wip::draw::Prim> arr;
+    out = cv::gapi::wip::draw::render3ch(in, arr);
+    cv::GComputation comp(cv::GIn(in, arr), cv::GOut(out));
+
+    auto serialized = cv::gapi::serialize(comp);
+    auto dc = cv::gapi::deserialize<cv::GComputation>(serialized);
+
+    cv::Mat input(1920, 1080, CV_8UC3);
+    cv::randu(input, cv::Scalar::all(0), cv::Scalar::all(255));
+    cv::Mat ref_mat = input.clone();
+    dc.apply(cv::gin(input, prims), cv::gout(input));
+
+    // OpenCV code //////////////////////////////////////////////////////////////
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect rect(200 + i, 200 + i, 200, 200);
+        cv::rectangle(ref_mat, rect, color, thick, lt, shift);
+    }
+
+    for (int i = 0; i < rects_num; ++i) {
+        cv::Rect mos(200 + i, 200 + i, 200, 200);
+         drawMosaicRef(ref_mat, mos, cellsz);
+    }
+
+    for (int i = 0; i < text_num; ++i) {
+        cv::Point org(200 + i, 200 + i);
+        cv::putText(ref_mat, text, org, ff, fs, color, thick, lt, blo);
+    }
+
+    for (int i = 0; i < image_num; ++i) {
+        cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
+        blendImageRef(ref_mat, org_img, img, alpha);
+    }
+
+    cv::circle(ref_mat, center, rad, color, thick, lt, shift);
+    cv::line(ref_mat, center, point_next, color, thick, lt, shift);
+    std::vector<std::vector<cv::Point>> pp{points};
+    cv::fillPoly(ref_mat, pp, color, lt, shift);
+
+    EXPECT_EQ(cv::norm(input,  ref_mat), 0);
+}
+} // namespace opencv_test
index 32cffa1..1150e6a 100644 (file)
@@ -730,6 +730,8 @@ TEST(GAPI_Streaming_Types, OutputScalar)
 
     cv::VideoCapture cap;
     cap.open(video_path);
+    if (!cap.isOpened())
+        throw SkipTestException("Video file can not be opened");
 
     cv::Mat tmp;
     cv::Scalar out_scl;
@@ -774,6 +776,8 @@ TEST(GAPI_Streaming_Types, OutputVector)
 
     cv::VideoCapture cap;
     cap.open(video_path);
+    if (!cap.isOpened())
+        throw SkipTestException("Video file can not be opened");
 
     cv::Mat tmp;
     std::vector<int> ref_vec;
@@ -815,6 +819,10 @@ struct GAPI_Streaming_Unit: public ::testing::Test {
     }
 };
 
+// FIXME: (GAPI_Streaming_Types,   InputOpaque) test is missing here!
+// FIXME: (GAPI_Streaming_Types, XChangeOpaque) test is missing here!
+// FIXME: (GAPI_Streaming_Types,  OutputOpaque) test is missing here!
+
 TEST_F(GAPI_Streaming_Unit, TestTwoVideoSourcesFail)
 {
     const auto c_ptr = gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(findDataFile("cv/video/768x576.avi"));
index 03f0be2..6253acf 100644 (file)
@@ -2,7 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 //
-// Copyright (C) 2018 Intel Corporation
+// Copyright (C) 2018-2020 Intel Corporation
 
 
 // FIXME: OpenCV header
@@ -16,8 +16,9 @@
 #include <opencv2/ts.hpp>
 
 #include <opencv2/gapi.hpp>
-#include <opencv2/gapi/imgproc.hpp>
 #include <opencv2/gapi/core.hpp>
+#include <opencv2/gapi/imgproc.hpp>
+#include <opencv2/gapi/video.hpp>
 #include <opencv2/gapi/cpu/gcpukernel.hpp>
 #include <opencv2/gapi/gpu/ggpukernel.hpp>
 #include <opencv2/gapi/gpu/imgproc.hpp>
index f85b1fb..65d5e57 100644 (file)
@@ -33,7 +33,7 @@ TEST(Variant, EmptyCTor)
     EXPECT_EQ("", util::get<std::string>(vsi));
 }
 
-TEST(Variant, ValueMoveCTor)
+TEST(Variant, ConvertingCTorMove)
 {
     util::variant<int> vi(42);
     EXPECT_EQ(0u,     vi.index());
@@ -55,16 +55,25 @@ TEST(Variant, ValueMoveCTor)
     EXPECT_EQ(0u,     vsi.index());
     EXPECT_EQ("2017", util::get<std::string>(vsi));
 
+    std::string rvs("2017");
+    util::variant<std::string, int> vsi3(std::move(rvs));
+    EXPECT_EQ(0u,     vsi3.index());
+    EXPECT_EQ("2017", util::get<std::string>(vsi3));
+    //C++ standard state that std::string instance that was moved from stays in valid, but unspecified state.
+    //So the best assumption we can made here is that s is not the same as it was before move.
+    EXPECT_NE("2017", rvs) <<"Rvalue source argument was not moved from while should?";
+
     util::variant<std::string, int> vsi2(42);
     EXPECT_EQ(1u,     vsi2.index());
     EXPECT_EQ(42,     util::get<int>(vsi2));
 }
 
-TEST(Variant, ValueCopyCTor)
+TEST(Variant, ConvertingCTorCopy)
 {
     const int i42         = 42;
     const int i17         = 2017;
     const std::string s17 = "2017";
+    std::string s17_lvref = s17;
 
     util::variant<int> vi(i42);
     EXPECT_EQ(0u,     vi.index());
@@ -82,6 +91,11 @@ TEST(Variant, ValueCopyCTor)
     EXPECT_EQ(0u,     vs.index());
     EXPECT_EQ(s17,    util::get<std::string>(vs));
 
+    util::variant<std::string> vs_lv(s17_lvref);
+    EXPECT_EQ(0u,           vs_lv.index());
+    EXPECT_EQ(s17, s17_lvref);
+    EXPECT_EQ(s17_lvref,    util::get<std::string>(vs_lv));
+
     util::variant<std::string, int> vsi(s17);
     EXPECT_EQ(0u,     vsi.index());
     EXPECT_EQ(s17, util::get<std::string>(vsi));
@@ -151,6 +165,38 @@ TEST(Variant, Assign_ValueUpdate_DiffType)
     EXPECT_EQ("42", util::get<std::string>(vis));
 }
 
+TEST(Variant, Assign_RValueRef_DiffType)
+{
+    TestVar vis(42);
+
+    EXPECT_EQ(0u, vis.index());
+    EXPECT_EQ(42, util::get<int>(vis));
+
+    std::string s("42");
+    vis = std::move(s);
+    EXPECT_EQ(1u, vis.index());
+    EXPECT_EQ("42", util::get<std::string>(vis));
+    //C++ standard state that std::string instance that was moved from stays in valid, but unspecified state.
+    //So the best assumption we can made here is that s is not the same as it was before move.
+    EXPECT_NE("42", s) << "right hand side argument of assignment operation was not moved from while should?";
+}
+
+TEST(Variant, Assign_RValueRef_SameType)
+{
+    TestVar vis(std::string("43"));
+
+    EXPECT_EQ(1u, vis.index());
+    EXPECT_EQ("43", util::get<std::string>(vis));
+
+    std::string s("42");
+    vis = std::move(s);
+    EXPECT_EQ(1u, vis.index());
+    EXPECT_EQ("42", util::get<std::string>(vis));
+    //C++ standard state that std::string instance that was moved from stays in valid, but unspecified state.
+    //So the best assumption we can made here is that s is not the same as it was before move.
+    EXPECT_NE("42", s) << "right hand side argument of assignment operation was not moved from while should?";
+}
+
 TEST(Variant, Assign_LValueRef_DiffType)
 {
     TestVar vis(42);
@@ -162,9 +208,10 @@ TEST(Variant, Assign_LValueRef_DiffType)
     vis = s;
     EXPECT_EQ(1u, vis.index());
     EXPECT_EQ("42", util::get<std::string>(vis));
+    EXPECT_EQ("42", s) << "right hand side argument of assignment operation was moved from while should not ?";
 }
 
-TEST(Variant, Assign_ValueUpdate_Const)
+TEST(Variant, Assign_ValueUpdate_Const_Variant)
 {
     TestVar va(42);
     const TestVar vb(43);
@@ -181,7 +228,7 @@ TEST(Variant, Assign_ValueUpdate_Const)
     EXPECT_EQ(43, util::get<int>(va));
 }
 
-TEST(Variant, Assign_ValueUpdate_Const_DiffType)
+TEST(Variant, Assign_ValueUpdate_Const_DiffType_Variant)
 {
     TestVar va(42);
     const TestVar vb(std::string("42"));
@@ -198,10 +245,11 @@ TEST(Variant, Assign_ValueUpdate_Const_DiffType)
     EXPECT_EQ("42", util::get<std::string>(va));
 }
 
-TEST(Variant, Assign_Move)
+TEST(Variant, Assign_Move_Variant)
 {
     TestVar va(42);
     TestVar vb(std::string("42"));
+    TestVar vd(std::string("43"));
     TestVar vc(43);
 
     EXPECT_EQ(0u, va.index());
@@ -213,10 +261,24 @@ TEST(Variant, Assign_Move)
     EXPECT_EQ(0u, vc.index());
     EXPECT_EQ(43, util::get<int>(vc));
 
+    EXPECT_EQ(1u, vd.index());
+    EXPECT_EQ("43", util::get<std::string>(vd));
+
     va = std::move(vb);
     EXPECT_EQ(1u, va.index());
     EXPECT_EQ("42", util::get<std::string>(va));
 
+    EXPECT_EQ(1u, vb.index());
+    EXPECT_EQ("", util::get<std::string>(vb));
+
+
+    vb = std::move(vd);
+    EXPECT_EQ(1u, vb.index());
+    EXPECT_EQ("43", util::get<std::string>(vb));
+
+    EXPECT_EQ(1u, vd.index());
+    EXPECT_EQ("", util::get<std::string>(vd));
+
     va = std::move(vc);
     EXPECT_EQ(0u, va.index());
     EXPECT_EQ(43, util::get<int>(va));
@@ -262,6 +324,22 @@ TEST(Variant, Swap_DiffIndex)
     EXPECT_EQ(3.14f, util::get<float>(tv1));
 }
 
+TEST(Variant, GetIf)
+{
+    const TestVar cv(42);
+
+    // Test const& get_if()
+    EXPECT_EQ(nullptr, util::get_if<std::string>(&cv));
+    ASSERT_NE(nullptr, util::get_if<int>(&cv));
+    EXPECT_EQ(42, *util::get_if<int>(&cv));
+
+    // Test &get_if
+    TestVar cv2(std::string("42"));
+    EXPECT_EQ(nullptr, util::get_if<int>(&cv2));
+    ASSERT_NE(nullptr, util::get_if<std::string>(&cv2));
+    EXPECT_EQ("42", *util::get_if<std::string>(&cv2));
+}
+
 TEST(Variant, Get)
 {
     const TestVar cv(42);