From f734e7679b2a168fa8f96ae26578ac2c7a8a771e Mon Sep 17 00:00:00 2001 From: Orest Chura Date: Wed, 8 Dec 2021 14:43:31 +0300 Subject: [PATCH] Update fluid (#9007) --- thirdparty/fluid/checksum.txt | 2 +- thirdparty/fluid/modules/gapi/CMakeLists.txt | 127 +- .../modules/gapi/cmake/DownloadADE.cmake | 20 +- .../fluid/modules/gapi/cmake/init.cmake | 7 + .../fluid/modules/gapi/cmake/standalone.cmake | 7 + .../modules/gapi/doc/20-kernel-api.markdown | 12 +- .../modules/gapi/include/opencv2/gapi.hpp | 3 +- .../gapi/include/opencv2/gapi/core.hpp | 64 +- .../include/opencv2/gapi/cpu/gcpukernel.hpp | 20 +- .../gapi/include/opencv2/gapi/cpu/stereo.hpp | 48 + .../opencv2/gapi/fluid/gfluidbuffer.hpp | 2 +- .../opencv2/gapi/fluid/gfluidkernel.hpp | 3 + .../gapi/include/opencv2/gapi/garg.hpp | 65 +- .../gapi/include/opencv2/gapi/garray.hpp | 99 +- .../include/opencv2/gapi/gasync_context.hpp | 7 + .../gapi/include/opencv2/gapi/gcommon.hpp | 14 +- .../include/opencv2/gapi/gcomputation.hpp | 15 +- .../gapi/include/opencv2/gapi/gframe.hpp | 48 +- .../gapi/include/opencv2/gapi/gkernel.hpp | 28 +- .../gapi/include/opencv2/gapi/gmat.hpp | 74 +- .../gapi/include/opencv2/gapi/gopaque.hpp | 36 +- .../gapi/include/opencv2/gapi/gproto.hpp | 4 +- .../gapi/include/opencv2/gapi/gscalar.hpp | 79 +- .../gapi/include/opencv2/gapi/gstreaming.hpp | 66 +- .../gapi/include/opencv2/gapi/gtransform.hpp | 2 +- .../include/opencv2/gapi/gtype_traits.hpp | 20 + .../gapi/include/opencv2/gapi/gtyped.hpp | 4 +- .../gapi/include/opencv2/gapi/imgproc.hpp | 10 +- .../gapi/include/opencv2/gapi/infer.hpp | 366 ++- .../opencv2/gapi/infer/bindings_ie.hpp | 14 + .../gapi/include/opencv2/gapi/infer/ie.hpp | 352 ++- .../gapi/include/opencv2/gapi/infer/onnx.hpp | 202 +- .../include/opencv2/gapi/infer/parsers.hpp | 33 +- .../gapi/include/opencv2/gapi/media.hpp | 196 +- .../include/opencv2/gapi/ocl/goclkernel.hpp | 3 + .../include/opencv2/gapi/opencv_includes.hpp | 8 + .../gapi/include/opencv2/gapi/own/cvdefs.hpp | 15 +- .../gapi/include/opencv2/gapi/own/exports.hpp | 4 + .../include/opencv2/gapi/own/saturate.hpp | 67 +- .../gapi/include/opencv2/gapi/own/types.hpp | 18 +- .../opencv2/gapi/plaidml/gplaidmlkernel.hpp | 2 +- .../include/opencv2/gapi/plaidml/plaidml.hpp | 5 + .../include/opencv2/gapi/python/python.hpp | 67 + .../include/opencv2/gapi/render/render.hpp | 54 +- .../opencv2/gapi/render/render_types.hpp | 100 +- .../gapi/include/opencv2/gapi/rmat.hpp | 28 +- .../gapi/include/opencv2/gapi/s11n.hpp | 234 +- .../gapi/include/opencv2/gapi/s11n/base.hpp | 40 +- .../gapi/include/opencv2/gapi/stereo.hpp | 85 + .../include/opencv2/gapi/streaming/desync.hpp | 5 +- .../include/opencv2/gapi/streaming/format.hpp | 34 +- .../streaming/gstreamer/gstreamerpipeline.hpp | 47 + .../streaming/gstreamer/gstreamersource.hpp | 89 + .../gapi/streaming/onevpl/cfg_params.hpp | 88 + .../onevpl/data_provider_interface.hpp | 105 + .../onevpl/device_selector_interface.hpp | 102 + .../opencv2/gapi/streaming/onevpl/source.hpp | 90 + .../include/opencv2/gapi/streaming/sync.hpp | 30 + .../gapi/include/opencv2/gapi/util/any.hpp | 6 +- .../include/opencv2/gapi/util/optional.hpp | 4 +- .../gapi/include/opencv2/gapi/util/util.hpp | 66 + .../include/opencv2/gapi/util/variant.hpp | 226 +- .../gapi/include/opencv2/gapi/video.hpp | 4 + .../gapi/misc/python/package/gapi/__init__.py | 299 +++ .../gapi/misc/python/pyopencv_gapi.hpp | 1087 ++++++++- .../gapi/misc/python/python_bridge.hpp | 338 +++ .../misc/python/samples/gaze_estimation.py | 458 ++++ .../modules/gapi/misc/python/shadow_gapi.hpp | 93 +- .../gapi/misc/python/test/test_gapi_core.py | 294 ++- .../misc/python/test/test_gapi_imgproc.py | 152 +- .../gapi/misc/python/test/test_gapi_infer.py | 351 ++- .../gapi/misc/python/test/test_gapi_render.py | 227 ++ .../python/test/test_gapi_sample_pipelines.py | 685 +++++- .../misc/python/test/test_gapi_streaming.py | 521 +++-- .../gapi/misc/python/test/test_gapi_types.py | 54 + .../gapi/perf/common/gapi_core_perf_tests.hpp | 23 +- .../perf/common/gapi_core_perf_tests_inl.hpp | 360 ++- .../perf/common/gapi_imgproc_perf_tests.hpp | 40 + .../common/gapi_imgproc_perf_tests_inl.hpp | 371 +++ .../perf/common/gapi_video_perf_tests.hpp | 9 + .../perf/common/gapi_video_perf_tests_inl.hpp | 238 ++ .../perf/cpu/gapi_core_perf_tests_cpu.cpp | 82 +- .../perf/cpu/gapi_core_perf_tests_fluid.cpp | 98 +- .../perf/cpu/gapi_imgproc_perf_tests_cpu.cpp | 140 ++ .../perf/cpu/gapi_video_perf_tests_cpu.cpp | 33 +- .../perf/gpu/gapi_core_perf_tests_gpu.cpp | 27 +- .../gapi_streaming_source_perf_tests.cpp | 83 + .../gapi/samples/face_detection_mtcnn.cpp | 733 ++++++ .../modules/gapi/samples/gaze_estimation.cpp | 95 +- .../gapi/samples/infer_ie_onnx_hybrid.cpp | 8 +- .../modules/gapi/samples/infer_single_roi.cpp | 86 +- .../modules/gapi/samples/infer_ssd_onnx.cpp | 78 +- .../gapi/samples/onevpl_infer_single_roi.cpp | 390 ++++ .../gapi/samples/privacy_masking_camera.cpp | 63 +- .../gapi/samples/semantic_segmentation.cpp | 184 ++ .../modules/gapi/src/api/gcomputation.cpp | 107 +- .../gapi/src/api/gcomputation_priv.hpp | 14 +- .../fluid/modules/gapi/src/api/ginfer.cpp | 69 +- .../fluid/modules/gapi/src/api/gkernel.cpp | 12 +- .../fluid/modules/gapi/src/api/gproto.cpp | 52 +- .../modules/gapi/src/api/gproto_priv.hpp | 3 + .../fluid/modules/gapi/src/api/grunarg.cpp | 45 + .../modules/gapi/src/api/kernels_core.cpp | 11 + .../modules/gapi/src/api/kernels_stereo.cpp | 18 + .../gapi/src/api/kernels_streaming.cpp | 15 +- .../fluid/modules/gapi/src/api/media.cpp | 19 + .../fluid/modules/gapi/src/api/render.cpp | 20 + .../fluid/modules/gapi/src/api/render_ocv.cpp | 6 +- .../fluid/modules/gapi/src/api/s11n.cpp | 34 +- .../gapi/src/backends/common/gbackend.hpp | 73 +- .../src/backends/common/gcompoundkernel.cpp | 2 +- .../gapi/src/backends/common/gmetabackend.cpp | 17 +- .../src/backends/common/serialization.cpp | 82 +- .../src/backends/common/serialization.hpp | 10 +- .../gapi/src/backends/cpu/gcpubackend.cpp | 25 +- .../gapi/src/backends/cpu/gcpucore.cpp | 36 +- .../gapi/src/backends/cpu/gcpustereo.cpp | 85 + .../gapi/src/backends/cpu/gcpuvideo.cpp | 26 +- .../gapi/src/backends/cpu/gnnparsers.cpp | 53 +- .../gapi/src/backends/cpu/gnnparsers.hpp | 13 +- .../gapi/src/backends/fluid/gfluidbackend.cpp | 14 +- .../gapi/src/backends/fluid/gfluidcore.cpp | 1388 +++++++++--- .../fluid/gfluidcore_func.dispatch.cpp | 172 ++ .../src/backends/fluid/gfluidcore_func.hpp | 136 ++ .../backends/fluid/gfluidcore_func.simd.hpp | 1461 ++++++++++++ .../backends/fluid/gfluidcore_simd_sse41.hpp | 733 ++++++ .../gapi/src/backends/ie/bindings_ie.cpp | 18 + .../gapi/src/backends/ie/giebackend.cpp | 1203 +++++++--- .../gapi/src/backends/ie/giebackend.hpp | 34 +- .../src/backends/ie/giebackend/giewrapper.cpp | 53 +- .../src/backends/ie/giebackend/giewrapper.hpp | 38 +- .../modules/gapi/src/backends/ie/util.hpp | 4 +- .../gapi/src/backends/ocl/goclbackend.cpp | 16 +- .../gapi/src/backends/ocl/goclcore.cpp | 10 + .../gapi/src/backends/onnx/gonnxbackend.cpp | 351 ++- .../src/backends/plaidml/gplaidmlbackend.cpp | 19 +- .../src/backends/python/gpythonbackend.cpp | 261 +++ .../gapi/src/backends/render/grenderocv.cpp | 77 +- .../backends/streaming/gstreamingbackend.cpp | 224 +- .../gapi/src/compiler/gcompiled_priv.hpp | 10 - .../modules/gapi/src/compiler/gcompiler.cpp | 44 +- .../modules/gapi/src/compiler/gcompiler.hpp | 2 +- .../gapi/src/compiler/gislandmodel.cpp | 51 +- .../gapi/src/compiler/gislandmodel.hpp | 10 +- .../gapi/src/compiler/gmodelbuilder.cpp | 4 +- .../modules/gapi/src/compiler/gstreaming.cpp | 57 +- .../gapi/src/compiler/gstreaming_priv.hpp | 1 + .../gapi/src/compiler/passes/kernels.cpp | 11 +- .../modules/gapi/src/compiler/passes/meta.cpp | 4 +- .../gapi/src/compiler/transactions.hpp | 4 +- .../modules/gapi/src/executor/gasync.cpp | 28 +- .../modules/gapi/src/executor/gexecutor.cpp | 30 +- .../gapi/src/executor/gstreamingexecutor.cpp | 450 +++- .../gapi/src/executor/gstreamingexecutor.hpp | 6 + .../gapi/src/executor/gtbbexecutor.cpp | 28 +- .../gapi/src/executor/gtbbexecutor.hpp | 11 +- .../gstreamer/gstreamer_buffer_utils.cpp | 27 + .../gstreamer/gstreamer_buffer_utils.hpp | 27 + .../gstreamer/gstreamer_media_adapter.cpp | 122 + .../gstreamer/gstreamer_media_adapter.hpp | 63 + .../gstreamer/gstreamer_pipeline_facade.cpp | 314 +++ .../gstreamer/gstreamer_pipeline_facade.hpp | 89 + .../src/streaming/gstreamer/gstreamerenv.cpp | 90 + .../src/streaming/gstreamer/gstreamerenv.hpp | 37 + .../streaming/gstreamer/gstreamerpipeline.cpp | 112 + .../gstreamer/gstreamerpipeline_priv.hpp | 58 + .../src/streaming/gstreamer/gstreamerptr.hpp | 177 ++ .../streaming/gstreamer/gstreamersource.cpp | 383 ++++ .../gstreamer/gstreamersource_priv.hpp | 94 + .../onevpl/accelerators/accel_policy_cpu.cpp | 171 ++ .../onevpl/accelerators/accel_policy_cpu.hpp | 52 + .../onevpl/accelerators/accel_policy_dx11.cpp | 120 + .../onevpl/accelerators/accel_policy_dx11.hpp | 70 + .../accelerators/accel_policy_interface.hpp | 61 + .../surface/cpu_frame_adapter.cpp | 119 + .../surface/cpu_frame_adapter.hpp | 43 + .../onevpl/accelerators/surface/surface.cpp | 78 + .../onevpl/accelerators/surface/surface.hpp | 104 + .../accelerators/surface/surface_pool.cpp | 85 + .../accelerators/surface/surface_pool.hpp | 52 + .../onevpl/cfg_param_device_selector.cpp | 275 +++ .../onevpl/cfg_param_device_selector.hpp | 44 + .../gapi/src/streaming/onevpl/cfg_params.cpp | 137 ++ .../streaming/onevpl/cfg_params_parser.cpp | 123 + .../streaming/onevpl/cfg_params_parser.hpp | 43 + .../onevpl/data_provider_defines.hpp | 32 + .../onevpl/data_provider_dispatcher.cpp | 68 + .../onevpl/data_provider_dispatcher.hpp | 29 + .../data_provider_interface_exception.cpp | 49 + .../demux/async_mfp_demux_data_provider.cpp | 820 +++++++ .../demux/async_mfp_demux_data_provider.hpp | 126 ++ .../onevpl/device_selector_interface.cpp | 87 + .../engine/decode/decode_engine_legacy.cpp | 391 ++++ .../engine/decode/decode_engine_legacy.hpp | 49 + .../onevpl/engine/decode/decode_session.cpp | 79 + .../onevpl/engine/decode/decode_session.hpp | 63 + .../onevpl/engine/engine_session.cpp | 33 + .../onevpl/engine/engine_session.hpp | 50 + .../onevpl/engine/processing_engine_base.cpp | 106 + .../onevpl/engine/processing_engine_base.hpp | 96 + .../streaming/onevpl/file_data_provider.cpp | 155 ++ .../streaming/onevpl/file_data_provider.hpp | 42 + .../gapi/src/streaming/onevpl/source.cpp | 115 + .../gapi/src/streaming/onevpl/source_priv.cpp | 387 ++++ .../gapi/src/streaming/onevpl/source_priv.hpp | 89 + .../gapi/src/streaming/onevpl/utils.cpp | 492 ++++ .../gapi/src/streaming/onevpl/utils.hpp | 83 + .../fluid/modules/gapi/src/utils/itt.cpp | 17 + .../fluid/modules/gapi/src/utils/itt.hpp | 78 + .../gapi/test/common/gapi_core_tests.hpp | 18 +- .../test/common/gapi_core_tests_common.hpp | 180 ++ .../gapi/test/common/gapi_core_tests_inl.hpp | 303 +-- .../gapi/test/common/gapi_imgproc_tests.hpp | 15 +- .../test/common/gapi_imgproc_tests_common.hpp | 197 ++ .../test/common/gapi_imgproc_tests_inl.hpp | 480 +--- .../test/common/gapi_operators_tests_inl.hpp | 6 +- .../gapi/test/common/gapi_render_tests.hpp | 2 + .../gapi/test/common/gapi_stereo_tests.cpp | 8 + .../gapi/test/common/gapi_stereo_tests.hpp | 26 + .../test/common/gapi_stereo_tests_inl.hpp | 74 + .../gapi/test/common/gapi_tests_common.hpp | 26 +- .../gapi/test/common/gapi_tests_helpers.hpp | 21 + .../test/common/gapi_video_tests_common.hpp | 142 +- .../gapi/test/common/gapi_video_tests_inl.hpp | 71 +- .../gapi/test/cpu/gapi_core_tests_cpu.cpp | 34 +- .../gapi/test/cpu/gapi_core_tests_fluid.cpp | 8 +- .../gapi/test/cpu/gapi_imgproc_tests_cpu.cpp | 27 +- .../cpu/gapi_ocv_stateful_kernel_tests.cpp | 20 - .../gapi/test/cpu/gapi_stereo_tests_cpu.cpp | 39 + .../gapi/test/cpu/gapi_video_tests_cpu.cpp | 2 +- .../executor/gtbbexecutor_internal_tests.cpp | 10 +- .../modules/gapi/test/gapi_array_tests.cpp | 30 + .../modules/gapi/test/gapi_async_test.cpp | 8 +- .../gapi/test/gapi_fluid_resize_test.cpp | 4 +- .../modules/gapi/test/gapi_fluid_test.cpp | 10 +- .../modules/gapi/test/gapi_frame_tests.cpp | 7 + .../gapi/test/gapi_gcompiled_tests.cpp | 59 + .../gapi/test/gapi_gcomputation_tests.cpp | 31 +- .../gapi/test/gapi_graph_meta_tests.cpp | 23 - .../modules/gapi/test/gapi_kernel_tests.cpp | 26 +- .../modules/gapi/test/gapi_opaque_tests.cpp | 16 +- .../modules/gapi/test/gapi_util_tests.cpp | 40 +- .../gapi/test/gpu/gapi_core_tests_gpu.cpp | 10 + .../gapi/test/infer/gapi_infer_ie_test.cpp | 2016 ++++++++++++++++- .../gapi/test/infer/gapi_infer_onnx_test.cpp | 884 +++++++- .../test/internal/gapi_int_executor_tests.cpp | 217 ++ .../test/internal/gapi_int_gmetaarg_test.cpp | 18 +- .../internal/gapi_int_gmodel_builder_test.cpp | 2 +- .../test/internal/gapi_int_proto_tests.cpp | 1 - .../internal/gapi_int_recompilation_test.cpp | 22 +- .../gapi/test/own/conc_queue_tests.cpp | 2 +- .../test/own/last_written_value_tests.cpp | 2 +- .../fluid/modules/gapi/test/own/mat_tests.cpp | 78 +- .../modules/gapi/test/own/scalar_tests.cpp | 18 +- .../test/render/gapi_render_tests_ocv.cpp | 318 ++- .../gapi/test/rmat/rmat_test_common.hpp | 4 +- .../modules/gapi/test/rmat/rmat_tests.cpp | 4 +- .../gapi/test/rmat/rmat_view_tests.cpp | 9 + .../gapi/test/s11n/gapi_s11n_tests.cpp | 130 +- .../test/s11n/gapi_sample_pipelines_s11n.cpp | 29 + ...pi_gstreamer_pipeline_facade_int_tests.cpp | 188 ++ .../streaming/gapi_gstreamersource_tests.cpp | 401 ++++ .../streaming/gapi_streaming_sync_tests.cpp | 220 ++ .../test/streaming/gapi_streaming_tests.cpp | 736 ++++-- .../gapi_streaming_vpl_core_test.cpp | 449 ++++ .../gapi_streaming_vpl_data_provider.cpp | 304 +++ .../gapi_streaming_vpl_device_selector.cpp | 229 ++ .../fluid/modules/gapi/test/test_main.cpp | 2 +- .../fluid/modules/gapi/test/test_precomp.hpp | 1 + .../modules/gapi/test/util/any_tests.cpp | 30 +- .../modules/gapi/test/util/variant_tests.cpp | 250 ++ thirdparty/fluid/revision.txt | 2 +- 272 files changed, 30542 insertions(+), 3888 deletions(-) create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/stereo.hpp create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/python/python.hpp create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/stereo.hpp create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamerpipeline.hpp create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/cfg_params.hpp create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/data_provider_interface.hpp create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/device_selector_interface.hpp create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/source.hpp create mode 100644 thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/sync.hpp create mode 100644 thirdparty/fluid/modules/gapi/misc/python/package/gapi/__init__.py create mode 100644 thirdparty/fluid/modules/gapi/misc/python/python_bridge.hpp create mode 100644 thirdparty/fluid/modules/gapi/misc/python/samples/gaze_estimation.py create mode 100644 thirdparty/fluid/modules/gapi/misc/python/test/test_gapi_render.py create mode 100644 thirdparty/fluid/modules/gapi/misc/python/test/test_gapi_types.py create mode 100644 thirdparty/fluid/modules/gapi/perf/streaming/gapi_streaming_source_perf_tests.cpp create mode 100644 thirdparty/fluid/modules/gapi/samples/face_detection_mtcnn.cpp create mode 100644 thirdparty/fluid/modules/gapi/samples/onevpl_infer_single_roi.cpp create mode 100644 thirdparty/fluid/modules/gapi/samples/semantic_segmentation.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/api/kernels_stereo.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/backends/cpu/gcpustereo.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidcore_func.dispatch.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidcore_func.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidcore_func.simd.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidcore_simd_sse41.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/backends/python/gpythonbackend.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamer_buffer_utils.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamer_buffer_utils.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamer_media_adapter.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamer_media_adapter.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamer_pipeline_facade.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamer_pipeline_facade.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamerenv.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamerenv.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamerpipeline.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamerpipeline_priv.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamerptr.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamersource.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/gstreamer/gstreamersource_priv.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_cpu.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_dx11.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_dx11.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/accel_policy_interface.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/surface/surface.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/surface/surface.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/accelerators/surface/surface_pool.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/cfg_param_device_selector.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/cfg_param_device_selector.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/cfg_params.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/cfg_params_parser.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/cfg_params_parser.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/data_provider_defines.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/data_provider_dispatcher.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/data_provider_dispatcher.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/data_provider_interface_exception.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/demux/async_mfp_demux_data_provider.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/demux/async_mfp_demux_data_provider.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/device_selector_interface.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/engine/decode/decode_engine_legacy.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/engine/decode/decode_session.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/engine/engine_session.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/engine/engine_session.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/engine/processing_engine_base.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/engine/processing_engine_base.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/file_data_provider.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/file_data_provider.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/source.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/source_priv.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/source_priv.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/utils.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/streaming/onevpl/utils.hpp create mode 100644 thirdparty/fluid/modules/gapi/src/utils/itt.cpp create mode 100644 thirdparty/fluid/modules/gapi/src/utils/itt.hpp create mode 100644 thirdparty/fluid/modules/gapi/test/common/gapi_core_tests_common.hpp create mode 100644 thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests_common.hpp create mode 100644 thirdparty/fluid/modules/gapi/test/common/gapi_stereo_tests.cpp create mode 100644 thirdparty/fluid/modules/gapi/test/common/gapi_stereo_tests.hpp create mode 100644 thirdparty/fluid/modules/gapi/test/common/gapi_stereo_tests_inl.hpp create mode 100644 thirdparty/fluid/modules/gapi/test/cpu/gapi_stereo_tests_cpu.cpp create mode 100644 thirdparty/fluid/modules/gapi/test/streaming/gapi_gstreamer_pipeline_facade_int_tests.cpp create mode 100644 thirdparty/fluid/modules/gapi/test/streaming/gapi_gstreamersource_tests.cpp create mode 100644 thirdparty/fluid/modules/gapi/test/streaming/gapi_streaming_sync_tests.cpp create mode 100644 thirdparty/fluid/modules/gapi/test/streaming/gapi_streaming_vpl_core_test.cpp create mode 100644 thirdparty/fluid/modules/gapi/test/streaming/gapi_streaming_vpl_data_provider.cpp create mode 100644 thirdparty/fluid/modules/gapi/test/streaming/gapi_streaming_vpl_device_selector.cpp diff --git a/thirdparty/fluid/checksum.txt b/thirdparty/fluid/checksum.txt index f517be3cf0d..d4ac1a3744b 100644 --- a/thirdparty/fluid/checksum.txt +++ b/thirdparty/fluid/checksum.txt @@ -1 +1 @@ -91e7c0aaa00be504e8e6692d0b3b86c1 +52e7351a888ee42076be4db81d9ac992 diff --git a/thirdparty/fluid/modules/gapi/CMakeLists.txt b/thirdparty/fluid/modules/gapi/CMakeLists.txt index 2ad7be9ad2f..855ce27088a 100644 --- a/thirdparty/fluid/modules/gapi/CMakeLists.txt +++ b/thirdparty/fluid/modules/gapi/CMakeLists.txt @@ -23,25 +23,20 @@ ocv_add_module(gapi REQUIRED opencv_imgproc OPTIONAL - opencv_video + opencv_video opencv_calib3d 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) + if(MSVC_VERSION LESS 1910) + # Disable obsolete warning C4503 popping up on MSVC << 15 2017 + # https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4503?view=vs-2019 + # and IE deprecated code warning C4996 + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4503 /wd4996) endif() endif() -if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") # don't add Clang here: issue should be investigated and fixed (workaround for Apple only) - ocv_warnings_disable(CMAKE_CXX_FLAGS -Wrange-loop-analysis) # https://github.com/opencv/opencv/issues/18928 -endif() - file(GLOB gapi_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/*.hpp" @@ -52,10 +47,13 @@ file(GLOB gapi_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/infer/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/ocl/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/own/*.hpp" + "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/plaidml/*.hpp" + "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/python/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/render/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/s11n/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/streaming/*.hpp" - "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/plaidml/*.hpp" + "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/streaming/gstreamer/*.hpp" + "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/streaming/onevpl/*.hpp" "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/util/*.hpp" ) @@ -80,6 +78,7 @@ set(gapi_srcs src/api/kernels_video.cpp src/api/kernels_nnparsers.cpp src/api/kernels_streaming.cpp + src/api/kernels_stereo.cpp src/api/render.cpp src/api/render_ocv.cpp src/api/ginfer.cpp @@ -115,6 +114,7 @@ set(gapi_srcs src/backends/cpu/gcpubackend.cpp src/backends/cpu/gcpukernel.cpp src/backends/cpu/gcpuimgproc.cpp + src/backends/cpu/gcpustereo.cpp src/backends/cpu/gcpuvideo.cpp src/backends/cpu/gcpucore.cpp src/backends/cpu/gnnparsers.cpp @@ -125,6 +125,7 @@ set(gapi_srcs src/backends/fluid/gfluidimgproc.cpp src/backends/fluid/gfluidimgproc_func.dispatch.cpp src/backends/fluid/gfluidcore.cpp + src/backends/fluid/gfluidcore_func.dispatch.cpp # OCL Backend (currently built-in) src/backends/ocl/goclbackend.cpp @@ -162,9 +163,45 @@ set(gapi_srcs # Python bridge src/backends/ie/bindings_ie.cpp + src/backends/python/gpythonbackend.cpp + + # OpenVPL Streaming source + src/streaming/onevpl/source.cpp + src/streaming/onevpl/source_priv.cpp + src/streaming/onevpl/file_data_provider.cpp + src/streaming/onevpl/cfg_params.cpp + src/streaming/onevpl/cfg_params_parser.cpp + src/streaming/onevpl/utils.cpp + src/streaming/onevpl/data_provider_interface_exception.cpp + src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.cpp + src/streaming/onevpl/accelerators/surface/surface.cpp + src/streaming/onevpl/accelerators/surface/surface_pool.cpp + src/streaming/onevpl/accelerators/accel_policy_cpu.cpp + src/streaming/onevpl/accelerators/accel_policy_dx11.cpp + src/streaming/onevpl/engine/engine_session.cpp + src/streaming/onevpl/engine/processing_engine_base.cpp + src/streaming/onevpl/engine/decode/decode_engine_legacy.cpp + src/streaming/onevpl/engine/decode/decode_session.cpp + src/streaming/onevpl/demux/async_mfp_demux_data_provider.cpp + src/streaming/onevpl/data_provider_dispatcher.cpp + + src/streaming/onevpl/cfg_param_device_selector.cpp + src/streaming/onevpl/device_selector_interface.cpp + + # GStreamer Streaming source + src/streaming/gstreamer/gstreamer_pipeline_facade.cpp + src/streaming/gstreamer/gstreamerpipeline.cpp + src/streaming/gstreamer/gstreamersource.cpp + src/streaming/gstreamer/gstreamer_buffer_utils.cpp + src/streaming/gstreamer/gstreamer_media_adapter.cpp + src/streaming/gstreamer/gstreamerenv.cpp + + # Utils (ITT tracing) + src/utils/itt.cpp ) ocv_add_dispatched_file(backends/fluid/gfluidimgproc_func SSE4_1 AVX2) +ocv_add_dispatched_file(backends/fluid/gfluidcore_func SSE4_1 AVX2) ocv_list_add_prefix(gapi_srcs "${CMAKE_CURRENT_LIST_DIR}/") @@ -178,17 +215,33 @@ ocv_module_include_directories("${CMAKE_CURRENT_LIST_DIR}/src") ocv_create_module() 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_NGRAPH) + ocv_target_link_libraries(${the_module} PRIVATE ngraph::ngraph) +endif() + if(HAVE_TBB) ocv_target_link_libraries(${the_module} PRIVATE tbb) endif() +# TODO: Consider support of ITT in G-API standalone mode. +if(CV_TRACE AND HAVE_ITT) + ocv_target_compile_definitions(${the_module} PRIVATE -DOPENCV_WITH_ITT=1) + ocv_module_include_directories(${ITT_INCLUDE_DIRS}) + ocv_target_link_libraries(${the_module} PRIVATE ${ITT_LIBRARIES}) +endif() + set(__test_extra_deps "") if(OPENCV_GAPI_INF_ENGINE) list(APPEND __test_extra_deps ${INF_ENGINE_TARGET}) endif() +if(HAVE_NGRAPH) + list(APPEND __test_extra_deps ngraph::ngraph) +endif() ocv_add_accuracy_tests(${__test_extra_deps}) # FIXME: test binary is linked with ADE directly since ADE symbols @@ -198,6 +251,9 @@ ocv_add_accuracy_tests(${__test_extra_deps}) if(TARGET opencv_test_gapi) target_include_directories(opencv_test_gapi PRIVATE "${CMAKE_CURRENT_LIST_DIR}/src") target_link_libraries(opencv_test_gapi PRIVATE ade) + if (HAVE_NGRAPH) + ocv_target_compile_definitions(opencv_test_gapi PRIVATE -DHAVE_NGRAPH) + endif() endif() if(HAVE_TBB AND TARGET opencv_test_gapi) @@ -222,6 +278,29 @@ if(HAVE_PLAIDML) ocv_target_include_directories(${the_module} SYSTEM PRIVATE ${PLAIDML_INCLUDE_DIRS}) endif() +if(HAVE_GAPI_ONEVPL) + if(TARGET opencv_test_gapi) + ocv_target_compile_definitions(opencv_test_gapi PRIVATE -DHAVE_ONEVPL) + ocv_target_link_libraries(opencv_test_gapi PRIVATE ${VPL_IMPORTED_TARGETS}) + if(HAVE_D3D11 AND HAVE_OPENCL) + ocv_target_include_directories(opencv_test_gapi SYSTEM PRIVATE ${OPENCL_INCLUDE_DIRS}) + endif() + endif() + ocv_target_compile_definitions(${the_module} PRIVATE -DHAVE_ONEVPL) + ocv_target_link_libraries(${the_module} PRIVATE ${VPL_IMPORTED_TARGETS}) + if(HAVE_D3D11 AND HAVE_OPENCL) + ocv_target_include_directories(${the_module} SYSTEM PRIVATE ${OPENCL_INCLUDE_DIRS}) + endif() +endif() + +if(HAVE_GSTREAMER) + if(TARGET opencv_test_gapi) + ocv_target_compile_definitions(opencv_test_gapi PRIVATE -DHAVE_GSTREAMER) + ocv_target_link_libraries(opencv_test_gapi PRIVATE ocv.3rdparty.gstreamer) + endif() + ocv_target_compile_definitions(${the_module} PRIVATE -DHAVE_GSTREAMER) + ocv_target_link_libraries(${the_module} PRIVATE ocv.3rdparty.gstreamer) +endif() if(WIN32) # Required for htonl/ntohl on Windows @@ -239,3 +318,27 @@ endif() ocv_add_perf_tests() ocv_add_samples() + + +# Required for sample with inference on host +if (TARGET example_gapi_onevpl_infer_single_roi) + if(OPENCV_GAPI_INF_ENGINE) + ocv_target_link_libraries(example_gapi_onevpl_infer_single_roi PRIVATE ${INF_ENGINE_TARGET}) + ocv_target_compile_definitions(example_gapi_onevpl_infer_single_roi PRIVATE -DHAVE_INF_ENGINE) + endif() + if(HAVE_D3D11 AND HAVE_OPENCL) + ocv_target_include_directories(example_gapi_onevpl_infer_single_roi SYSTEM PRIVATE ${OPENCL_INCLUDE_DIRS}) + endif() +endif() + +# perf test dependencies postprocessing +if(HAVE_GAPI_ONEVPL) + # NB: TARGET opencv_perf_gapi doesn't exist before `ocv_add_perf_tests` + if(TARGET opencv_perf_gapi) + ocv_target_compile_definitions(opencv_perf_gapi PRIVATE -DHAVE_ONEVPL) + ocv_target_link_libraries(opencv_perf_gapi PRIVATE ${VPL_IMPORTED_TARGETS}) + if(HAVE_D3D11 AND HAVE_OPENCL) + ocv_target_include_directories(opencv_perf_gapi SYSTEM PRIVATE ${OPENCL_INCLUDE_DIRS}) + endif() + endif() +endif() diff --git a/thirdparty/fluid/modules/gapi/cmake/DownloadADE.cmake b/thirdparty/fluid/modules/gapi/cmake/DownloadADE.cmake index ee1b6454124..aa24e949eac 100644 --- a/thirdparty/fluid/modules/gapi/cmake/DownloadADE.cmake +++ b/thirdparty/fluid/modules/gapi/cmake/DownloadADE.cmake @@ -20,12 +20,26 @@ endif() set(ADE_root "${ade_src_dir}/${ade_subdir}/sources/ade") file(GLOB_RECURSE ADE_sources "${ADE_root}/source/*.cpp") file(GLOB_RECURSE ADE_include "${ADE_root}/include/ade/*.hpp") -add_library(ade STATIC ${ADE_include} ${ADE_sources}) +add_library(ade STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL} + ${ADE_include} + ${ADE_sources} +) target_include_directories(ade PUBLIC $) -set_target_properties(ade PROPERTIES POSITION_INDEPENDENT_CODE True) +set_target_properties(ade PROPERTIES + POSITION_INDEPENDENT_CODE True + OUTPUT_NAME ade + DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" + COMPILE_PDB_NAME ade + COMPILE_PDB_NAME_DEBUG "ade${OPENCV_DEBUG_POSTFIX}" + ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} +) + +if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(ade PROPERTIES FOLDER "3rdparty") +endif() if(NOT BUILD_SHARED_LIBS) - ocv_install_target(ade EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) + ocv_install_target(ade EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev OPTIONAL) endif() ocv_install_3rdparty_licenses(ade "${ade_src_dir}/${ade_subdir}/LICENSE") diff --git a/thirdparty/fluid/modules/gapi/cmake/init.cmake b/thirdparty/fluid/modules/gapi/cmake/init.cmake index 4c25c75f555..1c464328ca1 100644 --- a/thirdparty/fluid/modules/gapi/cmake/init.cmake +++ b/thirdparty/fluid/modules/gapi/cmake/init.cmake @@ -32,3 +32,10 @@ if(WITH_PLAIDML) set(HAVE_PLAIDML TRUE) endif() endif() + +if(WITH_GAPI_ONEVPL) + find_package(VPL) + if(VPL_FOUND) + set(HAVE_GAPI_ONEVPL TRUE) + endif() +endif() diff --git a/thirdparty/fluid/modules/gapi/cmake/standalone.cmake b/thirdparty/fluid/modules/gapi/cmake/standalone.cmake index d08eda1be5e..f81c1c8a85d 100644 --- a/thirdparty/fluid/modules/gapi/cmake/standalone.cmake +++ b/thirdparty/fluid/modules/gapi/cmake/standalone.cmake @@ -6,6 +6,13 @@ if (NOT TARGET ade ) find_package(ade 0.1.0 REQUIRED) endif() +if (WITH_GAPI_ONEVPL) + find_package(VPL) + if(VPL_FOUND) + set(HAVE_GAPI_ONEVPL TRUE) + endif() +endif() + set(FLUID_TARGET fluid) set(FLUID_ROOT "${CMAKE_CURRENT_LIST_DIR}/../") diff --git a/thirdparty/fluid/modules/gapi/doc/20-kernel-api.markdown b/thirdparty/fluid/modules/gapi/doc/20-kernel-api.markdown index 6ad882eda82..9a7cf39f678 100644 --- a/thirdparty/fluid/modules/gapi/doc/20-kernel-api.markdown +++ b/thirdparty/fluid/modules/gapi/doc/20-kernel-api.markdown @@ -47,7 +47,7 @@ an external parameter. G-API provides a macro to define a new kernel interface -- G_TYPED_KERNEL(): -@snippet modules/gapi/samples/kernel_api_snippets.cpp filter2d_api +@snippet samples/cpp/tutorial_code/gapi/doc_snippets/kernel_api_snippets.cpp filter2d_api This macro is a shortcut to a new type definition. It takes three arguments to register a new type, and requires type body to be present @@ -81,18 +81,18 @@ Once a kernel is defined, it can be used in pipelines with special, G-API-supplied method "::on()". This method has the same signature as defined in kernel, so this code: -@snippet modules/gapi/samples/kernel_api_snippets.cpp filter2d_on +@snippet samples/cpp/tutorial_code/gapi/doc_snippets/kernel_api_snippets.cpp filter2d_on is a perfectly legal construction. This example has some verbosity, though, so usually a kernel declaration comes with a C++ function wrapper ("factory method") which enables optional parameters, more compact syntax, Doxygen comments, etc: -@snippet modules/gapi/samples/kernel_api_snippets.cpp filter2d_wrap +@snippet samples/cpp/tutorial_code/gapi/doc_snippets/kernel_api_snippets.cpp filter2d_wrap so now it can be used like: -@snippet modules/gapi/samples/kernel_api_snippets.cpp filter2d_wrap_call +@snippet samples/cpp/tutorial_code/gapi/doc_snippets/kernel_api_snippets.cpp filter2d_wrap_call # Extra information {#gapi_kernel_supp_info} @@ -143,7 +143,7 @@ For example, the aforementioned `Filter2D` is implemented in "reference" CPU (OpenCV) plugin this way (*NOTE* -- this is a simplified form with improper border handling): -@snippet modules/gapi/samples/kernel_api_snippets.cpp filter2d_ocv +@snippet samples/cpp/tutorial_code/gapi/doc_snippets/kernel_api_snippets.cpp filter2d_ocv Note how CPU (OpenCV) plugin has transformed the original kernel signature: @@ -174,7 +174,7 @@ point extraction to an STL vector: A compound kernel _implementation_ can be defined using a generic macro GAPI_COMPOUND_KERNEL(): -@snippet modules/gapi/samples/kernel_api_snippets.cpp compound +@snippet samples/cpp/tutorial_code/gapi/doc_snippets/kernel_api_snippets.cpp compound diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi.hpp index e4b20214796..f10dfd471db 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi.hpp @@ -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-2021 Intel Corporation #ifndef OPENCV_GAPI_HPP @@ -19,6 +19,7 @@ @} @defgroup gapi_std_backends G-API Standard Backends @defgroup gapi_compile_args G-API Graph Compilation Arguments + @defgroup gapi_serialization G-API Serialization functionality @} */ diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/core.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/core.hpp index a01a8902b6f..052c6a944ca 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/core.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/core.hpp @@ -29,6 +29,10 @@ */ namespace cv { namespace gapi { +/** + * @brief This namespace contains G-API Operation Types for OpenCV + * Core module functionality. + */ namespace core { using GMat2 = std::tuple; using GMat3 = std::tuple; // FIXME: how to avoid this? @@ -53,6 +57,7 @@ namespace core { G_TYPED_KERNEL(GAddC, , "org.opencv.core.math.addC") { static GMatDesc outMeta(GMatDesc a, GScalarDesc, int ddepth) { + GAPI_Assert(a.chan <= 4); return a.withDepth(ddepth); } }; @@ -298,8 +303,8 @@ namespace core { } }; - G_TYPED_KERNEL(GAbsDiffC, , "org.opencv.core.matrixop.absdiffC") { - static GMatDesc outMeta(GMatDesc a, GScalarDesc) { + G_TYPED_KERNEL(GAbsDiffC, , "org.opencv.core.matrixop.absdiffC") { + static GMatDesc outMeta(const GMatDesc& a, const GScalarDesc&) { return a; } }; @@ -394,7 +399,7 @@ namespace core { }; G_TYPED_KERNEL(GResize, , "org.opencv.core.transform.resize") { - static GMatDesc outMeta(GMatDesc in, Size sz, double fx, double fy, int) { + static GMatDesc outMeta(GMatDesc in, Size sz, double fx, double fy, int /*interp*/) { if (sz.width != 0 && sz.height != 0) { return in.withSize(sz); @@ -575,6 +580,12 @@ namespace core { return std::make_tuple(empty_gopaque_desc(), empty_array_desc(), empty_array_desc()); } }; + + G_TYPED_KERNEL(GTranspose, , "org.opencv.core.transpose") { + static GMatDesc outMeta(GMatDesc in) { + return in.withSize({in.size.height, in.size.width}); + } + }; } // namespace core namespace streaming { @@ -591,6 +602,12 @@ G_TYPED_KERNEL(GSizeR, (GOpaque)>, "org.opencv.streaming.siz return empty_gopaque_desc(); } }; + +G_TYPED_KERNEL(GSizeMF, (GFrame)>, "org.opencv.streaming.sizeMF") { + static GOpaqueDesc outMeta(const GFrameDesc&) { + return empty_gopaque_desc(); + } +}; } // namespace streaming //! @addtogroup gapi_math @@ -639,7 +656,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 addC(const GMat& src1, const GScalar& c, int ddepth = -1); +GAPI_EXPORTS_W GMat addC(const GMat& src1, const GScalar& c, int ddepth = -1); //! @overload GAPI_EXPORTS GMat addC(const GScalar& c, const GMat& src1, int ddepth = -1); @@ -754,7 +771,10 @@ GAPI_EXPORTS GMat mulC(const GScalar& multiplier, const GMat& src, int ddepth = The function divides one matrix by another: \f[\texttt{dst(I) = saturate(src1(I)*scale/src2(I))}\f] -When src2(I) is zero, dst(I) will also be zero. Different channels of +For integer types when src2(I) is zero, dst(I) will also be zero. +Floating point case returns Inf/NaN (according to IEEE). + +Different channels of multi-channel matrices are processed independently. The matrices can be single or multi channel. Output matrix must have the same size and depth as src. @@ -1484,7 +1504,7 @@ enlarge an image, it will generally look best with cv::INTER_CUBIC (slow) or cv: @sa warpAffine, warpPerspective, remap, resizeP */ -GAPI_EXPORTS GMat resize(const GMat& src, const Size& dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR); +GAPI_EXPORTS_W GMat resize(const GMat& src, const Size& dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR); /** @brief Resizes a planar image. @@ -1903,14 +1923,14 @@ kmeans(const GMat& data, const int K, const GMat& bestLabels, - Function textual ID is "org.opencv.core.kmeansNDNoInit" - #KMEANS_USE_INITIAL_LABELS flag must not be set while using this overload. */ -GAPI_EXPORTS std::tuple,GMat,GMat> +GAPI_EXPORTS_W std::tuple,GMat,GMat> kmeans(const GMat& data, const int K, const TermCriteria& criteria, const int attempts, const KmeansFlags flags); /** @overload @note Function textual ID is "org.opencv.core.kmeans2D" */ -GAPI_EXPORTS std::tuple,GArray,GArray> +GAPI_EXPORTS_W std::tuple,GArray,GArray> kmeans(const GArray& data, const int K, const GArray& bestLabels, const TermCriteria& criteria, const int attempts, const KmeansFlags flags); @@ -1921,6 +1941,21 @@ GAPI_EXPORTS std::tuple,GArray,GArray> kmeans(const GArray& data, const int K, const GArray& bestLabels, const TermCriteria& criteria, const int attempts, const KmeansFlags flags); + +/** @brief Transposes a matrix. + +The function transposes the matrix: +\f[\texttt{dst} (i,j) = \texttt{src} (j,i)\f] + +@note + - Function textual ID is "org.opencv.core.transpose" + - No complex conjugation is done in case of a complex matrix. It should be done separately if needed. + +@param src input array. +*/ +GAPI_EXPORTS GMat transpose(const GMat& src); + + namespace streaming { /** @brief Gets dimensions from Mat. @@ -1929,7 +1964,7 @@ namespace streaming { @param src Input tensor @return Size (tensor dimensions). */ -GAPI_EXPORTS GOpaque size(const GMat& src); +GAPI_EXPORTS_W GOpaque size(const GMat& src); /** @overload Gets dimensions from rectangle. @@ -1939,7 +1974,16 @@ Gets dimensions from rectangle. @param r Input rectangle. @return Size (rectangle dimensions). */ -GAPI_EXPORTS GOpaque size(const GOpaque& r); +GAPI_EXPORTS_W GOpaque size(const GOpaque& r); + +/** @brief Gets dimensions from MediaFrame. + +@note Function textual ID is "org.opencv.streaming.sizeMF" + +@param src Input frame +@return Size (frame dimensions). +*/ +GAPI_EXPORTS GOpaque size(const GFrame& src); } //namespace streaming } //namespace gapi } //namespace cv diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp index 6ddcb7270c4..48909a84fc0 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp @@ -28,18 +28,14 @@ namespace gimpl { // Forward-declare an internal class class GCPUExecutable; - - namespace render - { - namespace ocv - { - class GRenderExecutable; - } - } } // namespace gimpl namespace gapi { +/** + * @brief This namespace contains G-API CPU backend functions, + * structures, and symbols. + */ namespace cpu { /** @@ -129,7 +125,6 @@ protected: std::unordered_map m_results; friend class gimpl::GCPUExecutable; - friend class gimpl::render::ocv::GRenderExecutable; }; class GAPI_EXPORTS GCPUKernel @@ -190,6 +185,11 @@ template<> struct get_in >: public get_in>/GArray> conversion should be done more gracefully in the system +template struct get_in> >: public get_in> > +{ +}; + //FIXME(dm): GOpaque/GOpaque conversion should be done more gracefully in the system template<> struct get_in >: public get_in > { @@ -487,7 +487,7 @@ public: #define GAPI_OCV_KERNEL_ST(Name, API, State) \ struct Name: public cv::GCPUStKernelImpl \ - +/// @private class gapi::cpu::GOCVFunctor : public gapi::GFunctor { public: diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/stereo.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/stereo.hpp new file mode 100644 index 00000000000..e2a2242bd0b --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/stereo.hpp @@ -0,0 +1,48 @@ +// 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) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_CPU_STEREO_API_HPP +#define OPENCV_GAPI_CPU_STEREO_API_HPP + +#include // GKernelPackage + +namespace cv { +namespace gapi { +namespace calib3d { +namespace cpu { + +GAPI_EXPORTS GKernelPackage kernels(); + +/** @brief Structure for the Stereo operation initialization parameters.*/ +struct GAPI_EXPORTS StereoInitParam { + StereoInitParam(int nD, int bS, double bL, double f): + numDisparities(nD), blockSize(bS), baseline(bL), focus(f) {} + + StereoInitParam() = default; + + int numDisparities = 0; + int blockSize = 21; + double baseline = 63.5; + double focus = 3.6; +}; + +} // namespace cpu +} // namespace calib3d +} // namespace gapi + +namespace detail { + + template<> struct CompileArgTag { + static const char* tag() { + return "org.opencv.stereoInit"; + } +}; + +} // namespace detail +} // namespace cv + + +#endif // OPENCV_GAPI_CPU_STEREO_API_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidbuffer.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidbuffer.hpp index daa9d4153ed..551f0a398fe 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidbuffer.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidbuffer.hpp @@ -25,7 +25,7 @@ namespace fluid { struct Border { // This constructor is required to support existing kernels which are part of G-API - Border(int _type, cv::Scalar _val) : type(_type), value(_val) {}; + Border(int _type, cv::Scalar _val) : type(_type), value(_val) {} int type; cv::Scalar value; diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp index dbb36d801de..53b68c4e218 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp @@ -25,6 +25,9 @@ namespace cv { namespace gapi { +/** + * @brief This namespace contains G-API Fluid backend functions, structures, and symbols. + */ namespace fluid { /** diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garg.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garg.hpp index d1482da8e48..bfe147f8f06 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garg.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garg.hpp @@ -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-2020 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation #ifndef OPENCV_GAPI_GARG_HPP @@ -171,7 +171,7 @@ using GRunArgs = std::vector; * It's an ordinary overload of addition assignment operator. * * Example of usage: - * @snippet dynamic_graph.cpp GRunArgs usage + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/dynamic_graph_snippets.cpp GRunArgs usage * */ inline GRunArgs& operator += (GRunArgs &lhs, const GRunArgs &rhs) @@ -223,7 +223,7 @@ using GRunArgsP = std::vector; * It's an ordinary overload of addition assignment operator. * * Example of usage: - * @snippet dynamic_graph.cpp GRunArgsP usage + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/dynamic_graph_snippets.cpp GRunArgsP usage * */ inline GRunArgsP& operator += (GRunArgsP &lhs, const GRunArgsP &rhs) @@ -235,8 +235,39 @@ inline GRunArgsP& operator += (GRunArgsP &lhs, const GRunArgsP &rhs) namespace gapi { - GAPI_EXPORTS cv::GRunArgsP bind(cv::GRunArgs &results); - GAPI_EXPORTS cv::GRunArg bind(cv::GRunArgP &out); // FIXME: think more about it +/** + * \addtogroup gapi_serialization + * @{ + * + * @brief G-API functions and classes for serialization and deserialization. + */ +/** @brief Wraps deserialized output GRunArgs to GRunArgsP which can be used by GCompiled. + * + * Since it's impossible to get modifiable output arguments from deserialization + * it needs to be wrapped by this function. + * + * Example of usage: + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp bind after deserialization + * + * @param out_args deserialized GRunArgs. + * @return the same GRunArgs wrapped in GRunArgsP. + * @see deserialize + */ +GAPI_EXPORTS cv::GRunArgsP bind(cv::GRunArgs &out_args); +/** @brief Wraps output GRunArgsP available during graph execution to GRunArgs which can be serialized. + * + * GRunArgsP is pointer-to-value, so to be serialized they need to be binded to real values + * which this function does. + * + * Example of usage: + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp bind before serialization + * + * @param out output GRunArgsP available during graph execution. + * @return the same GRunArgsP wrapped in serializable GRunArgs. + * @see serialize + */ +GAPI_EXPORTS cv::GRunArg bind(cv::GRunArgP &out); // FIXME: think more about it +/** @} */ } template inline GRunArgs gin(const Ts&... args) @@ -249,6 +280,30 @@ template inline GRunArgsP gout(Ts&... args) return GRunArgsP{ GRunArgP(detail::wrap_host_helper::wrap_out(args))... }; } +struct GTypeInfo; +using GTypesInfo = std::vector; + +// FIXME: Needed for python bridge, must be moved to more appropriate header +namespace detail { +struct ExtractArgsCallback +{ + cv::GRunArgs operator()(const cv::GTypesInfo& info) const { return c(info); } + using CallBackT = std::function; + CallBackT c; +}; + +struct ExtractMetaCallback +{ + cv::GMetaArgs operator()(const cv::GTypesInfo& info) const { return c(info); } + using CallBackT = std::function; + CallBackT c; +}; + +void constructGraphOutputs(const cv::GTypesInfo &out_info, + cv::GRunArgs &args, + cv::GRunArgsP &outs); +} // namespace detail + } // namespace cv #endif // OPENCV_GAPI_GARG_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garray.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garray.hpp index 5d4b3c59e0d..17b03332e00 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garray.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garray.hpp @@ -35,14 +35,14 @@ template class GArray; * \addtogroup gapi_meta_args * @{ */ -struct GArrayDesc +struct GAPI_EXPORTS_W_SIMPLE GArrayDesc { // FIXME: Body // FIXME: Also implement proper operator== then bool operator== (const GArrayDesc&) const { return true; } }; template GArrayDesc descr_of(const std::vector &) { return {};} -static inline GArrayDesc empty_array_desc() {return {}; } +GAPI_EXPORTS_W inline GArrayDesc empty_array_desc() {return {}; } /** @} */ std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &desc); @@ -236,7 +236,7 @@ namespace detail class VectorRef { std::shared_ptr m_ref; - cv::detail::OpaqueKind m_kind; + cv::detail::OpaqueKind m_kind = cv::detail::OpaqueKind::CV_UNKNOWN; template inline void check() const { @@ -246,12 +246,18 @@ namespace detail public: VectorRef() = default; - template explicit VectorRef(const std::vector& vec) : - m_ref(new VectorRefT(vec)), m_kind(GOpaqueTraits::kind) {} - template explicit VectorRef(std::vector& vec) : - m_ref(new VectorRefT(vec)), m_kind(GOpaqueTraits::kind) {} - template explicit VectorRef(std::vector&& vec) : - m_ref(new VectorRefT(std::move(vec))), m_kind(GOpaqueTraits::kind) {} + template explicit VectorRef(const std::vector& vec) + : m_ref(new VectorRefT(vec)) + , m_kind(GOpaqueTraits::kind) + {} + template explicit VectorRef(std::vector& vec) + : m_ref(new VectorRefT(vec)) + , m_kind(GOpaqueTraits::kind) + {} + template explicit VectorRef(std::vector&& vec) + : m_ref(new VectorRefT(std::move(vec))) + , m_kind(GOpaqueTraits::kind) + {} cv::detail::OpaqueKind getKind() const { @@ -321,9 +327,10 @@ namespace detail # define FLATTEN_NS cv #endif template struct flatten_g; - template<> struct flatten_g { using type = FLATTEN_NS::Mat; }; - template<> struct flatten_g { using type = FLATTEN_NS::Scalar; }; - template struct flatten_g { using type = T; }; + template<> struct flatten_g { using type = FLATTEN_NS::Mat; }; + template<> struct flatten_g { using type = FLATTEN_NS::Scalar; }; + template struct flatten_g> { using type = std::vector; }; + template struct flatten_g { using type = T; }; #undef FLATTEN_NS // FIXME: the above mainly duplicates "ProtoToParam" thing from gtyped.hpp // but I decided not to include gtyped here - probably worth moving that stuff @@ -333,21 +340,79 @@ namespace detail /** \addtogroup gapi_data_objects * @{ */ - +/** + * @brief `cv::GArray` template class represents a list of objects + * of class `T` in the graph. + * + * `cv::GArray` describes a functional relationship between + * operations consuming and producing arrays of objects of class + * `T`. The primary purpose of `cv::GArray` is to represent a + * dynamic list of objects -- where the size of the list is not known + * at the graph construction or compile time. Examples include: corner + * and feature detectors (`cv::GArray`), object detection + * and tracking results (`cv::GArray`). Programmers can use + * their own types with `cv::GArray` in the custom operations. + * + * Similar to `cv::GScalar`, `cv::GArray` may be value-initialized + * -- in this case a graph-constant value is associated with the object. + * + * `GArray` is a virtual counterpart of `std::vector`, which is + * usually used to represent the `GArray` data in G-API during the + * execution. + * + * @sa `cv::GOpaque` + */ template class GArray { public: // Host type (or Flat type) - the type this GArray is actually // specified to. + /// @private using HT = typename detail::flatten_g::type>::type; + /** + * @brief Constructs a value-initialized `cv::GArray` + * + * `cv::GArray` objects may have their values + * be associated at graph construction time. It is useful when + * some operation has a `cv::GArray` input which doesn't change during + * the program execution, and is set only once. In this case, + * there is no need to declare such `cv::GArray` as a graph input. + * + * @note The value of `cv::GArray` may be overwritten by assigning some + * other `cv::GArray` to the object using `operator=` -- on the + * assigment, the old association or value is discarded. + * + * @param v a std::vector to associate with this + * `cv::GArray` object. Vector data is copied into the + * `cv::GArray` (no reference to the passed data is held). + */ explicit GArray(const std::vector& v) // Constant value constructor : m_ref(detail::GArrayU(detail::VectorRef(v))) { putDetails(); } + + /** + * @overload + * @brief Constructs a value-initialized `cv::GArray` + * + * @param v a std::vector to associate with this + * `cv::GArray` object. Vector data is moved into the `cv::GArray`. + */ explicit GArray(std::vector&& 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) + + /** + * @brief Constructs an empty `cv::GArray` + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty `cv::GArray` is assigned to a result + * of some operation, it obtains a functional link to this + * operation (and is not empty anymore). + */ + GArray() { putDetails(); } // Empty constructor + + /// @private + explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor + : m_ref(ref) { putDetails(); } // (used by GCall, not for users) /// @private detail::GArrayU strip() const { @@ -368,8 +433,6 @@ private: detail::GArrayU m_ref; }; -using GArrayP2f = GArray; - /** @} */ } // namespace cv diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gasync_context.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gasync_context.hpp index 69ce530fc93..f49b59822d9 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gasync_context.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gasync_context.hpp @@ -17,6 +17,13 @@ namespace cv { namespace gapi{ + +/** + * @brief This namespace contains experimental G-API functionality, + * functions or structures in this namespace are subjects to change or + * removal in the future releases. This namespace also contains + * functions which API is not stabilized yet. + */ namespace wip { /** diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcommon.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcommon.hpp index 8119e397ebf..dfbd9e3a2ad 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcommon.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcommon.hpp @@ -44,6 +44,7 @@ namespace detail CV_UNKNOWN, // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization CV_BOOL, // bool user G-API data CV_INT, // int user G-API data + CV_INT64, // int64_t user G-API data CV_DOUBLE, // double user G-API data CV_FLOAT, // float user G-API data CV_UINT64, // uint64_t user G-API data @@ -61,6 +62,7 @@ namespace detail template struct GOpaqueTraits; template struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT64; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_FLOAT; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UINT64; }; @@ -132,12 +134,12 @@ namespace detail { * * For example, if an example computation is executed like this: * - * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_decl_apply + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_decl_apply * * Extra parameter specifying which kernels to compile with can be * passed like this: * - * @snippet modules/gapi/samples/api_ref_snippets.cpp apply_with_param + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp apply_with_param */ /** @@ -195,6 +197,14 @@ private: using GCompileArgs = std::vector; +inline cv::GCompileArgs& operator += ( cv::GCompileArgs &lhs, + const cv::GCompileArgs &rhs) +{ + lhs.reserve(lhs.size() + rhs.size()); + lhs.insert(lhs.end(), rhs.begin(), rhs.end()); + return lhs; +} + /** * @brief Wraps a list of arguments (a parameter pack) into a vector of * compilation arguments (cv::GCompileArg). diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcomputation.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcomputation.hpp index 8732ada0d6c..13944c78528 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcomputation.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcomputation.hpp @@ -61,11 +61,11 @@ namespace s11n { * executed. The below example expresses calculation of Sobel operator * for edge detection (\f$G = \sqrt{G_x^2 + G_y^2}\f$): * - * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_def + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_def * * Full pipeline can be now captured with this object declaration: * - * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_cap_full + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_cap_full * * Input/output data objects on which a call graph should be * reconstructed are passed using special wrappers cv::GIn and @@ -78,7 +78,7 @@ namespace s11n { * expects that image gradients are already pre-calculated may be * defined like this: * - * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_cap_sub + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_cap_sub * * The resulting graph would expect two inputs and produce one * output. In this case, it doesn't matter if gx/gy data objects are @@ -130,7 +130,7 @@ public: * Graph can be defined in-place directly at the moment of its * construction with a lambda: * - * @snippet modules/gapi/samples/api_ref_snippets.cpp graph_gen + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp graph_gen * * This may be useful since all temporary objects (cv::GMats) and * namespaces can be localized to scope of lambda, without @@ -258,7 +258,8 @@ public: void apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); // Arg-to-arg overload /// @private -- Exclude this function from OpenCV documentation - GAPI_WRAP GRunArgs apply(GRunArgs &&ins, GCompileArgs &&args = {}); + GAPI_WRAP GRunArgs apply(const cv::detail::ExtractArgsCallback &callback, + GCompileArgs &&args = {}); /// @private -- Exclude this function from OpenCV documentation void apply(const std::vector& ins, // Compatibility overload @@ -459,6 +460,10 @@ public: */ GAPI_WRAP GStreamingCompiled compileStreaming(GCompileArgs &&args = {}); + /// @private -- Exclude this function from OpenCV documentation + GAPI_WRAP GStreamingCompiled compileStreaming(const cv::detail::ExtractMetaCallback &callback, + GCompileArgs &&args = {}); + // 2. Direct metadata version /** * @overload diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gframe.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gframe.hpp index 13fd5d6d295..96913dc4cc5 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gframe.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gframe.hpp @@ -28,14 +28,54 @@ struct GOrigin; /** \addtogroup gapi_data_objects * @{ */ +/** + * @brief GFrame class represents an image or media frame in the graph. + * + * GFrame doesn't store any data itself, instead it describes a + * functional relationship between operations consuming and producing + * GFrame objects. + * + * GFrame is introduced to handle various media formats (e.g., NV12 or + * I420) under the same type. Various image formats may differ in the + * number of planes (e.g. two for NV12, three for I420) and the pixel + * layout inside. GFrame type allows to handle these media formats in + * the graph uniformly -- the graph structure will not change if the + * media format changes, e.g. a different camera or decoder is used + * with the same graph. G-API provides a number of operations which + * operate directly on GFrame, like `infer<>()` or + * renderFrame(); these operations are expected to handle different + * media formats inside. There is also a number of accessor + * operations like BGR(), Y(), UV() -- these operations provide + * access to frame's data in the familiar cv::GMat form, which can be + * used with the majority of the existing G-API operations. These + * accessor functions may perform color space converion on the fly if + * the image format of the GFrame they are applied to differs from the + * operation's semantic (e.g. the BGR() accessor is called on an NV12 + * image frame). + * + * GFrame is a virtual counterpart of cv::MediaFrame. + * + * @sa cv::MediaFrame, cv::GFrameDesc, BGR(), Y(), UV(), infer<>(). + */ class GAPI_EXPORTS_W_SIMPLE GFrame { public: - GAPI_WRAP GFrame(); // Empty constructor - GFrame(const GNode &n, std::size_t out); // Operation result constructor + /** + * @brief Constructs an empty GFrame + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty GFrame is assigned to a result of some + * operation, it obtains a functional link to this operation (and + * is not empty anymore). + */ + GAPI_WRAP GFrame(); // Empty constructor - GOrigin& priv(); // Internal use only - const GOrigin& priv() const; // Internal use only + /// @private + GFrame(const GNode &n, std::size_t out); // Operation result constructor + /// @private + GOrigin& priv(); // Internal use only + /// @private + const GOrigin& priv() const; // Internal use only private: std::shared_ptr m_priv; diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gkernel.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gkernel.hpp index 2c44c67a963..4d3fbd82c57 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gkernel.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gkernel.hpp @@ -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-2020 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation #ifndef OPENCV_GAPI_GKERNEL_HPP @@ -30,6 +30,7 @@ struct GTypeInfo { GShape shape; cv::detail::OpaqueKind kind; + detail::HostCtor ctor; }; using GShapes = std::vector; @@ -371,6 +372,7 @@ namespace gapi { // Prework: model "Device" API before it gets to G-API headers. // FIXME: Don't mix with internal Backends class! + /// @private class GAPI_EXPORTS GBackend { public: @@ -411,6 +413,7 @@ namespace std namespace cv { namespace gapi { + /// @private class GFunctor { public: @@ -516,6 +519,13 @@ namespace gapi { */ const std::vector& get_transformations() const; + /** + * @brief Returns vector of kernel ids included in the package + * + * @return vector of kernel ids included in the package + */ + std::vector get_kernel_ids() const; + /** * @brief Test if a particular kernel _implementation_ KImpl is * included in this kernel package. @@ -605,6 +615,18 @@ namespace gapi { includeHelper(); } + /** + * @brief Adds a new kernel based on it's backend and id into the kernel package + * + * @param backend backend associated with the kernel + * @param kernel_id a name/id of the kernel + */ + void include(const cv::gapi::GBackend& backend, const std::string& kernel_id) + { + removeAPI(kernel_id); + m_id_kernels[kernel_id] = std::make_pair(backend, GKernelImpl{{}, {}}); + } + /** * @brief Lists all backends which are included into package * @@ -637,7 +659,7 @@ namespace gapi { * Use this function to pass kernel implementations (defined in * either way) and transformations to the system. Example: * - * @snippet modules/gapi/samples/api_ref_snippets.cpp kernels_snippet + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp kernels_snippet * * Note that kernels() itself is a function returning object, not * a type, so having `()` at the end is important -- it must be a @@ -697,7 +719,7 @@ namespace gapi { * @{ */ /** - * @brief cv::use_only() is a special combinator which hints G-API to use only + * @brief cv::gapi::use_only() is a special combinator which hints G-API to use only * kernels specified in cv::GComputation::compile() (and not to extend kernels available by * default with that package). */ diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmat.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmat.hpp index 20a10db92b5..7bea97bbc52 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmat.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmat.hpp @@ -30,29 +30,57 @@ struct GOrigin; * @brief G-API data objects used to build G-API expressions. * * These objects do not own any particular data (except compile-time - * associated values like with cv::GScalar) and are used to construct - * graphs. + * associated values like with cv::GScalar or `cv::GArray`) and are + * used only to construct graphs. * * Every graph in G-API starts and ends with data objects. * * Once constructed and compiled, G-API operates with regular host-side * data instead. Refer to the below table to find the mapping between - * G-API and regular data types. + * G-API and regular data types when passing input and output data + * structures to G-API: * * G-API data type | I/O data type * ------------------ | ------------- - * cv::GMat | cv::Mat + * cv::GMat | cv::Mat, cv::UMat, cv::RMat * cv::GScalar | cv::Scalar * `cv::GArray` | std::vector * `cv::GOpaque` | T + * cv::GFrame | cv::MediaFrame + */ +/** + * @brief GMat class represents image or tensor data in the + * graph. + * + * GMat doesn't store any data itself, instead it describes a + * functional relationship between operations consuming and producing + * GMat objects. + * + * GMat is a virtual counterpart of Mat and UMat, but it + * doesn't mean G-API use Mat or UMat objects internally to represent + * GMat objects -- the internal data representation may be + * backend-specific or optimized out at all. + * + * @sa Mat, GMatDesc */ class GAPI_EXPORTS_W_SIMPLE GMat { public: + /** + * @brief Constructs an empty GMat + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty GMat is assigned to a result of some + * operation, it obtains a functional link to this operation (and + * is not empty anymore). + */ GAPI_WRAP GMat(); // Empty constructor - GMat(const GNode &n, std::size_t out); // Operation result constructor + /// @private + GMat(const GNode &n, std::size_t out); // Operation result constructor + /// @private GOrigin& priv(); // Internal use only + /// @private const GOrigin& priv() const; // Internal use only private: @@ -73,25 +101,25 @@ class RMat; * \addtogroup gapi_meta_args * @{ */ -struct GAPI_EXPORTS GMatDesc +struct GAPI_EXPORTS_W_SIMPLE GMatDesc { // FIXME: Default initializers in C++14 - int depth; - int chan; - cv::Size size; // NB.: no multi-dimensional cases covered yet - bool planar; - std::vector dims; // FIXME: Maybe it's real questionable to have it here + GAPI_PROP int depth; + GAPI_PROP int chan; + GAPI_PROP cv::Size size; // NB.: no multi-dimensional cases covered yet + GAPI_PROP bool planar; + GAPI_PROP std::vector dims; // FIXME: Maybe it's real questionable to have it here - GMatDesc(int d, int c, cv::Size s, bool p = false) + GAPI_WRAP GMatDesc(int d, int c, cv::Size s, bool p = false) : depth(d), chan(c), size(s), planar(p) {} - GMatDesc(int d, const std::vector &dd) + GAPI_WRAP GMatDesc(int d, const std::vector &dd) : depth(d), chan(-1), size{-1,-1}, planar(false), dims(dd) {} - GMatDesc(int d, std::vector &&dd) + GAPI_WRAP GMatDesc(int d, std::vector &&dd) : depth(d), chan(-1), size{-1,-1}, planar(false), dims(std::move(dd)) {} - GMatDesc() : GMatDesc(-1, -1, {-1,-1}) {} + GAPI_WRAP GMatDesc() : GMatDesc(-1, -1, {-1,-1}) {} inline bool operator== (const GMatDesc &rhs) const { @@ -120,7 +148,7 @@ struct GAPI_EXPORTS GMatDesc // Meta combinator: return a new GMatDesc which differs in size by delta // (all other fields are taken unchanged from this GMatDesc) // FIXME: a better name? - GMatDesc withSizeDelta(cv::Size delta) const + GAPI_WRAP GMatDesc withSizeDelta(cv::Size delta) const { GMatDesc desc(*this); desc.size += delta; @@ -130,12 +158,12 @@ struct GAPI_EXPORTS GMatDesc // (all other fields are taken unchanged from this GMatDesc) // // This is an overload. - GMatDesc withSizeDelta(int dx, int dy) const + GAPI_WRAP GMatDesc withSizeDelta(int dx, int dy) const { return withSizeDelta(cv::Size{dx,dy}); } - GMatDesc withSize(cv::Size sz) const + GAPI_WRAP GMatDesc withSize(cv::Size sz) const { GMatDesc desc(*this); desc.size = sz; @@ -144,7 +172,7 @@ struct GAPI_EXPORTS GMatDesc // Meta combinator: return a new GMatDesc with specified data depth. // (all other fields are taken unchanged from this GMatDesc) - GMatDesc withDepth(int ddepth) const + GAPI_WRAP GMatDesc withDepth(int ddepth) const { GAPI_Assert(CV_MAT_CN(ddepth) == 1 || ddepth == -1); GMatDesc desc(*this); @@ -155,7 +183,7 @@ struct GAPI_EXPORTS GMatDesc // Meta combinator: return a new GMatDesc with specified data depth // and number of channels. // (all other fields are taken unchanged from this GMatDesc) - GMatDesc withType(int ddepth, int dchan) const + GAPI_WRAP GMatDesc withType(int ddepth, int dchan) const { GAPI_Assert(CV_MAT_CN(ddepth) == 1 || ddepth == -1); GMatDesc desc = withDepth(ddepth); @@ -166,7 +194,7 @@ struct GAPI_EXPORTS GMatDesc // Meta combinator: return a new GMatDesc with planar flag set // (no size changes are performed, only channel interpretation is changed // (interleaved -> planar) - GMatDesc asPlanar() const + GAPI_WRAP GMatDesc asPlanar() const { GAPI_Assert(planar == false); GMatDesc desc(*this); @@ -177,7 +205,7 @@ struct GAPI_EXPORTS GMatDesc // Meta combinator: return a new GMatDesc // reinterpreting 1-channel input as planar image // (size height is divided by plane number) - GMatDesc asPlanar(int planes) const + GAPI_WRAP GMatDesc asPlanar(int planes) const { GAPI_Assert(planar == false); GAPI_Assert(chan == 1); @@ -192,7 +220,7 @@ struct GAPI_EXPORTS GMatDesc // Meta combinator: return a new GMatDesc with planar flag set to false // (no size changes are performed, only channel interpretation is changed // (planar -> interleaved) - GMatDesc asInterleaved() const + GAPI_WRAP GMatDesc asInterleaved() const { GAPI_Assert(planar == true); GMatDesc desc(*this); diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gopaque.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gopaque.hpp index 6117971768b..f77795c5069 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gopaque.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gopaque.hpp @@ -21,6 +21,9 @@ #include #include +#include // OpaqueKind +#include // TypeHintBase + namespace cv { // Forward declaration; GNode and GOrigin are an internal @@ -33,14 +36,14 @@ template class GOpaque; * \addtogroup gapi_meta_args * @{ */ -struct GOpaqueDesc +struct GAPI_EXPORTS_W_SIMPLE GOpaqueDesc { // FIXME: Body // FIXME: Also implement proper operator== then bool operator== (const GOpaqueDesc&) const { return true; } }; template GOpaqueDesc descr_of(const U &) { return {};} -static inline GOpaqueDesc empty_gopaque_desc() {return {}; } +GAPI_EXPORTS_W inline GOpaqueDesc empty_gopaque_desc() {return {}; } /** @} */ std::ostream& operator<<(std::ostream& os, const cv::GOpaqueDesc &desc); @@ -229,7 +232,7 @@ namespace detail class OpaqueRef { std::shared_ptr m_ref; - cv::detail::OpaqueKind m_kind; + cv::detail::OpaqueKind m_kind = cv::detail::OpaqueKind::CV_UNKNOWN; template inline void check() const { @@ -304,15 +307,40 @@ namespace detail /** \addtogroup gapi_data_objects * @{ */ - +/** + * @brief `cv::GOpaque` template class represents an object of + * class `T` in the graph. + * + * `cv::GOpaque` describes a functional relationship between operations + * consuming and producing object of class `T`. `cv::GOpaque` is + * designed to extend G-API with user-defined data types, which are + * often required with user-defined operations. G-API can't apply any + * optimizations to user-defined types since these types are opaque to + * the framework. However, there is a number of G-API operations + * declared with `cv::GOpaque` as a return type, + * e.g. cv::gapi::streaming::timestamp() or cv::gapi::streaming::size(). + * + * @sa `cv::GArray` + */ template class GOpaque { public: // Host type (or Flat type) - the type this GOpaque is actually // specified to. + /// @private using HT = typename detail::flatten_g>::type; + /** + * @brief Constructs an empty `cv::GOpaque` + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty `cv::GOpaque` is assigned to a result + * of some operation, it obtains a functional link to this + * operation (and is not empty anymore). + */ GOpaque() { putDetails(); } // Empty constructor + + /// @private explicit GOpaque(detail::GOpaqueU &&ref) // GOpaqueU-based constructor : m_ref(ref) { putDetails(); } // (used by GCall, not for users) diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gproto.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gproto.hpp index f91fcdb2c8c..a2b5d83bc1e 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gproto.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gproto.hpp @@ -71,7 +71,7 @@ public: * It's an ordinary overload of addition assignment operator. * * Example of usage: - * @snippet dynamic_graph.cpp GIOProtoArgs usage + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/dynamic_graph_snippets.cpp GIOProtoArgs usage * */ template @@ -135,7 +135,7 @@ GRunArg value_of(const GOrigin &origin); // Transform run-time computation arguments into a collection of metadata // extracted from that arguments GMetaArg GAPI_EXPORTS descr_of(const GRunArg &arg ); -GMetaArgs GAPI_EXPORTS_W descr_of(const GRunArgs &args); +GMetaArgs GAPI_EXPORTS descr_of(const GRunArgs &args); // Transform run-time operation result argument into metadata extracted from that argument // Used to compare the metadata, which generated at compile time with the metadata result operation in run time diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gscalar.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gscalar.hpp index 00abdd1d139..7ebededcf0c 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gscalar.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gscalar.hpp @@ -25,18 +25,83 @@ struct GOrigin; /** \addtogroup gapi_data_objects * @{ */ - +/** + * @brief GScalar class represents cv::Scalar data in the graph. + * + * GScalar may be associated with a cv::Scalar value, which becomes + * its constant value bound in graph compile time. cv::GScalar describes a + * functional relationship between operations consuming and producing + * GScalar objects. + * + * GScalar is a virtual counterpart of cv::Scalar, which is usually used + * to represent the GScalar data in G-API during the execution. + * + * @sa Scalar + */ class GAPI_EXPORTS_W_SIMPLE GScalar { public: - GAPI_WRAP GScalar(); // Empty constructor - explicit GScalar(const cv::Scalar& s); // Constant value constructor from cv::Scalar + /** + * @brief Constructs an empty GScalar + * + * Normally, empty G-API data objects denote a starting point of + * the graph. When an empty GScalar is assigned to a result of some + * operation, it obtains a functional link to this operation (and + * is not empty anymore). + */ + GAPI_WRAP GScalar(); + + /** + * @brief Constructs a value-initialized GScalar + * + * In contrast with GMat (which can be either an explicit graph input + * or a result of some operation), GScalars may have their values + * be associated at graph construction time. It is useful when + * some operation has a GScalar input which doesn't change during + * the program execution, and is set only once. In this case, + * there is no need to declare such GScalar as a graph input. + * + * @note The value of GScalar may be overwritten by assigning some + * other GScalar to the object using `operator=` -- on the + * assigment, the old GScalar value is discarded. + * + * @param s a cv::Scalar value to associate with this GScalar object. + */ + explicit GScalar(const cv::Scalar& s); + + /** + * @overload + * @brief Constructs a value-initialized GScalar + * + * @param s a cv::Scalar value to associate with this GScalar object. + */ explicit GScalar(cv::Scalar&& s); // Constant value move-constructor from cv::Scalar + /** + * @overload + * @brief Constructs a value-initialized GScalar + * + * @param v0 A `double` value to associate with this GScalar. Note + * that only the first component of a four-component cv::Scalar is + * set to this value, with others remain zeros. + * + * This constructor overload is not marked `explicit` and can be + * used in G-API expression code like this: + * + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp gscalar_implicit + * + * Here operator+(GMat,GScalar) is used to wrap cv::gapi::addC() + * and a value-initialized GScalar is created on the fly. + * + * @overload + */ GScalar(double v0); // Constant value constructor from double - GScalar(const GNode &n, std::size_t out); // Operation result constructor + /// @private + GScalar(const GNode &n, std::size_t out); // Operation result constructor + /// @private GOrigin& priv(); // Internal use only + /// @private const GOrigin& priv() const; // Internal use only private: @@ -49,7 +114,7 @@ private: * \addtogroup gapi_meta_args * @{ */ -struct GScalarDesc +struct GAPI_EXPORTS_W_SIMPLE GScalarDesc { // NB.: right now it is empty @@ -64,9 +129,9 @@ struct GScalarDesc } }; -static inline GScalarDesc empty_scalar_desc() { return GScalarDesc(); } +GAPI_EXPORTS_W inline GScalarDesc empty_scalar_desc() { return GScalarDesc(); } -GAPI_EXPORTS GScalarDesc descr_of(const cv::Scalar &scalar); +GAPI_EXPORTS GScalarDesc descr_of(const cv::Scalar &scalar); std::ostream& operator<<(std::ostream& os, const cv::GScalarDesc &desc); diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gstreaming.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gstreaming.hpp index e09cf8d0f78..890eb584fb0 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gstreaming.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gstreaming.hpp @@ -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-2021 Intel Corporation #ifndef OPENCV_GAPI_GSTREAMING_COMPILED_HPP @@ -65,12 +65,23 @@ using OptionalOpaqueRef = OptRef; using GOptRunArgP = util::variant< optional*, optional*, + optional*, optional*, cv::detail::OptionalVectorRef, cv::detail::OptionalOpaqueRef >; using GOptRunArgsP = std::vector; +using GOptRunArg = util::variant< + optional, + optional, + optional, + optional, + optional, + optional +>; +using GOptRunArgs = std::vector; + namespace detail { template inline GOptRunArgP wrap_opt_arg(optional& arg) { @@ -86,6 +97,14 @@ template<> inline GOptRunArgP wrap_opt_arg(optional &m) { return GOptRunArgP{&m}; } +template<> inline GOptRunArgP wrap_opt_arg(optional &m) { + return GOptRunArgP{&m}; +} + +template<> inline GOptRunArgP wrap_opt_arg(optional &f) { + return GOptRunArgP{&f}; +} + template<> inline GOptRunArgP wrap_opt_arg(optional &s) { return GOptRunArgP{&s}; } @@ -180,7 +199,10 @@ public: * @param ins vector of inputs to process. * @sa gin */ - GAPI_WRAP void setSource(GRunArgs &&ins); + void setSource(GRunArgs &&ins); + + /// @private -- Exclude this function from OpenCV documentation + GAPI_WRAP void setSource(const cv::detail::ExtractArgsCallback& callback); /** * @brief Specify an input video stream for a single-input @@ -193,7 +215,7 @@ public: * @param s a shared pointer to IStreamSource representing the * input video stream. */ - GAPI_WRAP void setSource(const gapi::wip::IStreamSource::Ptr& s); + void setSource(const gapi::wip::IStreamSource::Ptr& s); /** * @brief Constructs and specifies an input video stream for a @@ -251,7 +273,8 @@ public: bool pull(cv::GRunArgsP &&outs); // NB: Used from python - GAPI_WRAP std::tuple pull(); + /// @private -- Exclude this function from OpenCV documentation + GAPI_WRAP std::tuple> pull(); /** * @brief Get some next available data from the pipeline. @@ -367,6 +390,41 @@ protected: }; /** @} */ +namespace gapi { + +/** + * @brief This namespace contains G-API functions, structures, and + * symbols related to the Streaming execution mode. + * + * Some of the operations defined in this namespace (e.g. size(), + * BGR(), etc.) can be used in the traditional execution mode too. + */ +namespace streaming { +/** + * @brief Specify queue capacity for streaming execution. + * + * In the streaming mode the pipeline steps are connected with queues + * and this compile argument controls every queue's size. + */ +struct GAPI_EXPORTS_W_SIMPLE queue_capacity +{ + GAPI_WRAP + explicit queue_capacity(size_t cap = 1) : capacity(cap) { }; + GAPI_PROP_RW + size_t capacity; +}; +/** @} */ +} // namespace streaming +} // namespace gapi + +namespace detail +{ +template<> struct CompileArgTag +{ + static const char* tag() { return "gapi.queue_capacity"; } +}; +} + } #endif // OPENCV_GAPI_GSTREAMING_COMPILED_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtransform.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtransform.hpp index 5d1b91b5173..109bc87b7f0 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtransform.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtransform.hpp @@ -31,7 +31,7 @@ struct GAPI_EXPORTS GTransform F pattern; F substitute; - GTransform(const std::string& d, const F &p, const F &s) : description(d), pattern(p), substitute(s){}; + GTransform(const std::string& d, const F &p, const F &s) : description(d), pattern(p), substitute(s) {} }; namespace detail diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtype_traits.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtype_traits.hpp index 2e8dcb1aec7..2b43421907a 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtype_traits.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtype_traits.hpp @@ -19,11 +19,25 @@ #include #include #include +#include +#include namespace cv { namespace detail { + template + struct contains_shape_field : std::false_type {}; + + template + struct contains_shape_field> : + std::is_same::type, GShape> + {}; + + template + struct has_gshape : contains_shape_field {}; + // FIXME: These traits and enum and possible numerous switch(kind) // block may be replaced with a special Handler object or with // a double dispatch @@ -181,10 +195,16 @@ namespace detail } template static auto wrap_in (const U &u) -> typename GTypeTraits::strip_type { + static_assert(!(cv::detail::has_gshape>::value + || cv::detail::contains::type, GAPI_OWN_TYPES_LIST>::value), + "gin/gout must not be used with G* classes or cv::gapi::own::*"); return GTypeTraits::wrap_in(u); } template static auto wrap_out(U &u) -> typename GTypeTraits::strip_type { + static_assert(!(cv::detail::has_gshape>::value + || cv::detail::contains::type, GAPI_OWN_TYPES_LIST>::value), + "gin/gout must not be used with G* classses or cv::gapi::own::*"); return GTypeTraits::wrap_out(u); } }; diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtyped.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtyped.hpp index 6fe52a62e16..c1c16d17670 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtyped.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtyped.hpp @@ -57,7 +57,7 @@ namespace detail * * Refer to the following example. Regular (untyped) code is written this way: * - * @snippet modules/gapi/samples/api_ref_snippets.cpp Untyped_Example + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp Untyped_Example * * Here: * @@ -71,7 +71,7 @@ namespace detail * * Now the same code written with typed API: * - * @snippet modules/gapi/samples/api_ref_snippets.cpp Typed_Example + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp Typed_Example * * The key difference is: * diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/imgproc.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/imgproc.hpp index 63617b42ff4..5c4c6f7031e 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/imgproc.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/imgproc.hpp @@ -47,6 +47,10 @@ void validateFindingContoursMeta(const int depth, const int chan, const int mode namespace cv { namespace gapi { +/** + * @brief This namespace contains G-API Operation Types for OpenCV + * ImgProc module functionality. + */ namespace imgproc { using GMat2 = std::tuple; using GMat3 = std::tuple; // FIXME: how to avoid this? @@ -1158,7 +1162,7 @@ if there are 2 channels, or have 2 columns if there is a single channel. Mat sho @param src Input gray-scale image @ref CV_8UC1; or input set of @ref CV_32S or @ref CV_32F 2D points stored in Mat. */ -GAPI_EXPORTS GOpaque boundingRect(const GMat& src); +GAPI_EXPORTS_W GOpaque boundingRect(const GMat& src); /** @overload @@ -1168,7 +1172,7 @@ Calculates the up-right bounding rectangle of a point set. @param src Input 2D point set, stored in std::vector. */ -GAPI_EXPORTS GOpaque boundingRect(const GArray& src); +GAPI_EXPORTS_W GOpaque boundingRect(const GArray& src); /** @overload @@ -1341,7 +1345,7 @@ Output image is 8-bit unsigned 3-channel image @ref CV_8UC3. @param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3. @sa RGB2BGR */ -GAPI_EXPORTS GMat BGR2RGB(const GMat& src); +GAPI_EXPORTS_W GMat BGR2RGB(const GMat& src); /** @brief Converts an image from RGB color space to gray-scaled. diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer.hpp index 8e3baedb79e..807c82d31f8 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer.hpp @@ -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-2020 Intel Corporation +// Copyright (C) 2019-2021 Intel Corporation #ifndef OPENCV_GAPI_INFER_HPP @@ -76,6 +76,113 @@ struct valid_infer2_types< std::tuple, std::tuple > { valid_infer2_types< std::tuple, std::tuple >::value && valid_infer2_types< std::tuple, std::tuple >::value; }; + +// Struct stores network input/output names. +// Used by infer +struct InOutInfo +{ + std::vector in_names; + std::vector out_names; +}; + +template +class GInferOutputsTyped +{ +public: + GInferOutputsTyped() = default; + GInferOutputsTyped(std::shared_ptr call) + : m_priv(std::make_shared(std::move(call))) + { + } + + OutT at(const std::string& name) + { + auto it = m_priv->blobs.find(name); + if (it == m_priv->blobs.end()) { + // FIXME: Avoid modifying GKernel + auto shape = cv::detail::GTypeTraits::shape; + m_priv->call->kernel().outShapes.push_back(shape); + m_priv->call->kernel().outCtors.emplace_back(cv::detail::GObtainCtor::get()); + auto out_idx = static_cast(m_priv->blobs.size()); + it = m_priv->blobs.emplace(name, + cv::detail::Yield::yield(*(m_priv->call), out_idx)).first; + m_priv->info->out_names.push_back(name); + } + return it->second; + } +private: + struct Priv + { + Priv(std::shared_ptr c) + : call(std::move(c)), info(cv::util::any_cast(&call->params())) + { + } + + std::shared_ptr call; + InOutInfo* info = nullptr; + std::unordered_map blobs; + }; + + std::shared_ptr m_priv; +}; + +template +class GInferInputsTyped +{ +public: + GInferInputsTyped() + : m_priv(std::make_shared()) + { + } + + template + GInferInputsTyped& setInput(const std::string& name, U in) + { + m_priv->blobs.emplace(std::piecewise_construct, + std::forward_as_tuple(name), + std::forward_as_tuple(in)); + return *this; + } + + using StorageT = cv::util::variant; + StorageT& operator[](const std::string& name) { + return m_priv->blobs[name]; + } + + using Map = std::unordered_map; + const Map& getBlobs() const { + return m_priv->blobs; + } + +private: + struct Priv + { + std::unordered_map blobs; + }; + + std::shared_ptr m_priv; +}; + +template +std::shared_ptr makeCall(const std::string &tag, + std::vector &&args, + std::vector &&names, + cv::GKinds &&kinds) { + auto call = std::make_shared(GKernel{ + InferT::id(), + tag, + InferT::getOutMeta, + {}, // outShape will be filled later + std::move(kinds), + {}, // outCtors will be filled later + }); + + call->setArgs(std::move(args)); + call->params() = cv::detail::InOutInfo{std::move(names), {}}; + + return call; +} + } // namespace detail // TODO: maybe tuple_wrap_helper from util.hpp may help with this. @@ -166,49 +273,6 @@ struct GInferBase { } }; -// Struct stores network input/output names. -// Used by infer -struct InOutInfo -{ - std::vector in_names; - std::vector out_names; -}; - -/** - * @{ - * @brief G-API object used to collect network inputs - */ -class GAPI_EXPORTS_W_SIMPLE GInferInputs -{ -using Map = std::unordered_map; -public: - GAPI_WRAP GInferInputs(); - GAPI_WRAP void setInput(const std::string& name, const cv::GMat& value); - - cv::GMat& operator[](const std::string& name); - const Map& getBlobs() const; - -private: - std::shared_ptr in_blobs; -}; -/** @} */ - -/** - * @{ - * @brief G-API object used to collect network outputs - */ -struct GAPI_EXPORTS_W_SIMPLE GInferOutputs -{ -public: - GAPI_WRAP GInferOutputs() = default; - GInferOutputs(std::shared_ptr call); - GAPI_WRAP cv::GMat at(const std::string& name); - -private: - struct Priv; - std::shared_ptr m_priv; -}; -/** @} */ // Base "InferROI" kernel. // All notes from "Infer" kernel apply here as well. struct GInferROIBase { @@ -295,6 +359,90 @@ struct GInferList2 final static constexpr const char* tag() { return Net::tag(); } }; +/** + * @brief G-API object used to collect network inputs + */ +using GInferInputs = cv::detail::GInferInputsTyped; + +/** + * @brief G-API object used to collect the list of network inputs + */ +using GInferListInputs = cv::detail::GInferInputsTyped, cv::GArray>; + +/** + * @brief G-API object used to collect network outputs + */ +using GInferOutputs = cv::detail::GInferOutputsTyped; + +/** + * @brief G-API object used to collect the list of network outputs + */ +using GInferListOutputs = cv::detail::GInferOutputsTyped>; + +namespace detail { +void inline unpackBlobs(const cv::GInferInputs::Map& blobs, + std::vector& args, + std::vector& names, + cv::GKinds& kinds) +{ + for (auto&& p : blobs) { + names.emplace_back(p.first); + switch (p.second.index()) { + case cv::GInferInputs::StorageT::index_of(): + args.emplace_back(cv::util::get(p.second)); + kinds.emplace_back(cv::detail::OpaqueKind::CV_MAT); + break; + case cv::GInferInputs::StorageT::index_of(): + args.emplace_back(cv::util::get(p.second)); + kinds.emplace_back(cv::detail::OpaqueKind::CV_UNKNOWN); + break; + default: + GAPI_Assert(false); + } + } +} + +template +struct InferROITraits; + +template <> +struct InferROITraits +{ + using outType = cv::GInferOutputs; + using inType = cv::GOpaque; +}; + +template <> +struct InferROITraits +{ + using outType = cv::GInferListOutputs; + using inType = cv::GArray; +}; + +template +typename InferROITraits::outType +inferGenericROI(const std::string& tag, + const typename InferROITraits::inType& in, + const cv::GInferInputs& inputs) +{ + std::vector args; + std::vector names; + cv::GKinds kinds; + + args.emplace_back(in); + kinds.emplace_back(cv::detail::OpaqueKind::CV_RECT); + + unpackBlobs(inputs.getBlobs(), args, names, kinds); + + auto call = cv::detail::makeCall(tag, + std::move(args), + std::move(names), + std::move(kinds)); + + return {std::move(call)}; +} + +} // namespace detail } // namespace cv // FIXME: Probably the signature makes a function/tuple/function round-trip @@ -384,7 +532,11 @@ typename Net::Result infer(Args&&... args) { } /** - * @brief Special network type + * @brief Generic network type: input and output layers are configured dynamically at runtime + * + * Unlike the network types defined with G_API_NET macro, this one + * doesn't fix number of network inputs and outputs at the compilation stage + * thus providing user with an opportunity to program them in runtime. */ struct Generic { }; @@ -395,38 +547,98 @@ struct Generic { }; * @param inputs networks's inputs * @return a GInferOutputs */ -template GInferOutputs -infer(const std::string& tag, const GInferInputs& inputs) +template cv::GInferOutputs +infer(const std::string& tag, const cv::GInferInputs& inputs) { - std::vector input_args; - std::vector input_names; + std::vector args; + std::vector names; + cv::GKinds kinds; - const auto& blobs = inputs.getBlobs(); - for (auto&& p : blobs) - { - input_names.push_back(p.first); - input_args.emplace_back(p.second); - } + cv::detail::unpackBlobs(inputs.getBlobs(), args, names, kinds); - GKinds kinds(blobs.size(), cv::detail::OpaqueKind::CV_MAT); - auto call = std::make_shared(GKernel{ - GInferBase::id(), - tag, - GInferBase::getOutMeta, - {}, // outShape will be filled later - std::move(kinds), - {}, // outCtors will be filled later - }); + auto call = cv::detail::makeCall(tag, + std::move(args), + std::move(names), + std::move(kinds)); - call->setArgs(std::move(input_args)); - call->params() = InOutInfo{input_names, {}}; - - return GInferOutputs{std::move(call)}; + return cv::GInferOutputs{std::move(call)}; } -GAPI_EXPORTS_W inline GInferOutputs infer(const String& name, const GInferInputs& inputs) +/** @brief Calculates response for the generic network + * for the specified region in the source image. + * Currently expects a single-input network only. + * + * @param tag a network tag + * @param roi a an object describing the region of interest + * in the source image. May be calculated in the same graph dynamically. + * @param inputs networks's inputs + * @return a cv::GInferOutputs + */ +template cv::GInferOutputs +infer(const std::string& tag, const cv::GOpaque& roi, const cv::GInferInputs& inputs) { - return infer(name, inputs); + return cv::detail::inferGenericROI(tag, roi, inputs); +} + +/** @brief Calculates responses for the specified network + * for every region in the source image. + * + * @param tag a network tag + * @param rois a list of rectangles describing regions of interest + * in the source image. Usually an output of object detector or tracker. + * @param inputs networks's inputs + * @return a cv::GInferListOutputs + */ +template cv::GInferListOutputs +infer(const std::string& tag, const cv::GArray& rois, const cv::GInferInputs& inputs) +{ + return cv::detail::inferGenericROI(tag, rois, inputs); +} + +/** @brief Calculates responses for the specified network + * for every region in the source image, extended version. + * + * @param tag a network tag + * @param in a source image containing regions of interest. + * @param inputs networks's inputs + * @return a cv::GInferListOutputs + */ +template +typename std::enable_if::value, cv::GInferListOutputs>::type +infer2(const std::string& tag, + const Input& in, + const cv::GInferListInputs& inputs) +{ + std::vector args; + std::vector names; + cv::GKinds kinds; + + args.emplace_back(in); + auto k = cv::detail::GOpaqueTraits::kind; + kinds.emplace_back(k); + + for (auto&& p : inputs.getBlobs()) { + names.emplace_back(p.first); + switch (p.second.index()) { + case cv::GInferListInputs::StorageT::index_of>(): + args.emplace_back(cv::util::get>(p.second)); + kinds.emplace_back(cv::detail::OpaqueKind::CV_MAT); + break; + case cv::GInferListInputs::StorageT::index_of>(): + args.emplace_back(cv::util::get>(p.second)); + kinds.emplace_back(cv::detail::OpaqueKind::CV_RECT); + break; + default: + GAPI_Assert(false); + } + } + + auto call = cv::detail::makeCall(tag, + std::move(args), + std::move(names), + std::move(kinds)); + + return cv::GInferListOutputs{std::move(call)}; } } // namespace gapi @@ -442,7 +654,8 @@ namespace gapi { // A type-erased form of network parameters. // Similar to how a type-erased GKernel is represented and used. -struct GAPI_EXPORTS GNetParam { +/// @private +struct GAPI_EXPORTS_W_SIMPLE GNetParam { std::string tag; // FIXME: const? GBackend backend; // Specifies the execution model util::any params; // Backend-interpreted parameter structure @@ -453,12 +666,13 @@ struct GAPI_EXPORTS GNetParam { */ /** * @brief A container class for network configurations. Similar to - * GKernelPackage.Use cv::gapi::networks() to construct this object. + * GKernelPackage. Use cv::gapi::networks() to construct this object. * * @sa cv::gapi::networks */ struct GAPI_EXPORTS_W_SIMPLE GNetPackage { GAPI_WRAP GNetPackage() = default; + GAPI_WRAP explicit GNetPackage(std::vector nets); explicit GNetPackage(std::initializer_list ii); std::vector backends() const; std::vector networks; @@ -486,6 +700,14 @@ template cv::gapi::GNetPackage networks(Args&&... args) { return cv::gapi::GNetPackage({ cv::detail::strip(args)... }); } + +inline cv::gapi::GNetPackage& operator += ( cv::gapi::GNetPackage& lhs, + const cv::gapi::GNetPackage& rhs) { + lhs.networks.reserve(lhs.networks.size() + rhs.networks.size()); + lhs.networks.insert(lhs.networks.end(), rhs.networks.begin(), rhs.networks.end()); + return lhs; +} + } // namespace gapi } // namespace cv diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/bindings_ie.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/bindings_ie.hpp index fdd4128b1ae..94272dea55b 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/bindings_ie.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/bindings_ie.hpp @@ -22,17 +22,31 @@ namespace ie { // This class can be marked as SIMPLE, because it's implemented as pimpl class GAPI_EXPORTS_W_SIMPLE PyParams { public: + GAPI_WRAP PyParams() = default; + GAPI_WRAP PyParams(const std::string &tag, const std::string &model, const std::string &weights, const std::string &device); + GAPI_WRAP PyParams(const std::string &tag, const std::string &model, const std::string &device); + GAPI_WRAP + PyParams& constInput(const std::string &layer_name, + const cv::Mat &data, + TraitAs hint = TraitAs::TENSOR); + + GAPI_WRAP + PyParams& cfgNumRequests(size_t nireq); + + GAPI_WRAP + PyParams& cfgBatchSize(const size_t size); + GBackend backend() const; std::string tag() const; cv::util::any params() const; diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/ie.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/ie.hpp index 53e31fbb099..e6b7be58adf 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/ie.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/ie.hpp @@ -2,12 +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) 2019 Intel Corporation +// Copyright (C) 2019-2021 Intel Corporation #ifndef OPENCV_GAPI_INFER_IE_HPP #define OPENCV_GAPI_INFER_IE_HPP #include +#include #include #include #include // tuple, tuple_size @@ -23,12 +24,17 @@ namespace cv { namespace gapi { // FIXME: introduce a new sub-namespace for NN? + +/** + * @brief This namespace contains G-API OpenVINO backend functions, + * structures, and symbols. + */ namespace ie { GAPI_EXPORTS cv::gapi::GBackend backend(); /** - * Specify how G-API and IE should trait input data + * Specifies how G-API and IE should trait input data * * In OpenCV, the same cv::Mat is used to represent both * image and tensor data. Sometimes those are hardly distinguishable, @@ -46,28 +52,39 @@ enum class TraitAs: int using IEConfig = std::map; namespace detail { - struct ParamDesc { - std::string model_path; - std::string weights_path; - std::string device_id; +struct ParamDesc { + std::string model_path; + std::string weights_path; + std::string device_id; - // NB: Here order follows the `Net` API - std::vector input_names; - std::vector output_names; + std::vector input_names; + std::vector output_names; - using ConstInput = std::pair; - std::unordered_map const_inputs; + using ConstInput = std::pair; + std::unordered_map const_inputs; - // NB: nun_* may differ from topology's real input/output port numbers - // (e.g. topology's partial execution) - std::size_t num_in; // How many inputs are defined in the operation - std::size_t num_out; // How many outputs are defined in the operation + std::size_t num_in; + std::size_t num_out; - enum class Kind { Load, Import }; - Kind kind; - bool is_generic; - IEConfig config; - }; + enum class Kind {Load, Import}; + Kind kind; + bool is_generic; + IEConfig config; + + std::map> reshape_table; + std::unordered_set layer_names_to_reshape; + + // NB: Number of asyncrhonious infer requests + size_t nireq; + + // NB: An optional config to setup RemoteContext for IE + cv::util::any context_config; + + // NB: batch_size can't be equal to 1 by default, because some of models + // have 2D (Layout::NC) input and if the first dimension not equal to 1 + // net.setBatchSize(1) will overwrite it. + cv::optional batch_size; +}; } // namespace detail // FIXME: this is probably a shared (reusable) thing @@ -81,8 +98,21 @@ struct PortCfg { , std::tuple_size::value >; }; +/** + * @brief This structure provides functions + * that fill inference parameters for "OpenVINO Toolkit" model. + */ template class Params { public: + /** @brief Class constructor. + + Constructs Params based on model information and specifies default values for other + inference description parameters. Model is loaded and compiled using "OpenVINO Toolkit". + + @param model Path to topology IR (.xml file). + @param weights Path to weights (.bin file). + @param device target device to use. + */ Params(const std::string &model, const std::string &weights, const std::string &device) @@ -91,9 +121,21 @@ public: , std::tuple_size::value // num_out , detail::ParamDesc::Kind::Load , false + , {} + , {} + , {} + , 1u + , {} , {}} { }; + /** @overload + Use this constructor to work with pre-compiled network. + Model is imported from a pre-compiled blob. + + @param model Path to model. + @param device target device to use. + */ Params(const std::string &model, const std::string &device) : desc{ model, {}, device, {}, {}, {} @@ -101,25 +143,61 @@ public: , std::tuple_size::value // num_out , detail::ParamDesc::Kind::Import , false + , {} + , {} + , {} + , 1u + , {} , {}} { }; - Params& cfgInputLayers(const typename PortCfg::In &ll) { + /** @brief Specifies sequence of network input layers names for inference. + + The function is used to associate cv::gapi::infer<> inputs with the model inputs. + Number of names has to match the number of network inputs as defined in G_API_NET(). + In case a network has only single input layer, there is no need to specify name manually. + + @param layer_names std::array where N is the number of inputs + as defined in the @ref G_API_NET. Contains names of input layers. + @return reference to this parameter structure. + */ + Params& cfgInputLayers(const typename PortCfg::In &layer_names) { desc.input_names.clear(); - desc.input_names.reserve(ll.size()); - std::copy(ll.begin(), ll.end(), + desc.input_names.reserve(layer_names.size()); + std::copy(layer_names.begin(), layer_names.end(), std::back_inserter(desc.input_names)); return *this; } - Params& cfgOutputLayers(const typename PortCfg::Out &ll) { + /** @brief Specifies sequence of network output layers names for inference. + + The function is used to associate cv::gapi::infer<> outputs with the model outputs. + Number of names has to match the number of network outputs as defined in G_API_NET(). + In case a network has only single output layer, there is no need to specify name manually. + + @param layer_names std::array where N is the number of outputs + as defined in the @ref G_API_NET. Contains names of output layers. + @return reference to this parameter structure. + */ + Params& cfgOutputLayers(const typename PortCfg::Out &layer_names) { desc.output_names.clear(); - desc.output_names.reserve(ll.size()); - std::copy(ll.begin(), ll.end(), + desc.output_names.reserve(layer_names.size()); + std::copy(layer_names.begin(), layer_names.end(), std::back_inserter(desc.output_names)); return *this; } + /** @brief Specifies a constant input. + + The function is used to set a constant input. This input has to be + a preprocessed tensor if its type is TENSOR. Need to provide name of the + network layer which will receive provided data. + + @param layer_name Name of network layer. + @param data cv::Mat that contains data which will be associated with network layer. + @param hint Input type @sa cv::gapi::ie::TraitAs. + @return reference to this parameter structure. + */ Params& constInput(const std::string &layer_name, const cv::Mat &data, TraitAs hint = TraitAs::TENSOR) { @@ -127,13 +205,134 @@ public: return *this; } + /** @brief Specifies OpenVINO plugin configuration. + + The function is used to set configuration for OpenVINO plugin. Some parameters + can be different for each plugin. Please follow https://docs.openvinotoolkit.org/latest/index.html + to check information about specific plugin. + + @param cfg Map of pairs: (config parameter name, config parameter value). + @return reference to this parameter structure. + */ + Params& pluginConfig(const IEConfig& cfg) { + desc.config = cfg; + return *this; + } + + /** @overload + Function with a rvalue parameter. + + @param cfg rvalue map of pairs: (config parameter name, config parameter value). + @return reference to this parameter structure. + */ Params& pluginConfig(IEConfig&& cfg) { desc.config = std::move(cfg); return *this; } - Params& pluginConfig(const IEConfig& cfg) { - desc.config = cfg; + /** @brief Specifies configuration for RemoteContext in InferenceEngine. + + When RemoteContext is configured the backend imports the networks using the context. + It also expects cv::MediaFrames to be actually remote, to operate with blobs via the context. + + @param ctx_cfg cv::util::any value which holds InferenceEngine::ParamMap. + @return reference to this parameter structure. + */ + Params& cfgContextParams(const cv::util::any& ctx_cfg) { + desc.context_config = ctx_cfg; + return *this; + } + + /** @overload + Function with an rvalue parameter. + + @param ctx_cfg cv::util::any value which holds InferenceEngine::ParamMap. + @return reference to this parameter structure. + */ + Params& cfgContextParams(cv::util::any&& ctx_cfg) { + desc.context_config = std::move(ctx_cfg); + return *this; + } + + /** @brief Specifies number of asynchronous inference requests. + + @param nireq Number of inference asynchronous requests. + @return reference to this parameter structure. + */ + Params& cfgNumRequests(size_t nireq) { + GAPI_Assert(nireq > 0 && "Number of infer requests must be greater than zero!"); + desc.nireq = nireq; + return *this; + } + + /** @brief Specifies new input shapes for the network inputs. + + The function is used to specify new input shapes for the network inputs. + Follow https://docs.openvinotoolkit.org/latest/classInferenceEngine_1_1networkNetwork.html + for additional information. + + @param reshape_table Map of pairs: name of corresponding data and its dimension. + @return reference to this parameter structure. + */ + Params& cfgInputReshape(const std::map>& reshape_table) { + desc.reshape_table = reshape_table; + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::map>&& reshape_table) { + desc.reshape_table = std::move(reshape_table); + return *this; + } + + /** @overload + + @param layer_name Name of layer. + @param layer_dims New dimensions for this layer. + @return reference to this parameter structure. + */ + Params& cfgInputReshape(const std::string& layer_name, const std::vector& layer_dims) { + desc.reshape_table.emplace(layer_name, layer_dims); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::string&& layer_name, std::vector&& layer_dims) { + desc.reshape_table.emplace(layer_name, layer_dims); + return *this; + } + + /** @overload + + @param layer_names set of names of network layers that will be used for network reshape. + @return reference to this parameter structure. + */ + Params& cfgInputReshape(const std::unordered_set& layer_names) { + desc.layer_names_to_reshape = layer_names; + return *this; + } + + /** @overload + + @param layer_names rvalue set of the selected layers will be reshaped automatically + its input image size. + @return reference to this parameter structure. + */ + Params& cfgInputReshape(std::unordered_set&& layer_names) { + desc.layer_names_to_reshape = std::move(layer_names); + return *this; + } + + /** @brief Specifies the inference batch size. + + The function is used to specify inference batch size. + Follow https://docs.openvinotoolkit.org/latest/classInferenceEngine_1_1CNNNetwork.html#a8e9d19270a48aab50cb5b1c43eecb8e9 for additional information + + @param size batch size which will be used. + @return reference to this parameter structure. + */ + Params& cfgBatchSize(const size_t size) { + desc.batch_size = cv::util::make_optional(size); return *this; } @@ -147,29 +346,118 @@ protected: detail::ParamDesc desc; }; +/* +* @brief This structure provides functions for generic network type that +* fill inference parameters. +* @see struct Generic +*/ template<> class Params { public: + /** @brief Class constructor. + + Constructs Params based on model information and sets default values for other + inference description parameters. Model is loaded and compiled using OpenVINO Toolkit. + + @param tag string tag of the network for which these parameters are intended. + @param model path to topology IR (.xml file). + @param weights path to weights (.bin file). + @param device target device to use. + */ Params(const std::string &tag, const std::string &model, const std::string &weights, const std::string &device) - : desc{ model, weights, device, {}, {}, {}, 0u, 0u, detail::ParamDesc::Kind::Load, true, {}}, m_tag(tag) { + : desc{ model, weights, device, {}, {}, {}, 0u, 0u, + detail::ParamDesc::Kind::Load, true, {}, {}, {}, 1u, + {}, {}}, + m_tag(tag) { }; + /** @overload + + This constructor for pre-compiled networks. Model is imported from pre-compiled + blob. + + @param tag string tag of the network for which these parameters are intended. + @param model path to model. + @param device target device to use. + */ Params(const std::string &tag, const std::string &model, const std::string &device) - : desc{ model, {}, device, {}, {}, {}, 0u, 0u, detail::ParamDesc::Kind::Import, true, {}}, m_tag(tag) { + : desc{ model, {}, device, {}, {}, {}, 0u, 0u, + detail::ParamDesc::Kind::Import, true, {}, {}, {}, 1u, + {}, {}}, + m_tag(tag) { }; + /** @see ie::Params::pluginConfig. */ + Params& pluginConfig(const IEConfig& cfg) { + desc.config = cfg; + return *this; + } + + /** @overload */ Params& pluginConfig(IEConfig&& cfg) { desc.config = std::move(cfg); return *this; } - Params& pluginConfig(const IEConfig& cfg) { - desc.config = cfg; + /** @see ie::Params::constInput. */ + Params& constInput(const std::string &layer_name, + const cv::Mat &data, + TraitAs hint = TraitAs::TENSOR) { + desc.const_inputs[layer_name] = {data, hint}; + return *this; + } + + /** @see ie::Params::cfgNumRequests. */ + Params& cfgNumRequests(size_t nireq) { + GAPI_Assert(nireq > 0 && "Number of infer requests must be greater than zero!"); + desc.nireq = nireq; + return *this; + } + + /** @see ie::Params::cfgInputReshape */ + Params& cfgInputReshape(const std::map>&reshape_table) { + desc.reshape_table = reshape_table; + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::map> && reshape_table) { + desc.reshape_table = std::move(reshape_table); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::string && layer_name, std::vector && layer_dims) { + desc.reshape_table.emplace(layer_name, layer_dims); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(const std::string & layer_name, const std::vector&layer_dims) { + desc.reshape_table.emplace(layer_name, layer_dims); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(std::unordered_set && layer_names) { + desc.layer_names_to_reshape = std::move(layer_names); + return *this; + } + + /** @overload */ + Params& cfgInputReshape(const std::unordered_set&layer_names) { + desc.layer_names_to_reshape = layer_names; + return *this; + } + + /** @see ie::Params::cfgBatchSize */ + Params& cfgBatchSize(const size_t size) { + desc.batch_size = cv::util::make_optional(size); return *this; } diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/onnx.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/onnx.hpp index d61ceb3dca9..bb5ef6c59e1 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/onnx.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/onnx.hpp @@ -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) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation #ifndef OPENCV_GAPI_INFER_ONNX_HPP #define OPENCV_GAPI_INFER_ONNX_HPP @@ -20,6 +20,10 @@ namespace cv { namespace gapi { + +/** + * @brief This namespace contains G-API ONNX Runtime backend functions, structures, and symbols. + */ namespace onnx { GAPI_EXPORTS cv::gapi::GBackend backend(); @@ -34,30 +38,35 @@ enum class TraitAs: int { using PostProc = std::function &, std::unordered_map &)>; - namespace detail { +/** +* @brief This structure contains description of inference parameters +* which is specific to ONNX models. +*/ struct ParamDesc { - std::string model_path; + std::string model_path; //!< Path to model. // NB: nun_* may differ from topology's real input/output port numbers // (e.g. topology's partial execution) - std::size_t num_in; // How many inputs are defined in the operation - std::size_t num_out; // How many outputs are defined in the operation + std::size_t num_in; //!< How many inputs are defined in the operation + std::size_t num_out; //!< How many outputs are defined in the operation // NB: Here order follows the `Net` API - std::vector input_names; - std::vector output_names; + std::vector input_names; //!< Names of input network layers. + std::vector output_names; //!< Names of output network layers. using ConstInput = std::pair; - std::unordered_map const_inputs; + std::unordered_map const_inputs; //!< Map with pair of name of network layer and ConstInput which will be associated with this. - std::vector mean; - std::vector stdev; + std::vector mean; //!< Mean values for preprocessing. + std::vector stdev; //!< Standard deviation values for preprocessing. - std::vector out_metas; - PostProc custom_post_proc; + std::vector out_metas; //!< Out meta information about your output (type, dimension). + PostProc custom_post_proc; //!< Post processing function. - std::vector normalize; + std::vector normalize; //!< Vector of bool values that enabled or disabled normalize of input data. + + std::vector names_to_remap; //!< Names of output layers that will be processed in PostProc function. }; } // namespace detail @@ -77,30 +86,71 @@ struct PortCfg { , std::tuple_size::value >; }; +/** + * Contains description of inference parameters and kit of functions that + * fill this parameters. + */ template class Params { public: + /** @brief Class constructor. + + Constructs Params based on model information and sets default values for other + inference description parameters. + + @param model Path to model (.onnx file). + */ Params(const std::string &model) { desc.model_path = model; desc.num_in = std::tuple_size::value; desc.num_out = std::tuple_size::value; }; - // BEGIN(G-API's network parametrization API) - GBackend backend() const { return cv::gapi::onnx::backend(); } - std::string tag() const { return Net::tag(); } - cv::util::any params() const { return { desc }; } - // END(G-API's network parametrization API) + /** @brief Specifies sequence of network input layers names for inference. - Params& cfgInputLayers(const typename PortCfg::In &ll) { - desc.input_names.assign(ll.begin(), ll.end()); + The function is used to associate data of graph inputs with input layers of + network topology. Number of names has to match the number of network inputs. If a network + has only one input layer, there is no need to call it as the layer is + associated with input automatically but this doesn't prevent you from + doing it yourself. Count of names has to match to number of network inputs. + + @param layer_names std::array where N is the number of inputs + as defined in the @ref G_API_NET. Contains names of input layers. + @return the reference on modified object. + */ + Params& cfgInputLayers(const typename PortCfg::In &layer_names) { + desc.input_names.assign(layer_names.begin(), layer_names.end()); return *this; } - Params& cfgOutputLayers(const typename PortCfg::Out &ll) { - desc.output_names.assign(ll.begin(), ll.end()); + /** @brief Specifies sequence of output layers names for inference. + + The function is used to associate data of graph outputs with output layers of + network topology. If a network has only one output layer, there is no need to call it + as the layer is associated with ouput automatically but this doesn't prevent + you from doing it yourself. Count of names has to match to number of network + outputs or you can set your own output but for this case you have to + additionally use @ref cfgPostProc function. + + @param layer_names std::array where N is the number of outputs + as defined in the @ref G_API_NET. Contains names of output layers. + @return the reference on modified object. + */ + Params& cfgOutputLayers(const typename PortCfg::Out &layer_names) { + desc.output_names.assign(layer_names.begin(), layer_names.end()); return *this; } + /** @brief Sets a constant input. + + The function is used to set constant input. This input has to be + a prepared tensor since preprocessing is disabled for this case. You should + provide name of network layer which will receive provided data. + + @param layer_name Name of network layer. + @param data cv::Mat that contains data which will be associated with network layer. + @param hint Type of input (TENSOR). + @return the reference on modified object. + */ Params& constInput(const std::string &layer_name, const cv::Mat &data, TraitAs hint = TraitAs::TENSOR) { @@ -108,6 +158,17 @@ public: return *this; } + /** @brief Specifies mean value and standard deviation for preprocessing. + + The function is used to set mean value and standard deviation for preprocessing + of input data. + + @param m std::array where N is the number of inputs + as defined in the @ref G_API_NET. Contains mean values. + @param s std::array where N is the number of inputs + as defined in the @ref G_API_NET. Contains standard deviation values. + @return the reference on modified object. + */ Params& cfgMeanStd(const typename PortCfg::NormCoefs &m, const typename PortCfg::NormCoefs &s) { desc.mean.assign(m.begin(), m.end()); @@ -115,18 +176,103 @@ public: return *this; } - Params& cfgPostProc(const std::vector &outs, - const PostProc &pp) { - desc.out_metas = outs; - desc.custom_post_proc = pp; + /** @brief Configures graph output and provides the post processing function from user. + + The function is used when you work with networks with dynamic outputs. + Since we can't know dimensions of inference result needs provide them for + construction of graph output. This dimensions can differ from inference result. + So you have to provide @ref PostProc function that gets information from inference + result and fill output which is constructed by dimensions from out_metas. + + @param out_metas Out meta information about your output (type, dimension). + @param remap_function Post processing function, which has two parameters. First is onnx + result, second is graph output. Both parameters is std::map that contain pair of + layer's name and cv::Mat. + @return the reference on modified object. + */ + Params& cfgPostProc(const std::vector &out_metas, + const PostProc &remap_function) { + desc.out_metas = out_metas; + desc.custom_post_proc = remap_function; return *this; } - Params& cfgNormalize(const typename PortCfg::Normalize &n) { - desc.normalize.assign(n.begin(), n.end()); + /** @overload + Function with a rvalue parameters. + + @param out_metas rvalue out meta information about your output (type, dimension). + @param remap_function rvalue post processing function, which has two parameters. First is onnx + result, second is graph output. Both parameters is std::map that contain pair of + layer's name and cv::Mat. + @return the reference on modified object. + */ + Params& cfgPostProc(std::vector &&out_metas, + PostProc &&remap_function) { + desc.out_metas = std::move(out_metas); + desc.custom_post_proc = std::move(remap_function); return *this; } + /** @overload + The function has additional parameter names_to_remap. This parameter provides + information about output layers which will be used for inference and post + processing function. + + @param out_metas Out meta information. + @param remap_function Post processing function. + @param names_to_remap Names of output layers. network's inference will + be done on these layers. Inference's result will be processed in post processing + function using these names. + @return the reference on modified object. + */ + Params& cfgPostProc(const std::vector &out_metas, + const PostProc &remap_function, + const std::vector &names_to_remap) { + desc.out_metas = out_metas; + desc.custom_post_proc = remap_function; + desc.names_to_remap = names_to_remap; + return *this; + } + + /** @overload + Function with a rvalue parameters and additional parameter names_to_remap. + + @param out_metas rvalue out meta information. + @param remap_function rvalue post processing function. + @param names_to_remap rvalue names of output layers. network's inference will + be done on these layers. Inference's result will be processed in post processing + function using these names. + @return the reference on modified object. + */ + Params& cfgPostProc(std::vector &&out_metas, + PostProc &&remap_function, + std::vector &&names_to_remap) { + desc.out_metas = std::move(out_metas); + desc.custom_post_proc = std::move(remap_function); + desc.names_to_remap = std::move(names_to_remap); + return *this; + } + + /** @brief Specifies normalize parameter for preprocessing. + + The function is used to set normalize parameter for preprocessing of input data. + + @param normalizations std::array where N is the number of inputs + as defined in the @ref G_API_NET. Сontains bool values that enabled or disabled + normalize of input data. + @return the reference on modified object. + */ + Params& cfgNormalize(const typename PortCfg::Normalize &normalizations) { + desc.normalize.assign(normalizations.begin(), normalizations.end()); + return *this; + } + + // BEGIN(G-API's network parametrization API) + GBackend backend() const { return cv::gapi::onnx::backend(); } + std::string tag() const { return Net::tag(); } + cv::util::any params() const { return { desc }; } + // END(G-API's network parametrization API) + protected: detail::ParamDesc desc; }; diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/parsers.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/parsers.hpp index 396d31bb023..c7308dd39f4 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/parsers.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/infer/parsers.hpp @@ -64,12 +64,13 @@ detection is smaller than confidence threshold, detection is rejected. given label will get to the output. @return a tuple with a vector of detected boxes and a vector of appropriate labels. */ -GAPI_EXPORTS std::tuple, GArray> parseSSD(const GMat& in, - const GOpaque& inSz, - const float confidenceThreshold = 0.5f, - const int filterLabel = -1); +GAPI_EXPORTS_W std::tuple, GArray> parseSSD(const GMat& in, + const GOpaque& inSz, + const float confidenceThreshold = 0.5f, + const int filterLabel = -1); + +/** @brief Parses output of SSD network. -/** @overload Extracts detection information (box, confidence) from SSD output and filters it by given confidence and by going out of bounds. @@ -85,11 +86,11 @@ 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 parseSSD(const GMat& in, - const GOpaque& inSz, - const float confidenceThreshold = 0.5f, - const bool alignmentToSquare = false, - const bool filterOutOfBounds = false); +GAPI_EXPORTS_W GArray parseSSD(const GMat& in, + const GOpaque& inSz, + const float confidenceThreshold, + const bool alignmentToSquare, + const bool filterOutOfBounds); /** @brief Parses output of Yolo network. @@ -112,12 +113,12 @@ If 1.f, nms is not performed and no boxes are rejected. documentation. @return a tuple with a vector of detected boxes and a vector of appropriate labels. */ -GAPI_EXPORTS std::tuple, GArray> parseYolo(const GMat& in, - const GOpaque& inSz, - const float confidenceThreshold = 0.5f, - const float nmsThreshold = 0.5f, - const std::vector& anchors - = nn::parsers::GParseYolo::defaultAnchors()); +GAPI_EXPORTS_W std::tuple, GArray> parseYolo(const GMat& in, + const GOpaque& inSz, + const float confidenceThreshold = 0.5f, + const float nmsThreshold = 0.5f, + const std::vector& anchors + = nn::parsers::GParseYolo::defaultAnchors()); } // namespace gapi } // namespace cv diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/media.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/media.hpp index f27cb809139..19aaef3fd1a 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/media.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/media.hpp @@ -13,26 +13,142 @@ #include // forward<>() #include +#include + +// Forward declaration +namespace cv { +namespace gapi { +namespace s11n { +struct IOStream; +struct IIStream; +} // namespace s11n +} // namespace gapi +} // namespace cv namespace cv { +/** \addtogroup gapi_data_structures + * @{ + * + * @brief Extra G-API data structures used to pass input/output data + * to the graph for processing. + */ +/** + * @brief cv::MediaFrame class represents an image/media frame + * obtained from an external source. + * + * cv::MediaFrame represents image data as specified in + * cv::MediaFormat. cv::MediaFrame is designed to be a thin wrapper over some + * external memory of buffer; the class itself provides an uniform + * interface over such types of memory. cv::MediaFrame wraps data from + * a camera driver or from a media codec and provides an abstraction + * layer over this memory to G-API. MediaFrame defines a compact interface + * to access and manage the underlying data; the implementation is + * fully defined by the associated Adapter (which is usually + * user-defined). + * + * @sa cv::RMat + */ class GAPI_EXPORTS MediaFrame { public: - enum class Access { R, W }; + /// This enum defines different types of cv::MediaFrame provided + /// access to the underlying data. Note that different flags can't + /// be combined in this version. + enum class Access { + R, ///< Access data for reading + W, ///< Access data for writing + }; class IAdapter; class View; using AdapterPtr = std::unique_ptr; + /** + * @brief Constructs an empty MediaFrame + * + * The constructed object has no any data associated with it. + */ MediaFrame(); - explicit MediaFrame(AdapterPtr &&); - template static cv::MediaFrame Create(Args&&...); - View access(Access) const; + /** + * @brief Constructs a MediaFrame with the given + * Adapter. MediaFrame takes ownership over the passed adapter. + * + * @param p an unique pointer to instance of IAdapter derived class. + */ + explicit MediaFrame(AdapterPtr &&p); + + /** + * @overload + * @brief Constructs a MediaFrame with the given parameters for + * the Adapter. The adapter of type `T` is costructed on the fly. + * + * @param args list of arguments to construct an adapter of type + * `T`. + */ + template static cv::MediaFrame Create(Args&&... args); + + /** + * @brief Obtain access to the underlying data with the given + * mode. + * + * Depending on the associated Adapter and the data wrapped, this + * method may be cheap (e.g., the underlying memory is local) or + * costly (if the underlying memory is external or device + * memory). + * + * @param mode an access mode flag + * @return a MediaFrame::View object. The views should be handled + * carefully, refer to the MediaFrame::View documentation for details. + */ + View access(Access mode) const; + + /** + * @brief Returns a media frame descriptor -- the information + * about the media format, dimensions, etc. + * @return a cv::GFrameDesc + */ cv::GFrameDesc desc() const; + // FIXME: design a better solution + // Should be used only if the actual adapter provides implementation + /// @private -- exclude from the OpenCV documentation for now. + cv::util::any blobParams() const; + + /** + * @brief Casts and returns the associated MediaFrame adapter to + * the particular adapter type `T`, returns nullptr if the type is + * different. + * + * This method may be useful if the adapter type is known by the + * caller, and some lower level access to the memory is required. + * Depending on the memory type, it may be more efficient than + * access(). + * + * @return a pointer to the adapter object, nullptr if the adapter + * type is different. + */ + template T* get() const { + static_assert(std::is_base_of::value, + "T is not derived from cv::MediaFrame::IAdapter!"); + auto* adapter = getAdapter(); + GAPI_Assert(adapter != nullptr); + return dynamic_cast(adapter); + } + + /** + * @brief Serialize MediaFrame's data to a byte array. + * + * @note The actual logic is implemented by frame's adapter class. + * Does nothing by default. + * + * @param os Bytestream to store serialized MediaFrame data in. + */ + void serialize(cv::gapi::s11n::IOStream& os) const; + private: struct Priv; std::shared_ptr m; + IAdapter* getAdapter() const; }; template @@ -41,6 +157,43 @@ inline cv::MediaFrame cv::MediaFrame::Create(Args&&... args) { return cv::MediaFrame(std::move(ptr)); } +/** + * @brief Provides access to the MediaFrame's underlying data. + * + * This object contains the necessary information to access the pixel + * data of the associated MediaFrame: arrays of pointers and strides + * (distance between every plane row, in bytes) for every image + * plane, as defined in cv::MediaFormat. + * There may be up to four image planes in MediaFrame. + * + * Depending on the MediaFrame::Access flag passed in + * MediaFrame::access(), a MediaFrame::View may be read- or + * write-only. + * + * Depending on the MediaFrame::IAdapter implementation associated + * with the parent MediaFrame, writing to memory with + * MediaFrame::Access::R flag may have no effect or lead to + * undefined behavior. Same applies to reading the memory with + * MediaFrame::Access::W flag -- again, depending on the IAdapter + * implementation, the host-side buffer the view provides access to + * may have no current data stored in (so in-place editing of the + * buffer contents may not be possible). + * + * MediaFrame::View objects must be handled carefully, as an external + * resource associated with MediaFrame may be locked for the time the + * MediaFrame::View object exists. Obtaining MediaFrame::View should + * be seen as "map" and destroying it as "unmap" in the "map/unmap" + * idiom (applicable to OpenCL, device memory, remote + * memory). + * + * When a MediaFrame buffer is accessed for writing, and the memory + * under MediaFrame::View::Ptrs is altered, the data synchronization + * of a host-side and device/remote buffer is not guaranteed until the + * MediaFrame::View is destroyed. In other words, the real data on the + * device or in a remote target may be updated at the MediaFrame::View + * destruction only -- but it depends on the associated + * MediaFrame::IAdapter implementation. + */ class GAPI_EXPORTS MediaFrame::View final { public: static constexpr const size_t MAX_PLANES = 4; @@ -48,25 +201,56 @@ public: using Strides = std::array; // in bytes using Callback = std::function; + /// @private View(Ptrs&& ptrs, Strides&& strs, Callback &&cb = [](){}); + + /// @private View(const View&) = delete; + + /// @private View(View&&) = default; + + /// @private View& operator = (const View&) = delete; + ~View(); - Ptrs ptr; - Strides stride; + Ptrs ptr; ///< Array of image plane pointers + Strides stride; ///< Array of image plane strides, in bytes. private: Callback m_cb; }; +/** + * @brief An interface class for MediaFrame data adapters. + * + * Implement this interface to wrap media data in the MediaFrame. It + * makes sense to implement this class if there is a custom + * cv::gapi::wip::IStreamSource defined -- in this case, a stream + * source can produce MediaFrame objects with this adapter and the + * media data may be passed to graph without any copy. For example, a + * GStreamer-based stream source can implement an adapter over + * `GstBuffer` and G-API will transparently use it in the graph. + */ class GAPI_EXPORTS MediaFrame::IAdapter { public: virtual ~IAdapter() = 0; virtual cv::GFrameDesc meta() const = 0; virtual MediaFrame::View access(MediaFrame::Access) = 0; + // FIXME: design a better solution + // The default implementation does nothing + virtual cv::util::any blobParams() const; + virtual void serialize(cv::gapi::s11n::IOStream&) { + GAPI_Assert(false && "Generic serialize method of MediaFrame::IAdapter does nothing by default. " + "Please, implement it in derived class to properly serialize the object."); + } + virtual void deserialize(cv::gapi::s11n::IIStream&) { + GAPI_Assert(false && "Generic deserialize method of MediaFrame::IAdapter does nothing by default. " + "Please, implement it in derived class to properly deserialize the object."); + } }; +/** @} */ } //namespace cv diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/ocl/goclkernel.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/ocl/goclkernel.hpp index 8ec388d588b..6a2f1df769b 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/ocl/goclkernel.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/ocl/goclkernel.hpp @@ -29,6 +29,9 @@ namespace gimpl namespace gapi { +/** + * @brief This namespace contains G-API OpenCL backend functions, structures, and symbols. + */ namespace ocl { /** diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/opencv_includes.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/opencv_includes.hpp index 08b2d6ed02d..25a67d6da60 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/opencv_includes.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/opencv_includes.hpp @@ -14,6 +14,12 @@ # include # include # include +#define GAPI_OWN_TYPES_LIST cv::gapi::own::Rect, \ + cv::gapi::own::Size, \ + cv::gapi::own::Point, \ + cv::gapi::own::Point2f, \ + cv::gapi::own::Scalar, \ + cv::gapi::own::Mat #else // Without OpenCV # include # include // cv::gapi::own::Rect/Size/Point @@ -28,6 +34,8 @@ namespace cv { using Scalar = gapi::own::Scalar; using Mat = gapi::own::Mat; } // namespace cv +#define GAPI_OWN_TYPES_LIST cv::gapi::own::VoidType + #endif // !defined(GAPI_STANDALONE) #endif // OPENCV_GAPI_OPENCV_INCLUDES_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/cvdefs.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/cvdefs.hpp index b9ab89cf767..d3bef98e980 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/cvdefs.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/cvdefs.hpp @@ -20,11 +20,12 @@ typedef char schar; typedef unsigned short ushort; +#define CV_USRTYPE1 (void)"CV_USRTYPE1 support has been dropped in OpenCV 4.0" + #define CV_CN_MAX 512 #define CV_CN_SHIFT 3 #define CV_DEPTH_MAX (1 << CV_CN_SHIFT) - #define CV_8U 0 #define CV_8S 1 #define CV_16U 2 @@ -33,7 +34,6 @@ typedef unsigned short ushort; #define CV_32F 5 #define CV_64F 6 #define CV_16F 7 -#define CV_USRTYPE1 8 #define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1) #define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK) @@ -71,7 +71,6 @@ typedef unsigned short ushort; #define CV_32SC4 CV_MAKETYPE(CV_32S,4) #define CV_32SC(n) CV_MAKETYPE(CV_32S,(n)) - #define CV_16FC1 CV_MAKETYPE(CV_16F,1) #define CV_16FC2 CV_MAKETYPE(CV_16F,2) #define CV_16FC3 CV_MAKETYPE(CV_16F,3) @@ -92,6 +91,16 @@ typedef unsigned short ushort; // cvdef.h: +#ifndef CV_ALWAYS_INLINE +# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# define CV_ALWAYS_INLINE inline __attribute__((always_inline)) +# elif defined(_MSC_VER) +# define CV_ALWAYS_INLINE __forceinline +# else +# define CV_ALWAYS_INLINE inline +# endif +#endif + #define CV_MAT_CN_MASK ((CV_CN_MAX - 1) << CV_CN_SHIFT) #define CV_MAT_CN(flags) ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1) #define CV_MAT_TYPE_MASK (CV_DEPTH_MAX*CV_CN_MAX - 1) diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/exports.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/exports.hpp index da42a3238cd..c36f4003d0f 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/exports.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/exports.hpp @@ -12,10 +12,14 @@ # include # define GAPI_EXPORTS CV_EXPORTS /* special informative macros for wrapper generators */ +# define GAPI_PROP CV_PROP +# define GAPI_PROP_RW CV_PROP_RW # define GAPI_WRAP CV_WRAP # define GAPI_EXPORTS_W_SIMPLE CV_EXPORTS_W_SIMPLE # define GAPI_EXPORTS_W CV_EXPORTS_W # else +# define GAPI_PROP +# define GAPI_PROP_RW # define GAPI_WRAP # define GAPI_EXPORTS # define GAPI_EXPORTS_W_SIMPLE diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/saturate.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/saturate.hpp index 5b232479ea5..74eaecf57e6 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/saturate.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/saturate.hpp @@ -11,9 +11,9 @@ #include #include -#include #include +#include namespace cv { namespace gapi { namespace own { //----------------------------- @@ -22,16 +22,12 @@ namespace cv { namespace gapi { namespace own { // //----------------------------- -template -static inline DST saturate(SRC x) +template::value && + std::is_integral::value && + std::is_integral::value> > +static CV_ALWAYS_INLINE DST saturate(SRC x) { - // only integral types please! - GAPI_DbgAssert(std::is_integral::value && - std::is_integral::value); - - if (std::is_same::value) - return static_cast(x); - if (sizeof(DST) > sizeof(SRC)) return static_cast(x); @@ -44,38 +40,35 @@ static inline DST saturate(SRC x) std::numeric_limits::max(): static_cast(x); } +template +static CV_ALWAYS_INLINE T saturate(T x) +{ + return x; +} +template::value, bool> = true > +static CV_ALWAYS_INLINE DST saturate(SRC x, R) +{ + return static_cast(x); +} +template::value && + std::is_integral::value , bool> = true > +static CV_ALWAYS_INLINE DST saturate(SRC x, R) +{ + return saturate(x); +} // Note, that OpenCV rounds differently: // - like std::round() for add, subtract // - like std::rint() for multiply, divide -template -static inline DST saturate(SRC x, R round) +template::value && + std::is_floating_point::value, bool> = true > +static CV_ALWAYS_INLINE DST saturate(SRC x, R round) { - if (std::is_floating_point::value) - { - return static_cast(x); - } - else if (std::is_integral::value) - { - GAPI_DbgAssert(std::is_integral::value && - std::is_integral::value); - return saturate(x); - } - else - { - GAPI_DbgAssert(std::is_integral::value && - std::is_floating_point::value); -#ifdef _WIN32 -// Suppress warning about converting x to floating-point -// Note that x is already floating-point at this point -#pragma warning(disable: 4244) -#endif - int ix = static_cast(round(x)); -#ifdef _WIN32 -#pragma warning(default: 4244) -#endif - return saturate(ix); - } + int ix = static_cast(round(x)); + return saturate(ix); } // explicit suffix 'd' for double type diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/types.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/types.hpp index c77a62ca537..38143660bca 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/types.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/types.hpp @@ -15,6 +15,11 @@ namespace cv { namespace gapi { + +/** + * @brief This namespace contains G-API own data structures used in + * its standalone mode build. + */ namespace own { @@ -22,7 +27,7 @@ class Point { public: Point() = default; - Point(int _x, int _y) : x(_x), y(_y) {}; + Point(int _x, int _y) : x(_x), y(_y) {} int x = 0; int y = 0; @@ -32,7 +37,7 @@ class Point2f { public: Point2f() = default; - Point2f(float _x, float _y) : x(_x), y(_y) {}; + Point2f(float _x, float _y) : x(_x), y(_y) {} float x = 0.f; float y = 0.f; @@ -42,9 +47,9 @@ class Rect { public: Rect() = default; - Rect(int _x, int _y, int _width, int _height) : x(_x), y(_y), width(_width), height(_height) {}; + Rect(int _x, int _y, int _width, int _height) : x(_x), y(_y), width(_width), height(_height) {} #if !defined(GAPI_STANDALONE) - Rect(const cv::Rect& other) : x(other.x), y(other.y), width(other.width), height(other.height) {}; + Rect(const cv::Rect& other) : x(other.x), y(other.y), width(other.width), height(other.height) {} inline Rect& operator=(const cv::Rect& other) { x = other.x; @@ -99,9 +104,9 @@ class Size { public: Size() = default; - Size(int _width, int _height) : width(_width), height(_height) {}; + Size(int _width, int _height) : width(_width), height(_height) {} #if !defined(GAPI_STANDALONE) - Size(const cv::Size& other) : width(other.width), height(other.height) {}; + Size(const cv::Size& other) : width(other.width), height(other.height) {} inline Size& operator=(const cv::Size& rhs) { width = rhs.width; @@ -138,6 +143,7 @@ inline std::ostream& operator<<(std::ostream& o, const Size& s) return o; } +struct VoidType {}; } // namespace own } // namespace gapi } // namespace cv diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/plaidml/gplaidmlkernel.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/plaidml/gplaidmlkernel.hpp index 7ce00cfa359..e22ecc7211f 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/plaidml/gplaidmlkernel.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/plaidml/gplaidmlkernel.hpp @@ -59,7 +59,7 @@ public: using F = std::function; GPlaidMLKernel() = default; - explicit GPlaidMLKernel(const F& f) : m_f(f) {}; + explicit GPlaidMLKernel(const F& f) : m_f(f) {} void apply(GPlaidMLContext &ctx) const { diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/plaidml/plaidml.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/plaidml/plaidml.hpp index bd12d258328..3207a8cb2e4 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/plaidml/plaidml.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/plaidml/plaidml.hpp @@ -15,6 +15,11 @@ namespace cv { namespace gapi { + +/** + * @brief This namespace contains G-API PlaidML backend functions, + * structures, and symbols. + */ namespace plaidml { diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/python/python.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/python/python.hpp new file mode 100644 index 00000000000..0e20bbbb595 --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/python/python.hpp @@ -0,0 +1,67 @@ +// 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) 2021 Intel Corporation + + +#ifndef OPENCV_GAPI_PYTHON_API_HPP +#define OPENCV_GAPI_PYTHON_API_HPP + +#include // GKernelPackage +#include // GAPI_EXPORTS + +namespace cv { +namespace gapi { + +/** + * @brief This namespace contains G-API Python backend functions, + * structures, and symbols. + * + * This functionality is required to enable G-API custom operations + * and kernels when using G-API from Python, no need to use it in the + * C++ form. + */ +namespace python { + +GAPI_EXPORTS cv::gapi::GBackend backend(); + +struct GPythonContext +{ + const cv::GArgs &ins; + const cv::GMetaArgs &in_metas; + const cv::GTypesInfo &out_info; +}; + +using Impl = std::function; + +class GAPI_EXPORTS GPythonKernel +{ +public: + GPythonKernel() = default; + GPythonKernel(Impl run); + + cv::GRunArgs operator()(const GPythonContext& ctx); +private: + Impl m_run; +}; + +class GAPI_EXPORTS GPythonFunctor : public cv::gapi::GFunctor +{ +public: + using Meta = cv::GKernel::M; + + GPythonFunctor(const char* id, const Meta &meta, const Impl& impl); + + GKernelImpl impl() const override; + gapi::GBackend backend() const override; + +private: + GKernelImpl impl_; +}; + +} // namespace python +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_PYTHON_API_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render.hpp index a4df3042892..53754122241 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render.hpp @@ -81,9 +81,9 @@ using GMatDesc2 = std::tuple; @param prims vector of drawing primitivies @param args graph compile time parameters */ -void GAPI_EXPORTS render(cv::Mat& bgr, - const Prims& prims, - cv::GCompileArgs&& args = {}); +void GAPI_EXPORTS_W render(cv::Mat& bgr, + const Prims& prims, + cv::GCompileArgs&& args = {}); /** @brief The function renders on two NV12 planes passed drawing primitivies @@ -92,11 +92,22 @@ void GAPI_EXPORTS render(cv::Mat& bgr, @param prims vector of drawing primitivies @param args graph compile time parameters */ -void GAPI_EXPORTS render(cv::Mat& y_plane, - cv::Mat& uv_plane, +void GAPI_EXPORTS_W render(cv::Mat& y_plane, + cv::Mat& uv_plane, + const Prims& prims, + cv::GCompileArgs&& args = {}); + +/** @brief The function renders on the input media frame passed drawing primitivies + +@param frame input Media Frame : @ref cv::MediaFrame. +@param prims vector of drawing primitivies +@param args graph compile time parameters +*/ +void GAPI_EXPORTS render(cv::MediaFrame& frame, const Prims& prims, cv::GCompileArgs&& args = {}); + G_TYPED_KERNEL_M(GRenderNV12, )>, "org.opencv.render.nv12") { static GMatDesc2 outMeta(GMatDesc y_plane, GMatDesc uv_plane, GArrayDesc) @@ -113,6 +124,14 @@ G_TYPED_KERNEL(GRenderBGR, )>, "or } }; +G_TYPED_KERNEL(GRenderFrame, )>, "org.opencv.render.frame") +{ + static GFrameDesc outMeta(GFrameDesc desc, GArrayDesc) + { + return desc; + } +}; + /** @brief Renders on 3 channels input Output image must be 8-bit unsigned planar 3-channel image @@ -120,7 +139,7 @@ Output image must be 8-bit unsigned planar 3-channel image @param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3 @param prims draw primitives */ -GAPI_EXPORTS GMat render3ch(const GMat& src, const GArray& prims); +GAPI_EXPORTS_W GMat render3ch(const GMat& src, const GArray& prims); /** @brief Renders on two planes @@ -131,19 +150,34 @@ uv image must be 8-bit unsigned planar 2-channel image @ref CV_8UC2 @param uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2 @param prims draw primitives */ -GAPI_EXPORTS GMat2 renderNV12(const GMat& y, - const GMat& uv, - const GArray& prims); +GAPI_EXPORTS_W GMat2 renderNV12(const GMat& y, + const GMat& uv, + const GArray& prims); + +/** @brief Renders Media Frame + +Output media frame frame cv::MediaFrame + +@param m_frame input image: cv::MediaFrame @ref cv::MediaFrame +@param prims draw primitives +*/ +GAPI_EXPORTS GFrame renderFrame(const GFrame& m_frame, + const GArray& prims); + //! @} gapi_draw_api } // namespace draw } // namespace wip +/** + * @brief This namespace contains G-API CPU rendering backend functions, + * structures, and symbols. See @ref gapi_draw for details. + */ namespace render { namespace ocv { - GAPI_EXPORTS cv::gapi::GKernelPackage kernels(); + GAPI_EXPORTS_W cv::gapi::GKernelPackage kernels(); } // namespace ocv } // namespace render diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render_types.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render_types.hpp index ca403be361e..6d70e3a877d 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render_types.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/render/render_types.hpp @@ -41,7 +41,7 @@ struct freetype_font * * Parameters match cv::putText(). */ -struct Text +struct GAPI_EXPORTS_W_SIMPLE Text { /** * @brief Text constructor @@ -55,6 +55,7 @@ struct 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 */ + GAPI_WRAP Text(const std::string& text_, const cv::Point& org_, int ff_, @@ -68,17 +69,18 @@ struct Text { } + GAPI_WRAP 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 + GAPI_PROP_RW std::string text; //!< The text string to be drawn + GAPI_PROP_RW cv::Point org; //!< The bottom-left corner of the text string in the image + GAPI_PROP_RW int ff; //!< The font type, see #HersheyFonts + GAPI_PROP_RW double fs; //!< The font scale factor that is multiplied by the font-specific base size + GAPI_PROP_RW cv::Scalar color; //!< The text color + GAPI_PROP_RW int thick; //!< The thickness of the lines used to draw a text + GAPI_PROP_RW int lt; //!< The line type. See #LineTypes + GAPI_PROP_RW bool bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner /*@{*/ }; @@ -122,7 +124,7 @@ struct FText * * Parameters match cv::rectangle(). */ -struct Rect +struct GAPI_EXPORTS_W_SIMPLE Rect { /** * @brief Rect constructor @@ -142,14 +144,15 @@ struct Rect { } + GAPI_WRAP 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 + GAPI_PROP_RW cv::Rect rect; //!< Coordinates of the rectangle + GAPI_PROP_RW cv::Scalar color; //!< The rectangle color or brightness (grayscale image) + GAPI_PROP_RW 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 + GAPI_PROP_RW int lt; //!< The type of the line. See #LineTypes + GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinates /*@{*/ }; @@ -158,7 +161,7 @@ struct Rect * * Parameters match cv::circle(). */ -struct Circle +struct GAPI_EXPORTS_W_SIMPLE Circle { /** * @brief Circle constructor @@ -170,6 +173,7 @@ struct Circle * @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 */ + GAPI_WRAP Circle(const cv::Point& center_, int radius_, const cv::Scalar& color_, @@ -180,15 +184,16 @@ struct Circle { } + GAPI_WRAP 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 + GAPI_PROP_RW cv::Point center; //!< The center of the circle + GAPI_PROP_RW int radius; //!< The radius of the circle + GAPI_PROP_RW cv::Scalar color; //!< The color of the circle + GAPI_PROP_RW int thick; //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn + GAPI_PROP_RW int lt; //!< The Type of the circle boundary. See #LineTypes + GAPI_PROP_RW int shift; //!< The Number of fractional bits in the coordinates of the center and in the radius value /*@{*/ }; @@ -197,7 +202,7 @@ struct Circle * * Parameters match cv::line(). */ -struct Line +struct GAPI_EXPORTS_W_SIMPLE Line { /** * @brief Line constructor @@ -209,6 +214,7 @@ struct Line * @param lt_ The Type of the line. See #LineTypes * @param shift_ The number of fractional bits in the point coordinates */ + GAPI_WRAP Line(const cv::Point& pt1_, const cv::Point& pt2_, const cv::Scalar& color_, @@ -219,15 +225,16 @@ struct Line { } + GAPI_WRAP 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 + GAPI_PROP_RW cv::Point pt1; //!< The first point of the line segment + GAPI_PROP_RW cv::Point pt2; //!< The second point of the line segment + GAPI_PROP_RW cv::Scalar color; //!< The line color + GAPI_PROP_RW int thick; //!< The thickness of line + GAPI_PROP_RW int lt; //!< The Type of the line. See #LineTypes + GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinates /*@{*/ }; @@ -236,7 +243,7 @@ struct Line * * Mosaicing is a very basic method to obfuscate regions in the image. */ -struct Mosaic +struct GAPI_EXPORTS_W_SIMPLE Mosaic { /** * @brief Mosaic constructor @@ -252,12 +259,13 @@ struct Mosaic { } + GAPI_WRAP Mosaic() : cellSz(0), decim(0) {} /*@{*/ - cv::Rect mos; //!< Coordinates of the mosaic - int cellSz; //!< Cell size (same for X, Y) - int decim; //!< Decimation (0 stands for no decimation) + GAPI_PROP_RW cv::Rect mos; //!< Coordinates of the mosaic + GAPI_PROP_RW int cellSz; //!< Cell size (same for X, Y) + GAPI_PROP_RW int decim; //!< Decimation (0 stands for no decimation) /*@{*/ }; @@ -266,7 +274,7 @@ struct Mosaic * * Image is blended on a frame using the specified mask. */ -struct Image +struct GAPI_EXPORTS_W_SIMPLE Image { /** * @brief Mosaic constructor @@ -275,6 +283,7 @@ struct Image * @param img_ Image to draw * @param alpha_ Alpha channel for image to draw (same size and number of channels) */ + GAPI_WRAP Image(const cv::Point& org_, const cv::Mat& img_, const cv::Mat& alpha_) : @@ -282,19 +291,20 @@ struct Image { } + GAPI_WRAP 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) + GAPI_PROP_RW cv::Point org; //!< The bottom-left corner of the image + GAPI_PROP_RW cv::Mat img; //!< Image to draw + GAPI_PROP_RW 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 +struct GAPI_EXPORTS_W_SIMPLE Poly { /** * @brief Mosaic constructor @@ -305,6 +315,7 @@ struct Poly * @param lt_ The Type of the line. See #LineTypes * @param shift_ The number of fractional bits in the point coordinate */ + GAPI_WRAP Poly(const std::vector& points_, const cv::Scalar& color_, int thick_ = 1, @@ -314,14 +325,15 @@ struct Poly { } + GAPI_WRAP Poly() = default; /*@{*/ - std::vector 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 + GAPI_PROP_RW std::vector points; //!< Points to connect + GAPI_PROP_RW cv::Scalar color; //!< The line color + GAPI_PROP_RW int thick; //!< The thickness of line + GAPI_PROP_RW int lt; //!< The Type of the line. See #LineTypes + GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinate /*@{*/ }; @@ -336,7 +348,7 @@ using Prim = util::variant , Poly >; -using Prims = std::vector; +using Prims = std::vector; //! @} gapi_draw_prims } // namespace draw diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/rmat.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/rmat.hpp index f50bd08b650..38668d67a58 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/rmat.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/rmat.hpp @@ -14,8 +14,8 @@ namespace cv { namespace gapi { namespace s11n { - struct IOStream; - struct IIStream; +struct IOStream; +struct IIStream; } // namespace s11n } // namespace gapi } // namespace cv @@ -25,11 +25,11 @@ 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 device specific implementation is hidden in the RMat::IAdapter 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 +// - Implements own AdapterT class which is derived from RMat::IAdapter // - Wraps device memory into RMat via make_rmat utility function: // cv::RMat rmat = cv::make_rmat(args); // @@ -42,6 +42,9 @@ namespace cv { // performCalculations(in_view, out_view); // // data from out_view is transferred to the device when out_view is destroyed // } +/** \addtogroup gapi_data_structures + * @{ + */ class GAPI_EXPORTS RMat { public: @@ -98,23 +101,27 @@ public: }; enum class Access { R, W }; - class Adapter + class IAdapter + // Adapter class is going to be deleted and renamed as IAdapter { public: - virtual ~Adapter() = default; + virtual ~IAdapter() = 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) = 0; virtual void serialize(cv::gapi::s11n::IOStream&) { - GAPI_Assert(false && "Generic serialize method should never be called for RMat adapter"); + GAPI_Assert(false && "Generic serialize method of RMat::IAdapter does nothing by default. " + "Please, implement it in derived class to properly serialize the object."); } virtual void deserialize(cv::gapi::s11n::IIStream&) { - GAPI_Assert(false && "Generic deserialize method should never be called for RMat adapter"); + GAPI_Assert(false && "Generic deserialize method of RMat::IAdapter does nothing by default. " + "Please, implement it in derived class to properly deserialize the object."); } }; - using AdapterP = std::shared_ptr; + using Adapter = IAdapter; // Keep backward compatibility + using AdapterP = std::shared_ptr; RMat() = default; RMat(AdapterP&& a) : m_adapter(std::move(a)) {} @@ -131,7 +138,7 @@ public: // return nullptr if underlying type is different template T* get() const { - static_assert(std::is_base_of::value, "T is not derived from Adapter!"); + static_assert(std::is_base_of::value, "T is not derived from IAdapter!"); GAPI_Assert(m_adapter != nullptr); return dynamic_cast(m_adapter.get()); } @@ -146,6 +153,7 @@ private: template RMat make_rmat(Ts&&... args) { return { std::make_shared(std::forward(args)...) }; } +/** @} */ } //namespace cv diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n.hpp index 0e2c4c239b9..6863a5ecabb 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n.hpp @@ -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) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation #ifndef OPENCV_GAPI_S11N_HPP #define OPENCV_GAPI_S11N_HPP @@ -13,61 +13,145 @@ #include #include #include +#include +#include + +// FIXME: caused by deserialize_runarg +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER +#pragma warning(disable: 4702) +#endif namespace cv { namespace gapi { +/** +* \addtogroup gapi_serialization +* @{ +*/ + namespace detail { - GAPI_EXPORTS cv::GComputation getGraph(const std::vector &p); + GAPI_EXPORTS cv::GComputation getGraph(const std::vector &bytes); - GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector &p); + GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector &bytes); - GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector &p); + GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector &bytes); + + GAPI_EXPORTS std::vector getVectorOfStrings(const std::vector &bytes); template - cv::GCompileArgs getCompileArgs(const std::vector &p); + cv::GCompileArgs getCompileArgs(const std::vector &bytes); - template - cv::GRunArgs getRunArgsWithRMats(const std::vector &p); + template + cv::GRunArgs getRunArgsWithAdapters(const std::vector &bytes); } // namespace detail +/** @brief Serialize a graph represented by GComputation into an array of bytes. + * + * Check different overloads for more examples. + * @param c GComputation to serialize. + * @return serialized vector of bytes. + */ GAPI_EXPORTS std::vector serialize(const cv::GComputation &c); -//namespace{ +/** @overload + * @param ca GCompileArgs to serialize. + */ +GAPI_EXPORTS std::vector serialize(const cv::GCompileArgs& ca); + +/** @overload + * @param ma GMetaArgs to serialize. + */ +GAPI_EXPORTS std::vector serialize(const cv::GMetaArgs& ma); + +/** @overload + * @param ra GRunArgs to serialize. + */ +GAPI_EXPORTS std::vector serialize(const cv::GRunArgs& ra); + +/** @overload + * @param vs std::vector to serialize. + */ +GAPI_EXPORTS std::vector serialize(const std::vector& vs); + +/** + * @private + */ template static inline -T deserialize(const std::vector &p); - -//} //ananymous namespace - -GAPI_EXPORTS std::vector serialize(const cv::GCompileArgs&); -GAPI_EXPORTS std::vector serialize(const cv::GMetaArgs&); -GAPI_EXPORTS std::vector serialize(const cv::GRunArgs&); +T deserialize(const std::vector &bytes); +/** @brief Deserialize GComputation from a byte array. + * + * Check different overloads for more examples. + * @param bytes serialized vector of bytes. + * @return deserialized GComputation object. + */ template<> inline -cv::GComputation deserialize(const std::vector &p) { - return detail::getGraph(p); +cv::GComputation deserialize(const std::vector &bytes) { + return detail::getGraph(bytes); } +/** @brief Deserialize GMetaArgs from a byte array. + * + * Check different overloads for more examples. + * @param bytes serialized vector of bytes. + * @return deserialized GMetaArgs object. + */ template<> inline -cv::GMetaArgs deserialize(const std::vector &p) { - return detail::getMetaArgs(p); +cv::GMetaArgs deserialize(const std::vector &bytes) { + return detail::getMetaArgs(bytes); } +/** @brief Deserialize GRunArgs from a byte array. + * + * Check different overloads for more examples. + * @param bytes serialized vector of bytes. + * @return deserialized GRunArgs object. + */ template<> inline -cv::GRunArgs deserialize(const std::vector &p) { - return detail::getRunArgs(p); +cv::GRunArgs deserialize(const std::vector &bytes) { + return detail::getRunArgs(bytes); } +/** @brief Deserialize std::vector from a byte array. + * + * Check different overloads for more examples. + * @param bytes serialized vector of bytes. + * @return deserialized std::vector object. + */ +template<> inline +std::vector deserialize(const std::vector &bytes) { + return detail::getVectorOfStrings(bytes); +} + +/** + * @brief Deserialize GCompileArgs which types were specified in the template from a byte array. + * + * @note cv::gapi::s11n::detail::S11N template specialization must be provided to make a custom type + * in GCompileArgs deserializable. + * + * @param bytes vector of bytes to deserialize GCompileArgs object from. + * @return GCompileArgs object. + * @see GCompileArgs cv::gapi::s11n::detail::S11N + */ template inline typename std::enable_if::value, GCompileArgs>:: -type deserialize(const std::vector &p) { - return detail::getCompileArgs(p); +type deserialize(const std::vector &bytes) { + return detail::getCompileArgs(bytes); } -template inline +/** + * @brief Deserialize GRunArgs including RMat and MediaFrame objects if any from a byte array. + * + * Adapter types are specified in the template. + * @note To be used properly specified adapter types must overload their deserialize() method. + * @param bytes vector of bytes to deserialize GRunArgs object from. + * @return GRunArgs including RMat and MediaFrame objects if any. + * @see RMat MediaFrame + */ +template inline typename std::enable_if::value, GRunArgs>:: -type deserialize(const std::vector &p) { - return detail::getRunArgsWithRMats(p); +type deserialize(const std::vector &bytes) { + return detail::getRunArgsWithAdapters(bytes); } } // namespace gapi } // namespace cv @@ -75,6 +159,17 @@ type deserialize(const std::vector &p) { namespace cv { namespace gapi { namespace s11n { + +/** @brief This structure is an interface for serialization routines. + * + * It's main purpose is to provide multiple overloads for operator<<() + * with basic C++ in addition to OpenCV/G-API types. + * + * This sctructure can be inherited and further extended with additional types. + * + * For example, it is utilized in cv::gapi::s11n::detail::S11N as input parameter + * in serialize() method. + */ struct GAPI_EXPORTS IOStream { virtual ~IOStream() = default; // Define the native support for basic C++ types at the API level: @@ -91,6 +186,16 @@ struct GAPI_EXPORTS IOStream { virtual IOStream& operator<< (const std::string&) = 0; }; +/** @brief This structure is an interface for deserialization routines. + * + * It's main purpose is to provide multiple overloads for operator>>() + * with basic C++ in addition to OpenCV/G-API types. + * + * This structure can be inherited and further extended with additional types. + * + * For example, it is utilized in cv::gapi::s11n::detail::S11N as input parameter + * in deserialize() method. + */ struct GAPI_EXPORTS IIStream { virtual ~IIStream() = default; virtual IIStream& operator>> (bool &) = 0; @@ -108,7 +213,7 @@ struct GAPI_EXPORTS IIStream { }; namespace detail { -GAPI_EXPORTS std::unique_ptr getInStream(const std::vector &p); +GAPI_EXPORTS std::unique_ptr getInStream(const std::vector &bytes); } // namespace detail //////////////////////////////////////////////////////////////////////////////// @@ -138,24 +243,26 @@ GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::Mat &m); // FIXME: for GRunArgs serailization #if !defined(GAPI_STANDALONE) -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::UMat &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::UMat &); +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::UMat & um); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::UMat & um); #endif // !defined(GAPI_STANDALONE) GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::RMat &r); GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::RMat &r); -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::gapi::wip::IStreamSource::Ptr &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::gapi::wip::IStreamSource::Ptr &); +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::gapi::wip::IStreamSource::Ptr &issptr); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::gapi::wip::IStreamSource::Ptr &issptr); -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::VectorRef &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::VectorRef &); +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::VectorRef &vr); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::VectorRef &vr); -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::OpaqueRef &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::OpaqueRef &); +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::detail::OpaqueRef &opr); +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::detail::OpaqueRef &opr); -GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::MediaFrame &); -GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::MediaFrame &); +/// @private -- Exclude this function from OpenCV documentation +GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::MediaFrame &mf); +/// @private -- Exclude this function from OpenCV documentation +GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::MediaFrame &mf); // Generic STL types //////////////////////////////////////////////////////////////// template @@ -178,6 +285,7 @@ IIStream& operator>> (IIStream& is, std::map &m) { } return is; } + template IOStream& operator<< (IOStream& os, const std::unordered_map &m) { const uint32_t sz = static_cast(m.size()); @@ -198,6 +306,7 @@ IIStream& operator>> (IIStream& is, std::unordered_map &m) { } return is; } + template IOStream& operator<< (IOStream& os, const std::vector &ts) { const uint32_t sz = static_cast(ts.size()); @@ -225,16 +334,19 @@ template IOStream& put_v(IOStream&, const V&, std::size_t) { GAPI_Assert(false && "variant>>: requested index is invalid"); }; + template IOStream& put_v(IOStream& os, const V& v, std::size_t x) { return (x == 0u) ? os << cv::util::get(v) : put_v(os, v, x-1); } + template IIStream& get_v(IIStream&, V&, std::size_t, std::size_t) { GAPI_Assert(false && "variant<<: requested index is invalid"); } + template IIStream& get_v(IIStream& is, V& v, std::size_t i, std::size_t gi) { if (i == gi) { @@ -246,11 +358,13 @@ IIStream& get_v(IIStream& is, V& v, std::size_t i, std::size_t gi) { } } // namespace detail +//! @overload template IOStream& operator<< (IOStream& os, const cv::util::variant &v) { os << static_cast(v.index()); return detail::put_v, Ts...>(os, v, v.index()); } +//! @overload template IIStream& operator>> (IIStream& is, cv::util::variant &v) { int idx = -1; @@ -260,6 +374,7 @@ IIStream& operator>> (IIStream& is, cv::util::variant &v) { } // FIXME: consider a better solution +/// @private -- Exclude this function from OpenCV documentation template void getRunArgByIdx (IIStream& is, cv::util::variant &v, uint32_t idx) { is = detail::get_v, Ts...>(is, v, 0u, idx); @@ -290,16 +405,39 @@ static cv::util::optional exec(const std::string& tag, cv::gapi::s1 } }; -template struct deserialize_runarg; +template +struct deserialize_arg_with_adapter; -template +template +struct deserialize_arg_with_adapter { +static GRunArg exec(cv::gapi::s11n::IIStream& is) { + std::unique_ptr ptr(new TA); + ptr->deserialize(is); + return GRunArg { RA(std::move(ptr)) }; +} +}; + +template +struct deserialize_arg_with_adapter { +static GRunArg exec(cv::gapi::s11n::IIStream&) { + GAPI_Assert(false && "No suitable adapter class found during RMat/MediaFrame deserialization. " + "Please, make sure you've passed them in cv::gapi::deserialize() template"); + return GRunArg{}; +} +}; + +template struct deserialize_runarg { static GRunArg exec(cv::gapi::s11n::IIStream& is, uint32_t idx) { if (idx == GRunArg::index_of()) { - auto ptr = std::make_shared(); - ptr->deserialize(is); - return GRunArg { RMat(std::move(ptr)) }; - } else { // non-RMat arg - use default deserialization + // Type or void (if not found) + using TA = typename cv::util::find_adapter_impl::type; + return deserialize_arg_with_adapter::exec(is); + } else if (idx == GRunArg::index_of()) { + // Type or void (if not found) + using TA = typename cv::util::find_adapter_impl::type; + return deserialize_arg_with_adapter::exec(is); + } else { // not an adapter holding type runarg - use default deserialization GRunArg arg; getRunArgByIdx(is, arg, idx); return arg; @@ -342,9 +480,9 @@ cv::GCompileArgs getCompileArgs(const std::vector &sArgs) { return args; } -template -cv::GRunArgs getRunArgsWithRMats(const std::vector &p) { - std::unique_ptr pIs = cv::gapi::s11n::detail::getInStream(p); +template +cv::GRunArgs getRunArgsWithAdapters(const std::vector &bytes) { + std::unique_ptr pIs = cv::gapi::s11n::detail::getInStream(bytes); cv::gapi::s11n::IIStream& is = *pIs; cv::GRunArgs args; @@ -353,12 +491,14 @@ cv::GRunArgs getRunArgsWithRMats(const std::vector &p) { for (uint32_t i = 0; i < sz; ++i) { uint32_t idx = 0; is >> idx; - args.push_back(cv::gapi::detail::deserialize_runarg::exec(is, idx)); + args.push_back(cv::gapi::detail::deserialize_runarg::exec(is, idx)); } return args; } } // namespace detail +/** @} */ + } // namespace gapi } // namespace cv diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n/base.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n/base.hpp index d9335ee9f7c..6cea94156ee 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n/base.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/s11n/base.hpp @@ -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) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation #ifndef OPENCV_GAPI_S11N_BASE_HPP #define OPENCV_GAPI_S11N_BASE_HPP @@ -12,31 +12,65 @@ namespace cv { namespace gapi { + +/** + * @brief This namespace contains G-API serialization and + * deserialization functions and data structures. + */ namespace s11n { struct IOStream; struct IIStream; namespace detail { +//! @addtogroup gapi_serialization +//! @{ + struct NotImplemented { }; -// The default S11N for custom types is NotImplemented -// Don't! sublass from NotImplemented if you actually implement S11N. +/** @brief This structure allows to implement serialization routines for custom types. + * + * The default S11N for custom types is not implemented. + * + * @note When providing an overloaded implementation for S11N with your type + * don't inherit it from NotImplemented structure. + * + * @note There are lots of overloaded >> and << operators for basic and OpenCV/G-API types + * which can be utilized when serializing a custom type. + * + * Example of usage: + * @snippet samples/cpp/tutorial_code/gapi/doc_snippets/api_ref_snippets.cpp S11N usage + * + */ template struct S11N: public NotImplemented { + /** + * @brief This function allows user to serialize their custom type. + * + * @note The default overload throws an exception if called. User need to + * properly overload the function to use it. + */ static void serialize(IOStream &, const T &) { GAPI_Assert(false && "No serialization routine is provided!"); } + /** + * @brief This function allows user to deserialize their custom type. + * + * @note The default overload throws an exception if called. User need to + * properly overload the function to use it. + */ static T deserialize(IIStream &) { GAPI_Assert(false && "No deserialization routine is provided!"); } }; +/// @private -- Exclude this struct from OpenCV documentation template struct has_S11N_spec { static constexpr bool value = !std::is_base_of::type>>::value; }; +//! @} gapi_serialization } // namespace detail } // namespace s11n diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/stereo.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/stereo.hpp new file mode 100644 index 00000000000..dcf8f4d2601 --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/stereo.hpp @@ -0,0 +1,85 @@ +// 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 distereoibution and at http://opencv.org/license.html. +// +// Copyright (C) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STEREO_HPP +#define OPENCV_GAPI_STEREO_HPP + +#include +#include +#include + +namespace cv { +namespace gapi { + +/** + * The enum specified format of result that you get from @ref cv::gapi::stereo. + */ +enum class StereoOutputFormat { + DEPTH_FLOAT16, ///< Floating point 16 bit value, CV_16FC1. + ///< This identifier is deprecated, use DEPTH_16F instead. + DEPTH_FLOAT32, ///< Floating point 32 bit value, CV_32FC1 + ///< This identifier is deprecated, use DEPTH_16F instead. + DISPARITY_FIXED16_11_5, ///< 16 bit signed: first bit for sign, + ///< 10 bits for integer part, + ///< 5 bits for fractional part. + ///< This identifier is deprecated, + ///< use DISPARITY_16Q_10_5 instead. + DISPARITY_FIXED16_12_4, ///< 16 bit signed: first bit for sign, + ///< 11 bits for integer part, + ///< 4 bits for fractional part. + ///< This identifier is deprecated, + ///< use DISPARITY_16Q_11_4 instead. + DEPTH_16F = DEPTH_FLOAT16, ///< Same as DEPTH_FLOAT16 + DEPTH_32F = DEPTH_FLOAT32, ///< Same as DEPTH_FLOAT32 + DISPARITY_16Q_10_5 = DISPARITY_FIXED16_11_5, ///< Same as DISPARITY_FIXED16_11_5 + DISPARITY_16Q_11_4 = DISPARITY_FIXED16_12_4 ///< Same as DISPARITY_FIXED16_12_4 +}; + + +/** + * @brief This namespace contains G-API Operation Types for Stereo and + * related functionality. + */ +namespace calib3d { + +G_TYPED_KERNEL(GStereo, , "org.opencv.stereo") { + static GMatDesc outMeta(const GMatDesc &left, const GMatDesc &right, const StereoOutputFormat of) { + GAPI_Assert(left.chan == 1); + GAPI_Assert(left.depth == CV_8U); + + GAPI_Assert(right.chan == 1); + GAPI_Assert(right.depth == CV_8U); + + switch(of) { + case StereoOutputFormat::DEPTH_FLOAT16: + return left.withDepth(CV_16FC1); + case StereoOutputFormat::DEPTH_FLOAT32: + return left.withDepth(CV_32FC1); + case StereoOutputFormat::DISPARITY_FIXED16_11_5: + case StereoOutputFormat::DISPARITY_FIXED16_12_4: + return left.withDepth(CV_16SC1); + default: + GAPI_Assert(false && "Unknown output format!"); + } + } +}; + +} // namespace calib3d + +/** @brief Computes disparity/depth map for the specified stereo-pair. +The function computes disparity or depth map depending on passed StereoOutputFormat argument. + +@param left 8-bit single-channel left image of @ref CV_8UC1 type. +@param right 8-bit single-channel right image of @ref CV_8UC1 type. +@param of enum to specified output kind: depth or disparity and corresponding type +*/ +GAPI_EXPORTS GMat stereo(const GMat& left, + const GMat& right, + const StereoOutputFormat of = StereoOutputFormat::DEPTH_FLOAT32); +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STEREO_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/desync.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/desync.hpp index 86de279fe94..1ed6e24b49a 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/desync.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/desync.hpp @@ -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) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation #ifndef OPENCV_GAPI_GSTREAMING_DESYNC_HPP @@ -73,9 +73,10 @@ G desync(const G &g) { * which produces an array of cv::util::optional<> objects. * * @note This feature is highly experimental now and is currently - * limited to a single GMat argument only. + * limited to a single GMat/GFrame argument only. */ GAPI_EXPORTS GMat desync(const GMat &g); +GAPI_EXPORTS GFrame desync(const GFrame &f); } // namespace streaming } // namespace gapi diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/format.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/format.hpp index 2837f301d4d..f7c3bd457df 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/format.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/format.hpp @@ -20,6 +20,19 @@ G_API_OP(GBGR, , "org.opencv.streaming.BGR") static GMatDesc outMeta(const GFrameDesc& in) { return GMatDesc{CV_8U, 3, in.size}; } }; +G_API_OP(GY, , "org.opencv.streaming.Y") { + static GMatDesc outMeta(const GFrameDesc& frameDesc) { + return GMatDesc { CV_8U, 1, frameDesc.size , false }; + } +}; + +G_API_OP(GUV, , "org.opencv.streaming.UV") { + static GMatDesc outMeta(const GFrameDesc& frameDesc) { + return GMatDesc { CV_8U, 2, cv::Size(frameDesc.size.width / 2, frameDesc.size.height / 2), + false }; + } +}; + /** @brief Gets bgr plane from input frame @note Function textual ID is "org.opencv.streaming.BGR" @@ -29,6 +42,25 @@ G_API_OP(GBGR, , "org.opencv.streaming.BGR") */ GAPI_EXPORTS cv::GMat BGR(const cv::GFrame& in); +/** @brief Extracts Y plane from media frame. + +Output image is 8-bit 1-channel image of @ref CV_8UC1. + +@note Function textual ID is "org.opencv.streaming.Y" + +@param frame input media frame. +*/ +GAPI_EXPORTS GMat Y(const cv::GFrame& frame); + +/** @brief Extracts UV plane from media frame. + +Output image is 8-bit 2-channel image of @ref CV_8UC2. + +@note Function textual ID is "org.opencv.streaming.UV" + +@param frame input media frame. +*/ +GAPI_EXPORTS GMat UV(const cv::GFrame& frame); } // namespace streaming //! @addtogroup gapi_transform @@ -42,7 +74,7 @@ e.g when graph's input needs to be passed directly to output, like in Streaming @param in Input image @return Copy of the input */ -GAPI_EXPORTS GMat copy(const GMat& in); +GAPI_EXPORTS_W GMat copy(const GMat& in); /** @brief Makes a copy of the input frame. Note that this copy may be not real (no actual data copied). Use this function to maintain graph contracts, diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamerpipeline.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamerpipeline.hpp new file mode 100644 index 00000000000..83afc993938 --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamerpipeline.hpp @@ -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) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERPIPELINE_HPP +#define OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERPIPELINE_HPP + +#include +#include + +#include +#include +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace gst { + +class GAPI_EXPORTS GStreamerPipeline +{ +public: + class Priv; + + explicit GStreamerPipeline(const std::string& pipeline); + IStreamSource::Ptr getStreamingSource(const std::string& appsinkName, + const GStreamerSource::OutputType outputType = + GStreamerSource::OutputType::MAT); + virtual ~GStreamerPipeline(); + +protected: + explicit GStreamerPipeline(std::unique_ptr priv); + + std::unique_ptr m_priv; +}; + +} // namespace gst + +using GStreamerPipeline = gst::GStreamerPipeline; + +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERPIPELINE_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp new file mode 100644 index 00000000000..b81bad31b8b --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/gstreamer/gstreamersource.hpp @@ -0,0 +1,89 @@ +// 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) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERSOURCE_HPP +#define OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERSOURCE_HPP + +#include +#include + +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace gst { + +/** + * @brief OpenCV's GStreamer streaming source. + * Streams cv::Mat-s/cv::MediaFrame from passed GStreamer pipeline. + * + * This class implements IStreamSource interface. + * + * To create GStreamerSource instance you need to pass 'pipeline' and, optionally, 'outputType' + * arguments into constructor. + * 'pipeline' should represent GStreamer pipeline in form of textual description. + * Almost any custom pipeline is supported which can be successfully ran via gst-launch. + * The only two limitations are: + * - there should be __one__ appsink element in the pipeline to pass data to OpenCV app. + * Pipeline can actually contain many sink elements, but it must have one and only one + * appsink among them. + * + * - data passed to appsink should be video-frame in NV12 format. + * + * 'outputType' is used to select type of output data to produce: 'cv::MediaFrame' or 'cv::Mat'. + * To produce 'cv::MediaFrame'-s you need to pass 'GStreamerSource::OutputType::FRAME' and, + * correspondingly, 'GStreamerSource::OutputType::MAT' to produce 'cv::Mat'-s. + * Please note, that in the last case, output 'cv::Mat' will be of BGR format, internal conversion + * from NV12 GStreamer data will happen. + * Default value for 'outputType' is 'GStreamerSource::OutputType::MAT'. + * + * @note Stream sources are passed to G-API via shared pointers, so please use gapi::make_src<> + * to create objects and ptr() to pass a GStreamerSource to cv::gin(). + * + * @note You need to build OpenCV with GStreamer support to use this class. + */ + +class GStreamerPipelineFacade; + +class GAPI_EXPORTS GStreamerSource : public IStreamSource +{ +public: + class Priv; + + // Indicates what type of data should be produced by GStreamerSource: cv::MediaFrame or cv::Mat + enum class OutputType { + FRAME, + MAT + }; + + GStreamerSource(const std::string& pipeline, + const GStreamerSource::OutputType outputType = + GStreamerSource::OutputType::MAT); + GStreamerSource(std::shared_ptr pipeline, + const std::string& appsinkName, + const GStreamerSource::OutputType outputType = + GStreamerSource::OutputType::MAT); + + bool pull(cv::gapi::wip::Data& data) override; + GMetaArg descr_of() const override; + ~GStreamerSource() override; + +protected: + explicit GStreamerSource(std::unique_ptr priv); + + std::unique_ptr m_priv; +}; + +} // namespace gst + +using GStreamerSource = gst::GStreamerSource; + +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_GSTREAMER_GSTREAMERSOURCE_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/cfg_params.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/cfg_params.hpp new file mode 100644 index 00000000000..9dc5ead7d74 --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/cfg_params.hpp @@ -0,0 +1,88 @@ +// 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) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_ONEVPL_CFG_PARAMS_HPP +#define OPENCV_GAPI_STREAMING_ONEVPL_CFG_PARAMS_HPP + +#include +#include +#include + +#include +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +/** + * @brief Public class is using for creation of onevpl::GSource instances. + * + * Class members availaible through methods @ref CfgParam::get_name() and @ref CfgParam::get_value() are used by + * onevpl::GSource inner logic to create or find oneVPL particular implementation + * (software/hardware, specific API version and etc.). + * + * @note Because oneVPL may provide several implementations which are satisfying with multiple (or single one) @ref CfgParam + * criteria therefore it is possible to configure `preferred` parameters. This kind of CfgParams are created + * using `is_major = false` argument in @ref CfgParam::create method and are not used by creating oneVPL particular implementations. + * Instead they fill out a "score table" to select preferrable implementation from available list. Implementation are satisfying + * with most of these optional params would be chosen. + * If no one optional CfgParam params were present then first of available oneVPL implementation would be applied. + * Please get on https://spec.oneapi.io/versions/latest/elements/oneVPL/source/API_ref/VPL_disp_api_func.html?highlight=mfxcreateconfig#mfxsetconfigfilterproperty + * for using OneVPL configuration. In this schema `mfxU8 *name` represents @ref CfgParam::get_name() and + * `mfxVariant value` is @ref CfgParam::get_value() + */ +struct GAPI_EXPORTS CfgParam { + using name_t = std::string; + using value_t = cv::util::variant; + + /** + * Create onevp::GSource configuration parameter. + * + *@param name name of parameter. + *@param value value of parameter. + *@param is_major TRUE if parameter MUST be provided by OneVPL inner implementation, FALSE for optional (for resolve multiple available implementations). + * + */ + template + static CfgParam create(const std::string& name, ValueType&& value, bool is_major = true) { + CfgParam param(name, CfgParam::value_t(std::forward(value)), is_major); + return param; + } + + struct Priv; + + const name_t& get_name() const; + const value_t& get_value() const; + bool is_major() const; + bool operator==(const CfgParam& rhs) const; + bool operator< (const CfgParam& rhs) const; + bool operator!=(const CfgParam& rhs) const; + + CfgParam& operator=(const CfgParam& src); + CfgParam& operator=(CfgParam&& src); + CfgParam(const CfgParam& src); + CfgParam(CfgParam&& src); + ~CfgParam(); +private: + CfgParam(const std::string& param_name, value_t&& param_value, bool is_major_param); + std::shared_ptr m_priv; +}; + +} //namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_ONEVPL_CFG_PARAMS_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/data_provider_interface.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/data_provider_interface.hpp new file mode 100644 index 00000000000..c70e3db0ac6 --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/data_provider_interface.hpp @@ -0,0 +1,105 @@ +// 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) 2021 Intel Corporation + +#ifndef GAPI_STREAMING_ONEVPL_ONEVPL_DATA_PROVIDER_INTERFACE_HPP +#define GAPI_STREAMING_ONEVPL_ONEVPL_DATA_PROVIDER_INTERFACE_HPP +#include +#include +#include + +#include // GAPI_EXPORTS +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +struct GAPI_EXPORTS DataProviderException : public std::exception { + DataProviderException(const std::string& descr); + DataProviderException(std::string&& descr); + + virtual ~DataProviderException() = default; + virtual const char* what() const noexcept override; +private: + std::string reason; +}; + +struct GAPI_EXPORTS DataProviderSystemErrorException final : public DataProviderException { + DataProviderSystemErrorException(int error_code, const std::string& desription = std::string()); + ~DataProviderSystemErrorException() = default; +}; + +struct GAPI_EXPORTS DataProviderUnsupportedException final : public DataProviderException { + DataProviderUnsupportedException(const std::string& description); + ~DataProviderUnsupportedException() = default; +}; + +struct GAPI_EXPORTS DataProviderImplementationException : public DataProviderException { + DataProviderImplementationException(const std::string& description); + ~DataProviderImplementationException() = default; +}; +/** + * @brief Public interface allows to customize extraction of video stream data + * used by onevpl::GSource instead of reading stream from file (by default). + * + * Interface implementation constructor MUST provide consistency and creates fully operable object. + * If error happened implementation MUST throw `DataProviderException` kind exceptions + * + * @note Interface implementation MUST manage stream and other constructed resources by itself to avoid any kind of leak. + * For simple interface implementation example please see `StreamDataProvider` in `tests/streaming/gapi_streaming_tests.cpp` + */ +struct GAPI_EXPORTS IDataProvider { + using Ptr = std::shared_ptr; + using mfx_codec_id_type = uint32_t; + + /** + * NB: here is supposed to be forward declaration of mfxBitstream + * But according to current oneVPL implementation it is impossible to forward + * declare untagged struct mfxBitstream. + * + * IDataProvider makes sense only for HAVE_VPL is ON and to keep IDataProvider + * interface API/ABI compliant between core library and user application layer + * let's introduce wrapper mfx_bitstream which inherits mfxBitstream in private + * G-API code section and declare forward for wrapper mfx_bitstream here + */ + struct mfx_bitstream; + + virtual ~IDataProvider() = default; + + /** + * The function is used by onevpl::GSource to extract codec id from data + * + */ + virtual mfx_codec_id_type get_mfx_codec_id() const = 0; + + /** + * The function is used by onevpl::GSource to extract binary data stream from @ref IDataProvider + * implementation. + * + * It MUST throw `DataProviderException` kind exceptions in fail cases. + * It MUST return MFX_ERR_MORE_DATA in EOF which considered as not-fail case. + * + * @param in_out_bitsream the input-output reference on MFX bitstream buffer which MUST be empty at the first request + * to allow implementation to allocate it by itself and to return back. Subsequent invocation of `fetch_bitstream_data` + * MUST use the previously used in_out_bitsream to avoid skipping rest of frames which haven't been consumed + * @return true for fetched data, false on EOF and throws exception on error + */ + virtual bool fetch_bitstream_data(std::shared_ptr &in_out_bitsream) = 0; + + /** + * The function is used by onevpl::GSource to check more binary data availability. + * + * It MUST return TRUE in case of EOF and NO_THROW exceptions. + * + * @return boolean value which detects end of stream + */ + virtual bool empty() const = 0; +}; +} // namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // GAPI_STREAMING_ONEVPL_ONEVPL_DATA_PROVIDER_INTERFACE_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/device_selector_interface.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/device_selector_interface.hpp new file mode 100644 index 00000000000..04f8cae02a4 --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/device_selector_interface.hpp @@ -0,0 +1,102 @@ +// 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) 2021 Intel Corporation + +#ifndef GAPI_STREAMING_ONEVPL_DEVICE_SELECTOR_INTERFACE_HPP +#define GAPI_STREAMING_ONEVPL_DEVICE_SELECTOR_INTERFACE_HPP + +#include +#include +#include +#include + +#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { + +enum class AccelType: uint8_t { + HOST, + DX11, + + LAST_VALUE = std::numeric_limits::max() +}; + +GAPI_EXPORTS const char* to_cstring(AccelType type); + +struct IDeviceSelector; +struct GAPI_EXPORTS Device { + friend struct IDeviceSelector; + using Ptr = void*; + + ~Device(); + const std::string& get_name() const; + Ptr get_ptr() const; + AccelType get_type() const; +private: + Device(Ptr device_ptr, const std::string& device_name, + AccelType device_type); + + std::string name; + Ptr ptr; + AccelType type; +}; + +struct GAPI_EXPORTS Context { + friend struct IDeviceSelector; + using Ptr = void*; + + ~Context(); + Ptr get_ptr() const; + AccelType get_type() const; +private: + Context(Ptr ctx_ptr, AccelType ctx_type); + Ptr ptr; + AccelType type; +}; + +struct GAPI_EXPORTS IDeviceSelector { + using Ptr = std::shared_ptr; + + struct GAPI_EXPORTS Score { + friend struct IDeviceSelector; + using Type = int16_t; + static constexpr Type MaxActivePriority = std::numeric_limits::max(); + static constexpr Type MinActivePriority = 0; + static constexpr Type MaxPassivePriority = MinActivePriority - 1; + static constexpr Type MinPassivePriority = std::numeric_limits::min(); + + Score(Type val); + ~Score(); + + operator Type () const; + Type get() const; + friend bool operator< (Score lhs, Score rhs) { + return lhs.get() < rhs.get(); + } + private: + Type value; + }; + + using DeviceScoreTable = std::map; + using DeviceContexts = std::vector; + + virtual ~IDeviceSelector(); + virtual DeviceScoreTable select_devices() const = 0; + virtual DeviceContexts select_context() = 0; +protected: + template + static Entity create(Args &&...args) { + return Entity(std::forward(args)...); + } +}; +} // namespace onevpl +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // GAPI_STREAMING_ONEVPL_DEVICE_SELECTOR_INTERFACE_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/source.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/source.hpp new file mode 100644 index 00000000000..6334480c1bb --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/onevpl/source.hpp @@ -0,0 +1,90 @@ +// 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) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP +#define OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP + +#include +#include +#include +#include +#include +#include + +namespace cv { +namespace gapi { +namespace wip { +namespace onevpl { +using CfgParams = std::vector; + +/** + * @brief G-API streaming source based on OneVPL implementation. + * + * This class implements IStreamSource interface. + * Its constructor takes source file path (in usual way) or @ref onevpl::IDataProvider + * interface implementation (for not file-based sources). It also allows to pass-through + * oneVPL configuration parameters by using several @ref onevpl::CfgParam. + * + * @note stream sources are passed to G-API via shared pointers, so + * please gapi::make_onevpl_src<> to create objects and ptr() to pass a + * GSource to cv::gin(). + */ +class GAPI_EXPORTS GSource : public IStreamSource +{ +public: + struct Priv; + + GSource(const std::string& filePath, + const CfgParams& cfg_params = CfgParams{}); + + GSource(const std::string& filePath, + const CfgParams& cfg_params, + const std::string& device_id, + void* accel_device_ptr, + void* accel_ctx_ptr); + + GSource(const std::string& filePath, + const CfgParams& cfg_params, + std::shared_ptr selector); + + + GSource(std::shared_ptr source, + const CfgParams& cfg_params = CfgParams{}); + + GSource(std::shared_ptr source, + const CfgParams& cfg_params, + const std::string& device_id, + void* accel_device_ptr, + void* accel_ctx_ptr); + + GSource(std::shared_ptr source, + const CfgParams& cfg_params, + std::shared_ptr selector); + + ~GSource() override; + + bool pull(cv::gapi::wip::Data& data) override; + GMetaArg descr_of() const override; + +private: + explicit GSource(std::unique_ptr&& impl); + std::unique_ptr m_priv; +}; +} // namespace onevpl + +using GVPLSource = onevpl::GSource; + +template +GAPI_EXPORTS_W cv::Ptr inline make_onevpl_src(Args&&... args) +{ + return make_src(std::forward(args)...); +} + +} // namespace wip +} // namespace gapi +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_ONEVPL_ONEVPL_SOURCE_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/sync.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/sync.hpp new file mode 100644 index 00000000000..5801e6f00a3 --- /dev/null +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/streaming/sync.hpp @@ -0,0 +1,30 @@ +// 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) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_STREAMING_SYNC_HPP +#define OPENCV_GAPI_STREAMING_SYNC_HPP + +namespace cv { +namespace gapi { +namespace streaming { + +enum class sync_policy { + dont_sync, + drop +}; + +} // namespace streaming +} // namespace gapi + +namespace detail { + template<> struct CompileArgTag { + static const char* tag() { return "gapi.streaming.sync_policy"; } + }; + +} // namespace detail +} // namespace cv + +#endif // OPENCV_GAPI_STREAMING_SYNC_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/any.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/any.hpp index 5f97e95b08e..94451c77171 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/any.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/any.hpp @@ -31,7 +31,11 @@ namespace internal #if defined(__GXX_RTTI) || defined(_CPPRTTI) return dynamic_cast(operand); #else - #warning used static cast instead of dynamic because RTTI is disabled +#ifdef __GNUC__ +#warning used static cast instead of dynamic because RTTI is disabled +#else +#pragma message("WARNING: used static cast instead of dynamic because RTTI is disabled") +#endif return static_cast(operand); #endif } diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/optional.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/optional.hpp index 26d7b64a02e..dca03cadad8 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/optional.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/optional.hpp @@ -33,7 +33,7 @@ namespace util // Constructors // NB.: there were issues with Clang 3.8 when =default() was used // instead {} - optional() {}; + optional() {} optional(const optional&) = default; explicit optional(T&&) noexcept; explicit optional(const T&) noexcept; @@ -84,7 +84,7 @@ namespace util // Implementation ////////////////////////////////////////////////////////// template optional::optional(T &&v) noexcept - : m_holder(v) + : m_holder(std::move(v)) { } diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/util.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/util.hpp index afcf5596fd6..3be46d7ec2e 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/util.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/util.hpp @@ -116,7 +116,73 @@ namespace detail using type = std::tuple; static type get(std::tuple&& objs) { return std::forward>(objs); } }; + + template + struct make_void { typedef void type;}; + + template + using void_t = typename make_void::type; + } // namespace detail + +namespace util +{ +template +struct overload_lamba_set; + +template +struct overload_lamba_set : public L1 +{ + overload_lamba_set(L1&& lambda) : L1(std::move(lambda)) {} + overload_lamba_set(const L1& lambda) : L1(lambda) {} + + using L1::operator(); +}; + +template +struct overload_lamba_set : public L1, public overload_lamba_set +{ + using base_type = overload_lamba_set; + overload_lamba_set(L1 &&lambda1, L&& ...lambdas): + L1(std::move(lambda1)), + base_type(std::forward(lambdas)...) {} + + overload_lamba_set(const L1 &lambda1, L&& ...lambdas): + L1(lambda1), + base_type(std::forward(lambdas)...) {} + + using L1::operator(); + using base_type::operator(); +}; + +template +overload_lamba_set overload_lambdas(L&& ...lambdas) +{ + return overload_lamba_set(std::forward(lambdas)...); +} + +template +struct find_adapter_impl; + +template +struct find_adapter_impl +{ + using type = typename std::conditional::value, + T, + void>::type; + static constexpr bool found = std::is_base_of::value; +}; + +template +struct find_adapter_impl +{ + using type = typename std::conditional::value, + T, + typename find_adapter_impl::type>::type; + static constexpr bool found = std::is_base_of::value || + find_adapter_impl::found; +}; +} // namespace util } // namespace cv // \endcond diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/variant.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/variant.hpp index 71a06d2dcf2..f412110deb7 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/variant.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/variant.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include // max_of_t #include @@ -44,6 +45,12 @@ namespace util static const constexpr std::size_t value = detail::type_list_index_helper<0, Target, Types...>::value; }; + template + struct type_list_element + { + using type = typename std::tuple_element >::type; + }; + class bad_variant_access: public std::exception { public: @@ -233,9 +240,87 @@ namespace util template const T& get(const util::variant &v); + template + typename util::type_list_element::type& get(util::variant &v); + + template + const typename util::type_list_element::type& get(const util::variant &v); + template bool holds_alternative(const util::variant &v) noexcept; + + // Visitor + namespace detail + { + struct visitor_interface {}; + + // Class `visitor_return_type_deduction_helper` + // introduces solution for deduction `return_type` in `visit` function in common way + // for both Lambda and class Visitor and keep one interface invocation point: `visit` only + // his helper class is required to unify return_type deduction mechanism because + // for Lambda it is possible to take type of `decltype(visitor(get<0>(var)))` + // but for class Visitor there is no operator() in base case, + // because it provides `operator() (std::size_t index, ...)` + // So `visitor_return_type_deduction_helper` expose `operator()` + // uses only for class Visitor only for deduction `return type` in visit() + template + struct visitor_return_type_deduction_helper + { + using return_type = R; + + // to be used in Lambda return type deduction context only + template + return_type operator() (T&&); + }; + } + + // Special purpose `static_visitor` can receive additional arguments + template + struct static_visitor : public detail::visitor_interface, + public detail::visitor_return_type_deduction_helper { + + // assign responsibility for return type deduction to helper class + using return_type = typename detail::visitor_return_type_deduction_helper::return_type; + using detail::visitor_return_type_deduction_helper::operator(); + friend Impl; + + template + return_type operator() (std::size_t index, VariantValue&& value, Args&& ...args) + { + suppress_unused_warning(index); + return static_cast(this)-> visit( + std::forward(value), + std::forward(args)...); + } + }; + + // Special purpose `static_indexed_visitor` can receive additional arguments + // And make forwarding current variant index as runtime function argument to its `Impl` + template + struct static_indexed_visitor : public detail::visitor_interface, + public detail::visitor_return_type_deduction_helper { + + // assign responsibility for return type deduction to helper class + using return_type = typename detail::visitor_return_type_deduction_helper::return_type; + using detail::visitor_return_type_deduction_helper::operator(); + friend Impl; + + template + return_type operator() (std::size_t Index, VariantValue&& value, Args&& ...args) + { + return static_cast(this)-> visit(Index, + std::forward(value), + std::forward(args)...); + } + }; + + template + struct variant_size; + + template + struct variant_size> + : std::integral_constant { }; // FIXME: T&&, const TT&& versions. // Implementation ////////////////////////////////////////////////////////// @@ -402,6 +487,22 @@ namespace util throw_error(bad_variant_access()); } + template + typename util::type_list_element::type& get(util::variant &v) + { + using ReturnType = typename util::type_list_element::type; + return const_cast(get(static_cast &>(v))); + } + + template + const typename util::type_list_element::type& get(const util::variant &v) + { + static_assert(Index < sizeof...(Types), + "`Index` it out of bound of `util::variant` type list"); + using ReturnType = typename util::type_list_element::type; + return get(v); + } + template bool holds_alternative(const util::variant &v) noexcept { @@ -428,7 +529,130 @@ namespace util { return !(lhs == rhs); } -} // namespace cv + +namespace detail +{ + // terminate recursion implementation for `non-void` ReturnType + template + ReturnType apply_visitor_impl(Visitor&&, Variant&, + std::true_type, std::false_type, + VisitorArgs&& ...) + { + return {}; + } + + // terminate recursion implementation for `void` ReturnType + template + void apply_visitor_impl(Visitor&&, Variant&, + std::true_type, std::true_type, + VisitorArgs&& ...) + { + } + + // Intermediate resursion processor for Lambda Visitors + template + typename std::enable_if::type>::value, ReturnType>::type + apply_visitor_impl(Visitor&& visitor, Variant&& v, std::false_type not_processed, + std::integral_constant should_no_return, + VisitorArgs&& ...args) + { + static_assert(std::is_same(v)))>::value, + "Different `ReturnType`s detected! All `Visitor::visit` or `overload_lamba_set`" + " must return the same type"); + suppress_unused_warning(not_processed); + if (v.index() == CurIndex) + { + return visitor.operator()(get(v), std::forward(args)... ); + } + + using is_variant_processed_t = std::integral_constant= ElemCount>; + return apply_visitor_impl( + std::forward(visitor), + std::forward(v), + is_variant_processed_t{}, + should_no_return, + std::forward(args)...); + } + + //Visual Studio 2014 compilation fix: cast visitor to base class before invoke operator() + template + typename std::enable_if::type>, + typename std::decay::type>::value, ReturnType>::type + invoke_class_visitor(Visitor& visitor, Value&& v, VisitorArgs&&...args) + { + return static_cast::type>&>(visitor).operator() (CurIndex, std::forward(v), std::forward(args)... ); + } + + //Visual Studio 2014 compilation fix: cast visitor to base class before invoke operator() + template + typename std::enable_if::type>, + typename std::decay::type>::value, ReturnType>::type + invoke_class_visitor(Visitor& visitor, Value&& v, VisitorArgs&&...args) + { + return static_cast::type>&>(visitor).operator() (CurIndex, std::forward(v), std::forward(args)... ); + } + + // Intermediate recursion processor for special case `visitor_interface` derived Visitors + template + typename std::enable_if::type>::value, ReturnType>::type + apply_visitor_impl(Visitor&& visitor, Variant&& v, std::false_type not_processed, + std::integral_constant should_no_return, + VisitorArgs&& ...args) + { + static_assert(std::is_same(v)))>::value, + "Different `ReturnType`s detected! All `Visitor::visit` or `overload_lamba_set`" + " must return the same type"); + suppress_unused_warning(not_processed); + if (v.index() == CurIndex) + { + return invoke_class_visitor(visitor, get(v), std::forward(args)... ); + } + + using is_variant_processed_t = std::integral_constant= ElemCount>; + return apply_visitor_impl( + std::forward(visitor), + std::forward(v), + is_variant_processed_t{}, + should_no_return, + std::forward(args)...); + } +} // namespace detail + + template + auto visit(Visitor &visitor, const Variant& var, VisitorArg &&...args) -> decltype(visitor(get<0>(var))) + { + constexpr std::size_t varsize = util::variant_size::value; + static_assert(varsize != 0, "utils::variant must contains one type at least "); + using is_variant_processed_t = std::false_type; + + using ReturnType = decltype(visitor(get<0>(var))); + using return_t = std::is_same; + return detail::apply_visitor_impl( + std::forward(visitor), + var, is_variant_processed_t{}, + return_t{}, + std::forward(args)...); + } + + template + auto visit(Visitor&& visitor, const Variant& var) -> decltype(visitor(get<0>(var))) + { + constexpr std::size_t varsize = util::variant_size::value; + static_assert(varsize != 0, "utils::variant must contains one type at least "); + using is_variant_processed_t = std::false_type; + + using ReturnType = decltype(visitor(get<0>(var))); + using return_t = std::is_same; + return detail::apply_visitor_impl( + std::forward(visitor), + var, is_variant_processed_t{}, + return_t{}); + } } // namespace util +} // namespace cv #endif // OPENCV_GAPI_UTIL_VARIANT_HPP diff --git a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/video.hpp b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/video.hpp index 10965b0aa65..4dcc1d41824 100644 --- a/thirdparty/fluid/modules/gapi/include/opencv2/gapi/video.hpp +++ b/thirdparty/fluid/modules/gapi/include/opencv2/gapi/video.hpp @@ -42,6 +42,10 @@ struct GAPI_EXPORTS KalmanParams Mat controlMatrix; }; +/** + * @brief This namespace contains G-API Operations and functions for + * video-oriented algorithms, like optical flow and background subtraction. + */ namespace video { using GBuildPyrOutput = std::tuple, GScalar>; diff --git a/thirdparty/fluid/modules/gapi/misc/python/package/gapi/__init__.py b/thirdparty/fluid/modules/gapi/misc/python/package/gapi/__init__.py new file mode 100644 index 00000000000..b1326712fcb --- /dev/null +++ b/thirdparty/fluid/modules/gapi/misc/python/package/gapi/__init__.py @@ -0,0 +1,299 @@ +__all__ = ['op', 'kernel'] + +import sys +import cv2 as cv + +# NB: Register function in specific module +def register(mname): + def parameterized(func): + sys.modules[mname].__dict__[func.__name__] = func + return func + return parameterized + + +@register('cv2.gapi') +def networks(*args): + return cv.gapi_GNetPackage(list(map(cv.detail.strip, args))) + + +@register('cv2.gapi') +def compile_args(*args): + return list(map(cv.GCompileArg, args)) + + +@register('cv2') +def GIn(*args): + return [*args] + + +@register('cv2') +def GOut(*args): + return [*args] + + +@register('cv2') +def gin(*args): + return [*args] + + +@register('cv2.gapi') +def descr_of(*args): + return [*args] + + +@register('cv2') +class GOpaque(): + # NB: Inheritance from c++ class cause segfault. + # So just aggregate cv.GOpaqueT instead of inheritance + def __new__(cls, argtype): + return cv.GOpaqueT(argtype) + + class Bool(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_BOOL) + + class Int(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_INT) + + class Double(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_DOUBLE) + + class Float(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_FLOAT) + + class String(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_STRING) + + class Point(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_POINT) + + class Point2f(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_POINT2F) + + class Size(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_SIZE) + + class Rect(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_RECT) + + class Prim(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_DRAW_PRIM) + + class Any(): + def __new__(self): + return cv.GOpaqueT(cv.gapi.CV_ANY) + +@register('cv2') +class GArray(): + # NB: Inheritance from c++ class cause segfault. + # So just aggregate cv.GArrayT instead of inheritance + def __new__(cls, argtype): + return cv.GArrayT(argtype) + + class Bool(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_BOOL) + + class Int(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_INT) + + class Double(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_DOUBLE) + + class Float(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_FLOAT) + + class String(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_STRING) + + class Point(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_POINT) + + class Point2f(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_POINT2F) + + class Size(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_SIZE) + + class Rect(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_RECT) + + class Scalar(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_SCALAR) + + class Mat(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_MAT) + + class GMat(): + def __new__(self): + return cv.GArrayT(cv.gapi.CV_GMAT) + + class Prim(): + def __new__(self): + return cv.GArray(cv.gapi.CV_DRAW_PRIM) + + class Any(): + def __new__(self): + return cv.GArray(cv.gapi.CV_ANY) + + +# NB: Top lvl decorator takes arguments +def op(op_id, in_types, out_types): + + garray_types= { + cv.GArray.Bool: cv.gapi.CV_BOOL, + cv.GArray.Int: cv.gapi.CV_INT, + cv.GArray.Double: cv.gapi.CV_DOUBLE, + cv.GArray.Float: cv.gapi.CV_FLOAT, + cv.GArray.String: cv.gapi.CV_STRING, + cv.GArray.Point: cv.gapi.CV_POINT, + cv.GArray.Point2f: cv.gapi.CV_POINT2F, + cv.GArray.Size: cv.gapi.CV_SIZE, + cv.GArray.Rect: cv.gapi.CV_RECT, + cv.GArray.Scalar: cv.gapi.CV_SCALAR, + cv.GArray.Mat: cv.gapi.CV_MAT, + cv.GArray.GMat: cv.gapi.CV_GMAT, + cv.GArray.Prim: cv.gapi.CV_DRAW_PRIM, + cv.GArray.Any: cv.gapi.CV_ANY + } + + gopaque_types= { + cv.GOpaque.Size: cv.gapi.CV_SIZE, + cv.GOpaque.Rect: cv.gapi.CV_RECT, + cv.GOpaque.Bool: cv.gapi.CV_BOOL, + cv.GOpaque.Int: cv.gapi.CV_INT, + cv.GOpaque.Double: cv.gapi.CV_DOUBLE, + cv.GOpaque.Float: cv.gapi.CV_FLOAT, + cv.GOpaque.String: cv.gapi.CV_STRING, + cv.GOpaque.Point: cv.gapi.CV_POINT, + cv.GOpaque.Point2f: cv.gapi.CV_POINT2F, + cv.GOpaque.Size: cv.gapi.CV_SIZE, + cv.GOpaque.Rect: cv.gapi.CV_RECT, + cv.GOpaque.Prim: cv.gapi.CV_DRAW_PRIM, + cv.GOpaque.Any: cv.gapi.CV_ANY + } + + type2str = { + cv.gapi.CV_BOOL: 'cv.gapi.CV_BOOL' , + cv.gapi.CV_INT: 'cv.gapi.CV_INT' , + cv.gapi.CV_DOUBLE: 'cv.gapi.CV_DOUBLE' , + cv.gapi.CV_FLOAT: 'cv.gapi.CV_FLOAT' , + cv.gapi.CV_STRING: 'cv.gapi.CV_STRING' , + cv.gapi.CV_POINT: 'cv.gapi.CV_POINT' , + cv.gapi.CV_POINT2F: 'cv.gapi.CV_POINT2F' , + cv.gapi.CV_SIZE: 'cv.gapi.CV_SIZE', + cv.gapi.CV_RECT: 'cv.gapi.CV_RECT', + cv.gapi.CV_SCALAR: 'cv.gapi.CV_SCALAR', + cv.gapi.CV_MAT: 'cv.gapi.CV_MAT', + cv.gapi.CV_GMAT: 'cv.gapi.CV_GMAT', + cv.gapi.CV_DRAW_PRIM: 'cv.gapi.CV_DRAW_PRIM' + } + + # NB: Second lvl decorator takes class to decorate + def op_with_params(cls): + if not in_types: + raise Exception('{} operation should have at least one input!'.format(cls.__name__)) + + if not out_types: + raise Exception('{} operation should have at least one output!'.format(cls.__name__)) + + for i, t in enumerate(out_types): + if t not in [cv.GMat, cv.GScalar, *garray_types, *gopaque_types]: + raise Exception('{} unsupported output type: {} in possition: {}' + .format(cls.__name__, t.__name__, i)) + + def on(*args): + if len(in_types) != len(args): + raise Exception('Invalid number of input elements!\nExpected: {}, Actual: {}' + .format(len(in_types), len(args))) + + for i, (t, a) in enumerate(zip(in_types, args)): + if t in garray_types: + if not isinstance(a, cv.GArrayT): + raise Exception("{} invalid type for argument {}.\nExpected: {}, Actual: {}" + .format(cls.__name__, i, cv.GArrayT.__name__, type(a).__name__)) + + elif a.type() != garray_types[t]: + raise Exception("{} invalid GArrayT type for argument {}.\nExpected: {}, Actual: {}" + .format(cls.__name__, i, type2str[garray_types[t]], type2str[a.type()])) + + elif t in gopaque_types: + if not isinstance(a, cv.GOpaqueT): + raise Exception("{} invalid type for argument {}.\nExpected: {}, Actual: {}" + .format(cls.__name__, i, cv.GOpaqueT.__name__, type(a).__name__)) + + elif a.type() != gopaque_types[t]: + raise Exception("{} invalid GOpaque type for argument {}.\nExpected: {}, Actual: {}" + .format(cls.__name__, i, type2str[gopaque_types[t]], type2str[a.type()])) + + else: + if t != type(a): + raise Exception('{} invalid input type for argument {}.\nExpected: {}, Actual: {}' + .format(cls.__name__, i, t.__name__, type(a).__name__)) + + op = cv.gapi.__op(op_id, cls.outMeta, *args) + + out_protos = [] + for i, out_type in enumerate(out_types): + if out_type == cv.GMat: + out_protos.append(op.getGMat()) + elif out_type == cv.GScalar: + out_protos.append(op.getGScalar()) + elif out_type in gopaque_types: + out_protos.append(op.getGOpaque(gopaque_types[out_type])) + elif out_type in garray_types: + out_protos.append(op.getGArray(garray_types[out_type])) + else: + raise Exception("""In {}: G-API operation can't produce the output with type: {} in position: {}""" + .format(cls.__name__, out_type.__name__, i)) + + return tuple(out_protos) if len(out_protos) != 1 else out_protos[0] + + # NB: Extend operation class + cls.id = op_id + cls.on = staticmethod(on) + return cls + + return op_with_params + + +def kernel(op_cls): + # NB: Second lvl decorator takes class to decorate + def kernel_with_params(cls): + # NB: Add new members to kernel class + cls.id = op_cls.id + cls.outMeta = op_cls.outMeta + return cls + + return kernel_with_params + + +# FIXME: On the c++ side every class is placed in cv2 module. +cv.gapi.wip.draw.Rect = cv.gapi_wip_draw_Rect +cv.gapi.wip.draw.Text = cv.gapi_wip_draw_Text +cv.gapi.wip.draw.Circle = cv.gapi_wip_draw_Circle +cv.gapi.wip.draw.Line = cv.gapi_wip_draw_Line +cv.gapi.wip.draw.Mosaic = cv.gapi_wip_draw_Mosaic +cv.gapi.wip.draw.Image = cv.gapi_wip_draw_Image +cv.gapi.wip.draw.Poly = cv.gapi_wip_draw_Poly + +cv.gapi.streaming.queue_capacity = cv.gapi_streaming_queue_capacity diff --git a/thirdparty/fluid/modules/gapi/misc/python/pyopencv_gapi.hpp b/thirdparty/fluid/modules/gapi/misc/python/pyopencv_gapi.hpp index e25328e64f1..64f8277740d 100644 --- a/thirdparty/fluid/modules/gapi/misc/python/pyopencv_gapi.hpp +++ b/thirdparty/fluid/modules/gapi/misc/python/pyopencv_gapi.hpp @@ -3,123 +3,449 @@ #ifdef HAVE_OPENCV_GAPI +#ifdef _MSC_VER +#pragma warning(disable: 4503) // "decorated name length exceeded" +#endif + +#include +#include + // NB: Python wrapper replaces :: with _ for classes -using gapi_GKernelPackage = cv::gapi::GKernelPackage; -using gapi_GNetPackage = cv::gapi::GNetPackage; -using gapi_ie_PyParams = cv::gapi::ie::PyParams; -using gapi_wip_IStreamSource_Ptr = cv::Ptr; +using gapi_GKernelPackage = cv::gapi::GKernelPackage; +using gapi_GNetPackage = cv::gapi::GNetPackage; +using gapi_ie_PyParams = cv::gapi::ie::PyParams; +using gapi_wip_IStreamSource_Ptr = cv::Ptr; +using detail_ExtractArgsCallback = cv::detail::ExtractArgsCallback; +using detail_ExtractMetaCallback = cv::detail::ExtractMetaCallback; +using vector_GNetParam = std::vector; +using gapi_streaming_queue_capacity = cv::gapi::streaming::queue_capacity; + +// NB: Python wrapper generate T_U for T +// This behavior is only observed for inputs +using GOpaque_bool = cv::GOpaque; +using GOpaque_int = cv::GOpaque; +using GOpaque_double = cv::GOpaque; +using GOpaque_float = cv::GOpaque; +using GOpaque_string = cv::GOpaque; +using GOpaque_Point2i = cv::GOpaque; +using GOpaque_Point2f = cv::GOpaque; +using GOpaque_Size = cv::GOpaque; +using GOpaque_Rect = cv::GOpaque; + +using GArray_bool = cv::GArray; +using GArray_int = cv::GArray; +using GArray_double = cv::GArray; +using GArray_float = cv::GArray; +using GArray_string = cv::GArray; +using GArray_Point2i = cv::GArray; +using GArray_Point2f = cv::GArray; +using GArray_Size = cv::GArray; +using GArray_Rect = cv::GArray; +using GArray_Scalar = cv::GArray; +using GArray_Mat = cv::GArray; +using GArray_GMat = cv::GArray; +using GArray_Prim = cv::GArray; // FIXME: Python wrapper generate code without namespace std, // so it cause error: "string wasn't declared" // WA: Create using using std::string; +namespace cv +{ +namespace detail +{ + +class PyObjectHolder +{ +public: + PyObjectHolder(PyObject* o, bool owner = true); + PyObject* get() const; + +private: + class Impl; + std::shared_ptr m_impl; +}; + +} // namespace detail +} // namespace cv + +class cv::detail::PyObjectHolder::Impl +{ +public: + Impl(PyObject* object, bool owner); + PyObject* get() const; + ~Impl(); + +private: + PyObject* m_object; +}; + +cv::detail::PyObjectHolder::Impl::Impl(PyObject* object, bool owner) + : m_object(object) +{ + // NB: Become an owner of that PyObject. + // Need to store this and get access + // after the caller which provide the object is out of range. + if (owner) + { + // NB: Impossible take ownership if object is NULL. + GAPI_Assert(object); + Py_INCREF(m_object); + } +} + +cv::detail::PyObjectHolder::Impl::~Impl() +{ + // NB: If NULL was set, don't decrease counter. + if (m_object) + { + Py_DECREF(m_object); + } +} + +PyObject* cv::detail::PyObjectHolder::Impl::get() const +{ + return m_object; +} + +cv::detail::PyObjectHolder::PyObjectHolder(PyObject* object, bool owner) + : m_impl(new cv::detail::PyObjectHolder::Impl{object, owner}) +{ +} + +PyObject* cv::detail::PyObjectHolder::get() const +{ + return m_impl->get(); +} + template<> +PyObject* pyopencv_from(const cv::detail::PyObjectHolder& v) +{ + PyObject* o = cv::util::any_cast(v).get(); + Py_INCREF(o); + return o; +} + +// #FIXME: Is it possible to implement pyopencv_from/pyopencv_to for generic +// cv::variant ? +template <> +PyObject* pyopencv_from(const cv::gapi::wip::draw::Prim& prim) +{ + switch (prim.index()) + { + case cv::gapi::wip::draw::Prim::index_of(): + return pyopencv_from(cv::util::get(prim)); + case cv::gapi::wip::draw::Prim::index_of(): + return pyopencv_from(cv::util::get(prim)); + case cv::gapi::wip::draw::Prim::index_of(): + return pyopencv_from(cv::util::get(prim)); + case cv::gapi::wip::draw::Prim::index_of(): + return pyopencv_from(cv::util::get(prim)); + case cv::gapi::wip::draw::Prim::index_of(): + return pyopencv_from(cv::util::get(prim)); + case cv::gapi::wip::draw::Prim::index_of(): + return pyopencv_from(cv::util::get(prim)); + case cv::gapi::wip::draw::Prim::index_of(): + return pyopencv_from(cv::util::get(prim)); + } + + util::throw_error(std::logic_error("Unsupported draw primitive type")); +} + +template <> +PyObject* pyopencv_from(const cv::gapi::wip::draw::Prims& value) +{ + return pyopencv_from_generic_vec(value); +} + +template<> +bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prim& value, const ArgInfo&) +{ +#define TRY_EXTRACT(Prim) \ + if (PyObject_TypeCheck(obj, reinterpret_cast(pyopencv_gapi_wip_draw_##Prim##_TypePtr))) \ + { \ + value = reinterpret_cast(obj)->v; \ + return true; \ + } \ + + TRY_EXTRACT(Rect) + TRY_EXTRACT(Text) + TRY_EXTRACT(Circle) + TRY_EXTRACT(Line) + TRY_EXTRACT(Mosaic) + TRY_EXTRACT(Image) + TRY_EXTRACT(Poly) +#undef TRY_EXTRACT + + failmsg("Unsupported primitive type"); + return false; +} + +template <> +bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prims& value, const ArgInfo& info) +{ + return pyopencv_to_generic_vec(obj, value, info); +} + +template <> +bool pyopencv_to(PyObject* obj, cv::GMetaArg& value, const ArgInfo&) +{ +#define TRY_EXTRACT(Meta) \ + if (PyObject_TypeCheck(obj, \ + reinterpret_cast(pyopencv_##Meta##_TypePtr))) \ + { \ + value = reinterpret_cast(obj)->v; \ + return true; \ + } \ + + TRY_EXTRACT(GMatDesc) + TRY_EXTRACT(GScalarDesc) + TRY_EXTRACT(GArrayDesc) + TRY_EXTRACT(GOpaqueDesc) +#undef TRY_EXTRACT + + failmsg("Unsupported cv::GMetaArg type"); + return false; +} + +template <> +bool pyopencv_to(PyObject* obj, cv::GMetaArgs& value, const ArgInfo& info) +{ + return pyopencv_to_generic_vec(obj, value, info); +} + + +template<> +PyObject* pyopencv_from(const cv::GArg& value) +{ + GAPI_Assert(value.kind != cv::detail::ArgKind::GOBJREF); +#define HANDLE_CASE(T, O) case cv::detail::OpaqueKind::CV_##T: \ + { \ + return pyopencv_from(value.get()); \ + } + +#define UNSUPPORTED(T) case cv::detail::OpaqueKind::CV_##T: break + switch (value.opaque_kind) + { + HANDLE_CASE(BOOL, bool); + HANDLE_CASE(INT, int); + HANDLE_CASE(INT64, int64_t); + HANDLE_CASE(DOUBLE, double); + HANDLE_CASE(FLOAT, float); + HANDLE_CASE(STRING, std::string); + HANDLE_CASE(POINT, cv::Point); + HANDLE_CASE(POINT2F, cv::Point2f); + HANDLE_CASE(SIZE, cv::Size); + HANDLE_CASE(RECT, cv::Rect); + HANDLE_CASE(SCALAR, cv::Scalar); + HANDLE_CASE(MAT, cv::Mat); + HANDLE_CASE(UNKNOWN, cv::detail::PyObjectHolder); + HANDLE_CASE(DRAW_PRIM, cv::gapi::wip::draw::Prim); + UNSUPPORTED(UINT64); +#undef HANDLE_CASE +#undef UNSUPPORTED + } + util::throw_error(std::logic_error("Unsupported kernel input type")); +} + +template<> +bool pyopencv_to(PyObject* obj, cv::GArg& value, const ArgInfo& info) +{ + value = cv::GArg(cv::detail::PyObjectHolder(obj)); + return true; +} + +template <> +bool pyopencv_to(PyObject* obj, std::vector& value, const ArgInfo& info) +{ + return pyopencv_to_generic_vec(obj, value, info); +} + +template <> +PyObject* pyopencv_from(const std::vector& value) +{ + return pyopencv_from_generic_vec(value); +} + +template <> bool pyopencv_to(PyObject* obj, std::vector& value, const ArgInfo& info) { return pyopencv_to_generic_vec(obj, value, info); } -template<> +template <> PyObject* pyopencv_from(const std::vector& value) { return pyopencv_from_generic_vec(value); } template<> -bool pyopencv_to(PyObject* obj, GRunArgs& value, const ArgInfo& info) +PyObject* pyopencv_from(const cv::detail::OpaqueRef& o) { - return pyopencv_to_generic_vec(obj, value, info); + switch (o.getKind()) + { + case cv::detail::OpaqueKind::CV_BOOL : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_INT : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_INT64 : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_DOUBLE : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_FLOAT : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_STRING : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_POINT : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_POINT2F : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_SIZE : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_RECT : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_UNKNOWN : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_DRAW_PRIM : return pyopencv_from(o.rref()); + case cv::detail::OpaqueKind::CV_UINT64 : break; + case cv::detail::OpaqueKind::CV_SCALAR : break; + case cv::detail::OpaqueKind::CV_MAT : break; + } + + PyErr_SetString(PyExc_TypeError, "Unsupported GOpaque type"); + return NULL; +}; + +template <> +PyObject* pyopencv_from(const cv::detail::VectorRef& v) +{ + switch (v.getKind()) + { + case cv::detail::OpaqueKind::CV_BOOL : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_INT : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_INT64 : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_DOUBLE : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_FLOAT : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_STRING : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_POINT : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_POINT2F : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_SIZE : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_RECT : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_SCALAR : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_MAT : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_UNKNOWN : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_DRAW_PRIM : return pyopencv_from_generic_vec(v.rref()); + case cv::detail::OpaqueKind::CV_UINT64 : break; + } + + PyErr_SetString(PyExc_TypeError, "Unsupported GArray type"); + return NULL; } -static PyObject* from_grunarg(const GRunArg& v) +template <> +PyObject* pyopencv_from(const GRunArg& v) { switch (v.index()) { case GRunArg::index_of(): - { - const auto& m = util::get(v); - return pyopencv_from(m); - } + return pyopencv_from(util::get(v)); case GRunArg::index_of(): - { - const auto& s = util::get(v); - return pyopencv_from(s); - } + return pyopencv_from(util::get(v)); + case GRunArg::index_of(): - { - const auto& vref = util::get(v); - switch (vref.getKind()) - { - case cv::detail::OpaqueKind::CV_POINT2F: - return pyopencv_from(vref.rref()); - default: - PyErr_SetString(PyExc_TypeError, "Unsupported kind for GArray"); - return NULL; - } - } - default: - PyErr_SetString(PyExc_TypeError, "Failed to unpack GRunArgs"); - return NULL; + return pyopencv_from(util::get(v)); + + case GRunArg::index_of(): + return pyopencv_from(util::get(v)); } - GAPI_Assert(false); + + PyErr_SetString(PyExc_TypeError, "Failed to unpack GRunArgs. Index of variant is unknown"); + return NULL; +} + +template +PyObject* pyopencv_from(const cv::optional& opt) +{ + if (!opt.has_value()) + { + Py_RETURN_NONE; + } + return pyopencv_from(*opt); +} + +template <> +PyObject* pyopencv_from(const GOptRunArg& v) +{ + switch (v.index()) + { + case GOptRunArg::index_of>(): + return pyopencv_from(util::get>(v)); + + case GOptRunArg::index_of>(): + return pyopencv_from(util::get>(v)); + + case GOptRunArg::index_of>(): + return pyopencv_from(util::get>(v)); + + case GOptRunArg::index_of>(): + return pyopencv_from(util::get>(v)); + } + + PyErr_SetString(PyExc_TypeError, "Failed to unpack GOptRunArg. Index of variant is unknown"); + return NULL; } template<> PyObject* pyopencv_from(const GRunArgs& value) { - size_t i, n = value.size(); - - // NB: It doesn't make sense to return list with a single element - if (n == 1) - { - PyObject* item = from_grunarg(value[0]); - if(!item) - { - return NULL; - } - return item; - } - - PyObject* list = PyList_New(n); - for(i = 0; i < n; ++i) - { - PyObject* item = from_grunarg(value[i]); - if(!item) - { - Py_DECREF(list); - PyErr_SetString(PyExc_TypeError, "Failed to unpack GRunArgs"); - return NULL; - } - PyList_SetItem(list, i, item); - } - - return list; + return value.size() == 1 ? pyopencv_from(value[0]) : pyopencv_from_generic_vec(value); } template<> -bool pyopencv_to(PyObject* obj, GMetaArgs& value, const ArgInfo& info) +PyObject* pyopencv_from(const GOptRunArgs& value) { - return pyopencv_to_generic_vec(obj, value, info); + return value.size() == 1 ? pyopencv_from(value[0]) : pyopencv_from_generic_vec(value); } -template<> -PyObject* pyopencv_from(const GMetaArgs& value) +// FIXME: cv::variant should be wrapped once for all types. +template <> +PyObject* pyopencv_from(const cv::util::variant& v) { - return pyopencv_from_generic_vec(value); + using RunArgs = cv::util::variant; + switch (v.index()) + { + case RunArgs::index_of(): + return pyopencv_from(util::get(v)); + case RunArgs::index_of(): + return pyopencv_from(util::get(v)); + } + + PyErr_SetString(PyExc_TypeError, "Failed to recognize kind of RunArgs. Index of variant is unknown"); + return NULL; } template -static PyObject* extract_proto_args(PyObject* py_args, PyObject* kw) +void pyopencv_to_with_check(PyObject* from, T& to, const std::string& msg = "") +{ + if (!pyopencv_to(from, to, ArgInfo("", false))) + { + cv::util::throw_error(std::logic_error(msg)); + } +} + +template +void pyopencv_to_generic_vec_with_check(PyObject* from, + std::vector& to, + const std::string& msg = "") +{ + if (!pyopencv_to_generic_vec(from, to, ArgInfo("", false))) + { + cv::util::throw_error(std::logic_error(msg)); + } +} + +template +static T extract_proto_args(PyObject* py_args) { using namespace cv; GProtoArgs args; - Py_ssize_t size = PyTuple_Size(py_args); + Py_ssize_t size = PyList_Size(py_args); + args.reserve(size); for (int i = 0; i < size; ++i) { - PyObject* item = PyTuple_GetItem(py_args, i); + PyObject* item = PyList_GetItem(py_args, i); if (PyObject_TypeCheck(item, reinterpret_cast(pyopencv_GScalar_TypePtr))) { args.emplace_back(reinterpret_cast(item)->v); @@ -128,87 +454,626 @@ static PyObject* extract_proto_args(PyObject* py_args, PyObject* kw) { args.emplace_back(reinterpret_cast(item)->v); } - else if (PyObject_TypeCheck(item, reinterpret_cast(pyopencv_GArrayP2f_TypePtr))) + else if (PyObject_TypeCheck(item, reinterpret_cast(pyopencv_GOpaqueT_TypePtr))) { - args.emplace_back(reinterpret_cast(item)->v.strip()); + args.emplace_back(reinterpret_cast(item)->v.strip()); + } + else if (PyObject_TypeCheck(item, reinterpret_cast(pyopencv_GArrayT_TypePtr))) + { + args.emplace_back(reinterpret_cast(item)->v.strip()); } else { - PyErr_SetString(PyExc_TypeError, "Unsupported type for cv.GIn()/cv.GOut()"); - return NULL; + util::throw_error(std::logic_error("Unsupported type for GProtoArgs")); } } - return pyopencv_from(T{std::move(args)}); + return T(std::move(args)); } -static PyObject* pyopencv_cv_GIn(PyObject* , PyObject* py_args, PyObject* kw) +static cv::detail::OpaqueRef extract_opaque_ref(PyObject* from, cv::detail::OpaqueKind kind) { - return extract_proto_args(py_args, kw); +#define HANDLE_CASE(T, O) case cv::detail::OpaqueKind::CV_##T: \ +{ \ + O obj{}; \ + pyopencv_to_with_check(from, obj, "Failed to obtain " # O); \ + return cv::detail::OpaqueRef{std::move(obj)}; \ +} +#define UNSUPPORTED(T) case cv::detail::OpaqueKind::CV_##T: break + switch (kind) + { + HANDLE_CASE(BOOL, bool); + HANDLE_CASE(INT, int); + HANDLE_CASE(DOUBLE, double); + HANDLE_CASE(FLOAT, float); + HANDLE_CASE(STRING, std::string); + HANDLE_CASE(POINT, cv::Point); + HANDLE_CASE(POINT2F, cv::Point2f); + HANDLE_CASE(SIZE, cv::Size); + HANDLE_CASE(RECT, cv::Rect); + HANDLE_CASE(UNKNOWN, cv::GArg); + UNSUPPORTED(UINT64); + UNSUPPORTED(INT64); + UNSUPPORTED(SCALAR); + UNSUPPORTED(MAT); + UNSUPPORTED(DRAW_PRIM); +#undef HANDLE_CASE +#undef UNSUPPORTED + } + util::throw_error(std::logic_error("Unsupported type for GOpaqueT")); } -static PyObject* pyopencv_cv_GOut(PyObject* , PyObject* py_args, PyObject* kw) +static cv::detail::VectorRef extract_vector_ref(PyObject* from, cv::detail::OpaqueKind kind) { - return extract_proto_args(py_args, kw); +#define HANDLE_CASE(T, O) case cv::detail::OpaqueKind::CV_##T: \ +{ \ + std::vector obj; \ + pyopencv_to_generic_vec_with_check(from, obj, "Failed to obtain vector of " # O); \ + return cv::detail::VectorRef{std::move(obj)}; \ +} +#define UNSUPPORTED(T) case cv::detail::OpaqueKind::CV_##T: break + switch (kind) + { + HANDLE_CASE(BOOL, bool); + HANDLE_CASE(INT, int); + HANDLE_CASE(DOUBLE, double); + HANDLE_CASE(FLOAT, float); + HANDLE_CASE(STRING, std::string); + HANDLE_CASE(POINT, cv::Point); + HANDLE_CASE(POINT2F, cv::Point2f); + HANDLE_CASE(SIZE, cv::Size); + HANDLE_CASE(RECT, cv::Rect); + HANDLE_CASE(SCALAR, cv::Scalar); + HANDLE_CASE(MAT, cv::Mat); + HANDLE_CASE(UNKNOWN, cv::GArg); + HANDLE_CASE(DRAW_PRIM, cv::gapi::wip::draw::Prim); + UNSUPPORTED(UINT64); + UNSUPPORTED(INT64); +#undef HANDLE_CASE +#undef UNSUPPORTED + } + util::throw_error(std::logic_error("Unsupported type for GArrayT")); } -static PyObject* pyopencv_cv_gin(PyObject* , PyObject* py_args, PyObject* kw) +static cv::GRunArg extract_run_arg(const cv::GTypeInfo& info, PyObject* item) +{ + switch (info.shape) + { + case cv::GShape::GMAT: + { + // NB: In case streaming it can be IStreamSource or cv::Mat + if (PyObject_TypeCheck(item, + reinterpret_cast(pyopencv_gapi_wip_IStreamSource_TypePtr))) + { + cv::gapi::wip::IStreamSource::Ptr source = + reinterpret_cast(item)->v; + return source; + } + cv::Mat obj; + pyopencv_to_with_check(item, obj, "Failed to obtain cv::Mat"); + return obj; + } + case cv::GShape::GSCALAR: + { + cv::Scalar obj; + pyopencv_to_with_check(item, obj, "Failed to obtain cv::Scalar"); + return obj; + } + case cv::GShape::GOPAQUE: + { + return extract_opaque_ref(item, info.kind); + } + case cv::GShape::GARRAY: + { + return extract_vector_ref(item, info.kind); + } + case cv::GShape::GFRAME: + { + // NB: Isn't supported yet. + break; + } + } + + util::throw_error(std::logic_error("Unsupported output shape")); +} + +static cv::GRunArgs extract_run_args(const cv::GTypesInfo& info, PyObject* py_args) +{ + GAPI_Assert(PyList_Check(py_args)); + + cv::GRunArgs args; + Py_ssize_t list_size = PyList_Size(py_args); + args.reserve(list_size); + + for (int i = 0; i < list_size; ++i) + { + args.push_back(extract_run_arg(info[i], PyList_GetItem(py_args, i))); + } + + return args; +} + +static cv::GMetaArg extract_meta_arg(const cv::GTypeInfo& info, PyObject* item) +{ + switch (info.shape) + { + case cv::GShape::GMAT: + { + cv::Mat obj; + pyopencv_to_with_check(item, obj, "Failed to obtain cv::Mat"); + return cv::GMetaArg{cv::descr_of(obj)}; + } + case cv::GShape::GSCALAR: + { + cv::Scalar obj; + pyopencv_to_with_check(item, obj, "Failed to obtain cv::Scalar"); + return cv::GMetaArg{cv::descr_of(obj)}; + } + case cv::GShape::GARRAY: + { + return cv::GMetaArg{cv::empty_array_desc()}; + } + case cv::GShape::GOPAQUE: + { + return cv::GMetaArg{cv::empty_gopaque_desc()}; + } + case cv::GShape::GFRAME: + { + // NB: Isn't supported yet. + break; + } + } + util::throw_error(std::logic_error("Unsupported output shape")); +} + +static cv::GMetaArgs extract_meta_args(const cv::GTypesInfo& info, PyObject* py_args) +{ + GAPI_Assert(PyList_Check(py_args)); + + cv::GMetaArgs metas; + Py_ssize_t list_size = PyList_Size(py_args); + metas.reserve(list_size); + + for (int i = 0; i < list_size; ++i) + { + metas.push_back(extract_meta_arg(info[i], PyList_GetItem(py_args, i))); + } + + return metas; +} + +static cv::GRunArgs run_py_kernel(cv::detail::PyObjectHolder kernel, + const cv::gapi::python::GPythonContext &ctx) +{ + const auto& ins = ctx.ins; + const auto& in_metas = ctx.in_metas; + const auto& out_info = ctx.out_info; + + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); + + cv::GRunArgs outs; + try + { + int in_idx = 0; + // NB: Doesn't increase reference counter (false), + // because PyObject already have ownership. + // In case exception decrement reference counter. + cv::detail::PyObjectHolder args(PyTuple_New(ins.size()), false); + for (size_t i = 0; i < ins.size(); ++i) + { + // NB: If meta is monostate then object isn't associated with G-TYPE. + if (cv::util::holds_alternative(in_metas[i])) + { + PyTuple_SetItem(args.get(), i, pyopencv_from(ins[i])); + continue; + } + + switch (in_metas[i].index()) + { + case cv::GMetaArg::index_of(): + PyTuple_SetItem(args.get(), i, pyopencv_from(ins[i].get())); + break; + case cv::GMetaArg::index_of(): + PyTuple_SetItem(args.get(), i, pyopencv_from(ins[i].get())); + break; + case cv::GMetaArg::index_of(): + PyTuple_SetItem(args.get(), i, pyopencv_from(ins[i].get())); + break; + case cv::GMetaArg::index_of(): + PyTuple_SetItem(args.get(), i, pyopencv_from(ins[i].get())); + break; + case cv::GMetaArg::index_of(): + util::throw_error(std::logic_error("GFrame isn't supported for custom operation")); + break; + } + ++in_idx; + } + // NB: Doesn't increase reference counter (false). + // In case PyObject_CallObject return NULL, do nothing in destructor. + cv::detail::PyObjectHolder result( + PyObject_CallObject(kernel.get(), args.get()), false); + + if (PyErr_Occurred()) + { + PyErr_PrintEx(0); + PyErr_Clear(); + throw std::logic_error("Python kernel failed with error!"); + } + // NB: In fact it's impossible situation, becase errors were handled above. + GAPI_Assert(result.get() && "Python kernel returned NULL!"); + + if (out_info.size() == 1) + { + outs = cv::GRunArgs{extract_run_arg(out_info[0], result.get())}; + } + else if (out_info.size() > 1) + { + GAPI_Assert(PyTuple_Check(result.get())); + + Py_ssize_t tuple_size = PyTuple_Size(result.get()); + outs.reserve(tuple_size); + + for (int i = 0; i < tuple_size; ++i) + { + outs.push_back(extract_run_arg(out_info[i], PyTuple_GetItem(result.get(), i))); + } + } + else + { + // Seems to be impossible case. + GAPI_Assert(false); + } + } + catch (...) + { + PyGILState_Release(gstate); + throw; + } + PyGILState_Release(gstate); + + return outs; +} + +static GMetaArg get_meta_arg(PyObject* obj) +{ + cv::GMetaArg arg; + if (!pyopencv_to(obj, arg, ArgInfo("arg", false))) + { + util::throw_error(std::logic_error("Unsupported output meta type")); + } + return arg; +} + +static cv::GMetaArgs get_meta_args(PyObject* tuple) +{ + size_t size = PyTuple_Size(tuple); + + cv::GMetaArgs metas; + metas.reserve(size); + for (size_t i = 0; i < size; ++i) + { + metas.push_back(get_meta_arg(PyTuple_GetItem(tuple, i))); + } + + return metas; +} + +static GMetaArgs run_py_meta(cv::detail::PyObjectHolder out_meta, + const cv::GMetaArgs &meta, + const cv::GArgs &gargs) +{ + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); + + cv::GMetaArgs out_metas; + try + { + // NB: Doesn't increase reference counter (false), + // because PyObject already have ownership. + // In case exception decrement reference counter. + cv::detail::PyObjectHolder args(PyTuple_New(meta.size()), false); + size_t idx = 0; + for (auto&& m : meta) + { + switch (m.index()) + { + case cv::GMetaArg::index_of(): + PyTuple_SetItem(args.get(), idx, pyopencv_from(cv::util::get(m))); + break; + case cv::GMetaArg::index_of(): + PyTuple_SetItem(args.get(), idx, pyopencv_from(cv::util::get(m))); + break; + case cv::GMetaArg::index_of(): + PyTuple_SetItem(args.get(), idx, pyopencv_from(cv::util::get(m))); + break; + case cv::GMetaArg::index_of(): + PyTuple_SetItem(args.get(), idx, pyopencv_from(cv::util::get(m))); + break; + case cv::GMetaArg::index_of(): + PyTuple_SetItem(args.get(), idx, pyopencv_from(gargs[idx])); + break; + case cv::GMetaArg::index_of(): + util::throw_error(std::logic_error("GFrame isn't supported for custom operation")); + break; + } + ++idx; + } + // NB: Doesn't increase reference counter (false). + // In case PyObject_CallObject return NULL, do nothing in destructor. + cv::detail::PyObjectHolder result( + PyObject_CallObject(out_meta.get(), args.get()), false); + + if (PyErr_Occurred()) + { + PyErr_PrintEx(0); + PyErr_Clear(); + throw std::logic_error("Python outMeta failed with error!"); + } + // NB: In fact it's impossible situation, becase errors were handled above. + GAPI_Assert(result.get() && "Python outMeta returned NULL!"); + + out_metas = PyTuple_Check(result.get()) ? get_meta_args(result.get()) + : cv::GMetaArgs{get_meta_arg(result.get())}; + } + catch (...) + { + PyGILState_Release(gstate); + throw; + } + PyGILState_Release(gstate); + + return out_metas; +} + +static PyObject* pyopencv_cv_gapi_kernels(PyObject* , PyObject* py_args, PyObject*) { using namespace cv; - - GRunArgs args; + gapi::GKernelPackage pkg; Py_ssize_t size = PyTuple_Size(py_args); + for (int i = 0; i < size; ++i) { - PyObject* item = PyTuple_GetItem(py_args, i); - if (PyTuple_Check(item)) + PyObject* user_kernel = PyTuple_GetItem(py_args, i); + + PyObject* id_obj = PyObject_GetAttrString(user_kernel, "id"); + if (!id_obj) { - cv::Scalar s; - if (pyopencv_to(item, s, ArgInfo("scalar", false))) - { - args.emplace_back(s); - } - else - { - PyErr_SetString(PyExc_TypeError, "Failed convert tuple to cv::Scalar"); - return NULL; - } + PyErr_SetString(PyExc_TypeError, + "Python kernel should contain id, please use cv.gapi.kernel to define kernel"); + return NULL; } - else if (PyArray_Check(item)) + + PyObject* out_meta = PyObject_GetAttrString(user_kernel, "outMeta"); + if (!out_meta) { - cv::Mat m; - if (pyopencv_to(item, m, ArgInfo("mat", false))) - { - args.emplace_back(m); - } - else - { - PyErr_SetString(PyExc_TypeError, "Failed convert array to cv::Mat"); - return NULL; - } + PyErr_SetString(PyExc_TypeError, + "Python kernel should contain outMeta, please use cv.gapi.kernel to define kernel"); + return NULL; + } + + PyObject* run = PyObject_GetAttrString(user_kernel, "run"); + if (!run) + { + PyErr_SetString(PyExc_TypeError, + "Python kernel should contain run, please use cv.gapi.kernel to define kernel"); + return NULL; + } + + std::string id; + if (!pyopencv_to(id_obj, id, ArgInfo("id", false))) + { + PyErr_SetString(PyExc_TypeError, "Failed to obtain string"); + return NULL; + } + + using namespace std::placeholders; + gapi::python::GPythonFunctor f(id.c_str(), + std::bind(run_py_meta , cv::detail::PyObjectHolder{out_meta}, _1, _2), + std::bind(run_py_kernel, cv::detail::PyObjectHolder{run} , _1)); + pkg.include(f); + } + return pyopencv_from(pkg); +} + +static PyObject* pyopencv_cv_gapi_op(PyObject* , PyObject* py_args, PyObject*) +{ + using namespace cv; + Py_ssize_t size = PyTuple_Size(py_args); + std::string id; + if (!pyopencv_to(PyTuple_GetItem(py_args, 0), id, ArgInfo("id", false))) + { + PyErr_SetString(PyExc_TypeError, "Failed to obtain: operation id must be a string"); + return NULL; + } + PyObject* outMeta = PyTuple_GetItem(py_args, 1); + + cv::GArgs args; + for (int i = 2; i < size; i++) + { + PyObject* item = PyTuple_GetItem(py_args, i); + if (PyObject_TypeCheck(item, + reinterpret_cast(pyopencv_GMat_TypePtr))) + { + args.emplace_back(reinterpret_cast(item)->v); } else if (PyObject_TypeCheck(item, - reinterpret_cast(pyopencv_gapi_wip_IStreamSource_TypePtr))) + reinterpret_cast(pyopencv_GScalar_TypePtr))) { - cv::gapi::wip::IStreamSource::Ptr source = - reinterpret_cast(item)->v; - args.emplace_back(source); + args.emplace_back(reinterpret_cast(item)->v); + } + else if (PyObject_TypeCheck(item, + reinterpret_cast(pyopencv_GOpaqueT_TypePtr))) + { + auto&& arg = reinterpret_cast(item)->v.arg(); +#define HC(T, K) case cv::GOpaqueT::Storage:: index_of>(): \ + args.emplace_back(cv::util::get>(arg)); \ + break; \ + + SWITCH(arg.index(), GOPAQUE_TYPE_LIST_G, HC) +#undef HC + } + else if (PyObject_TypeCheck(item, + reinterpret_cast(pyopencv_GArrayT_TypePtr))) + { + auto&& arg = reinterpret_cast(item)->v.arg(); +#define HC(T, K) case cv::GArrayT::Storage:: index_of>(): \ + args.emplace_back(cv::util::get>(arg)); \ + break; \ + + SWITCH(arg.index(), GARRAY_TYPE_LIST_G, HC) +#undef HC } else { - PyErr_SetString(PyExc_TypeError, "cv.gin can works only with cv::Mat," - "cv::Scalar, cv::gapi::wip::IStreamSource::Ptr"); - return NULL; + args.emplace_back(cv::GArg(cv::detail::PyObjectHolder{item})); } } - return pyopencv_from_generic_vec(args); + cv::GKernel::M outMetaWrapper = std::bind(run_py_meta, + cv::detail::PyObjectHolder{outMeta}, + std::placeholders::_1, + std::placeholders::_2); + return pyopencv_from(cv::gapi::wip::op(id, outMetaWrapper, std::move(args))); } -static PyObject* pyopencv_cv_gout(PyObject* o, PyObject* py_args, PyObject* kw) +template<> +bool pyopencv_to(PyObject* obj, cv::detail::ExtractArgsCallback& value, const ArgInfo&) { - return pyopencv_cv_gin(o, py_args, kw); + cv::detail::PyObjectHolder holder{obj}; + value = cv::detail::ExtractArgsCallback{[=](const cv::GTypesInfo& info) + { + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); + + cv::GRunArgs args; + try + { + args = extract_run_args(info, holder.get()); + } + catch (...) + { + PyGILState_Release(gstate); + throw; + } + PyGILState_Release(gstate); + return args; + }}; + return true; } +template<> +bool pyopencv_to(PyObject* obj, cv::detail::ExtractMetaCallback& value, const ArgInfo&) +{ + cv::detail::PyObjectHolder holder{obj}; + value = cv::detail::ExtractMetaCallback{[=](const cv::GTypesInfo& info) + { + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); + + cv::GMetaArgs args; + try + { + args = extract_meta_args(info, holder.get()); + } + catch (...) + { + PyGILState_Release(gstate); + throw; + } + PyGILState_Release(gstate); + return args; + }}; + return true; +} + +template +struct PyOpenCV_Converter> +{ + static PyObject* from(const cv::GArray& p) + { + return pyopencv_from(cv::GArrayT(p)); + } + static bool to(PyObject *obj, cv::GArray& value, const ArgInfo& info) + { + if (PyObject_TypeCheck(obj, reinterpret_cast(pyopencv_GArrayT_TypePtr))) + { + auto& array = reinterpret_cast(obj)->v; + try + { + value = cv::util::get>(array.arg()); + } + catch (...) + { + return false; + } + return true; + } + return false; + } +}; + +template +struct PyOpenCV_Converter> +{ + static PyObject* from(const cv::GOpaque& p) + { + return pyopencv_from(cv::GOpaqueT(p)); + } + static bool to(PyObject *obj, cv::GOpaque& value, const ArgInfo& info) + { + if (PyObject_TypeCheck(obj, reinterpret_cast(pyopencv_GOpaqueT_TypePtr))) + { + auto& opaque = reinterpret_cast(obj)->v; + try + { + value = cv::util::get>(opaque.arg()); + } + catch (...) + { + return false; + } + return true; + } + return false; + } +}; + +template<> +bool pyopencv_to(PyObject* obj, cv::GProtoInputArgs& value, const ArgInfo& info) +{ + try + { + value = extract_proto_args(obj); + return true; + } + catch (...) + { + failmsg("Can't parse cv::GProtoInputArgs"); + return false; + } +} + +template<> +bool pyopencv_to(PyObject* obj, cv::GProtoOutputArgs& value, const ArgInfo& info) +{ + try + { + value = extract_proto_args(obj); + return true; + } + catch (...) + { + failmsg("Can't parse cv::GProtoOutputArgs"); + return false; + } +} + +// extend cv.gapi methods +#define PYOPENCV_EXTRA_METHODS_GAPI \ + {"kernels", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_kernels), "kernels(...) -> GKernelPackage"}, \ + {"__op", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_op), "__op(...) -> retval\n"}, + + #endif // HAVE_OPENCV_GAPI #endif // OPENCV_GAPI_PYOPENCV_GAPI_HPP diff --git a/thirdparty/fluid/modules/gapi/misc/python/python_bridge.hpp b/thirdparty/fluid/modules/gapi/misc/python/python_bridge.hpp new file mode 100644 index 00000000000..11d17287308 --- /dev/null +++ b/thirdparty/fluid/modules/gapi/misc/python/python_bridge.hpp @@ -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) 2021 Intel Corporation + +#ifndef OPENCV_GAPI_PYTHON_BRIDGE_HPP +#define OPENCV_GAPI_PYTHON_BRIDGE_HPP + +#include +#include +#include +#include // Prim + +#define ID(T, E) T +#define ID_(T, E) ID(T, E), + +#define WRAP_ARGS(T, E, G) \ + G(T, E) + +#define SWITCH(type, LIST_G, HC) \ + switch(type) { \ + LIST_G(HC, HC) \ + default: \ + GAPI_Assert(false && "Unsupported type"); \ + } + +using cv::gapi::wip::draw::Prim; + +#define GARRAY_TYPE_LIST_G(G, G2) \ +WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \ +WRAP_ARGS(int , cv::gapi::ArgType::CV_INT, G) \ +WRAP_ARGS(int64_t , cv::gapi::ArgType::CV_INT64, G) \ +WRAP_ARGS(double , cv::gapi::ArgType::CV_DOUBLE, G) \ +WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \ +WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, G) \ +WRAP_ARGS(cv::Point , cv::gapi::ArgType::CV_POINT, G) \ +WRAP_ARGS(cv::Point2f , cv::gapi::ArgType::CV_POINT2F, G) \ +WRAP_ARGS(cv::Size , cv::gapi::ArgType::CV_SIZE, G) \ +WRAP_ARGS(cv::Rect , cv::gapi::ArgType::CV_RECT, G) \ +WRAP_ARGS(cv::Scalar , cv::gapi::ArgType::CV_SCALAR, G) \ +WRAP_ARGS(cv::Mat , cv::gapi::ArgType::CV_MAT, G) \ +WRAP_ARGS(Prim , cv::gapi::ArgType::CV_DRAW_PRIM, G) \ +WRAP_ARGS(cv::GArg , cv::gapi::ArgType::CV_ANY, G) \ +WRAP_ARGS(cv::GMat , cv::gapi::ArgType::CV_GMAT, G2) \ + +#define GOPAQUE_TYPE_LIST_G(G, G2) \ +WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \ +WRAP_ARGS(int , cv::gapi::ArgType::CV_INT, G) \ +WRAP_ARGS(int64_t , cv::gapi::ArgType::CV_INT64, G) \ +WRAP_ARGS(double , cv::gapi::ArgType::CV_DOUBLE, G) \ +WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \ +WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, G) \ +WRAP_ARGS(cv::Point , cv::gapi::ArgType::CV_POINT, G) \ +WRAP_ARGS(cv::Point2f , cv::gapi::ArgType::CV_POINT2F, G) \ +WRAP_ARGS(cv::Size , cv::gapi::ArgType::CV_SIZE, G) \ +WRAP_ARGS(cv::GArg , cv::gapi::ArgType::CV_ANY, G) \ +WRAP_ARGS(cv::Rect , cv::gapi::ArgType::CV_RECT, G2) \ + +namespace cv { +namespace gapi { + +// NB: cv.gapi.CV_BOOL in python +enum ArgType { + CV_BOOL, + CV_INT, + CV_INT64, + CV_DOUBLE, + CV_FLOAT, + CV_STRING, + CV_POINT, + CV_POINT2F, + CV_SIZE, + CV_RECT, + CV_SCALAR, + CV_MAT, + CV_GMAT, + CV_DRAW_PRIM, + CV_ANY, +}; + +GAPI_EXPORTS_W inline cv::GInferOutputs infer(const String& name, const cv::GInferInputs& inputs) +{ + return infer(name, inputs); +} + +GAPI_EXPORTS_W inline GInferOutputs infer(const std::string& name, + const cv::GOpaque& roi, + const GInferInputs& inputs) +{ + return infer(name, roi, inputs); +} + +GAPI_EXPORTS_W inline GInferListOutputs infer(const std::string& name, + const cv::GArray& rois, + const GInferInputs& inputs) +{ + return infer(name, rois, inputs); +} + +GAPI_EXPORTS_W inline GInferListOutputs infer2(const std::string& name, + const cv::GMat in, + const GInferListInputs& inputs) +{ + return infer2(name, in, inputs); +} + +} // namespace gapi + +namespace detail { + +template