summaryrefslogtreecommitdiff
path: root/inference-engine/thirdparty/fluid
diff options
context:
space:
mode:
authorAlexey Suhov <asuhov@users.noreply.github.com>2019-01-21 21:31:31 +0300
committeropenvino-pushbot <44090433+openvino-pushbot@users.noreply.github.com>2019-01-21 21:31:31 +0300
commit9de27f16bc8b712a5b8c99d1d4b4a66c9144942d (patch)
tree01a383efe94d92b9870d513c2c5ea5d15b07010a /inference-engine/thirdparty/fluid
parentfbc7a4a710c24def8ab199926a7da90a0394b87d (diff)
downloaddldt-9de27f16bc8b712a5b8c99d1d4b4a66c9144942d.tar.gz
dldt-9de27f16bc8b712a5b8c99d1d4b4a66c9144942d.tar.bz2
dldt-9de27f16bc8b712a5b8c99d1d4b4a66c9144942d.zip
Publishing R5 content (#72)
* Publishing R5 content * Updated ade revision * updated readme * add possibility to build CPU plugin with Intel MKL package
Diffstat (limited to 'inference-engine/thirdparty/fluid')
-rw-r--r--inference-engine/thirdparty/fluid/README.md45
-rw-r--r--inference-engine/thirdparty/fluid/check.sh15
-rw-r--r--inference-engine/thirdparty/fluid/checksum.sh3
-rw-r--r--inference-engine/thirdparty/fluid/checksum.txt1
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/CMakeLists.txt112
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/cmake/DownloadADE.cmake36
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/cmake/init.cmake11
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/cmake/standalone.cmake34
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/doc/00-root.markdown113
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/doc/01-background.markdown76
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/doc/10-hld-overview.md159
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/doc/20-kernel-api.markdown170
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/doc/30-implementation.markdown27
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/doc/dot/kernel_hierarchy.dot17
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/doc/pics/demo.jpgbin0 -> 65973 bytes
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/doc/pics/gapi_scheme.pngbin0 -> 76918 bytes
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/doc/pics/kernel_hierarchy.pngbin0 -> 8812 bytes
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi.hpp33
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/core.hpp1600
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/core.hpp27
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp266
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/imgproc.hpp27
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/core.hpp20
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidbuffer.hpp150
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp302
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/imgproc.hpp20
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garg.hpp126
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garray.hpp251
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcall.hpp63
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcommon.hpp166
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompiled.hpp217
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompoundkernel.hpp123
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcomputation.hpp456
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gkernel.hpp563
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmat.hpp149
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmetaarg.hpp66
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gproto.hpp96
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/core.hpp27
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/ggpukernel.hpp244
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/imgproc.hpp27
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gscalar.hpp83
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtype_traits.hpp152
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtyped.hpp187
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/imgproc.hpp677
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/opencv_includes.hpp21
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/operators.hpp69
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/assert.hpp41
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/convert.hpp50
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/cvdefs.hpp146
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/exports.hpp28
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/mat.hpp291
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/saturate.hpp90
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/scalar.hpp47
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/types.hpp135
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/any.hpp186
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/compiler_hints.hpp21
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/optional.hpp178
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/throw.hpp36
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/util.hpp92
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/variant.hpp377
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests.cpp9
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests.hpp76
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests_inl.hpp1841
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests.cpp9
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp46
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp909
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_core_perf_tests_cpu.cpp286
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp188
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_fluid.cpp76
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_core_perf_tests_gpu.cpp291
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_imgproc_perf_tests_gpu.cpp180
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/internal/gapi_compiler_perf_tests.cpp45
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/perf_main.cpp11
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/perf/perf_precomp.hpp25
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/samples/api_example.cpp34
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/samples/api_ref_snippets.cpp82
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/samples/kernel_api_snippets.cpp157
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/README.md1
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gapi_priv.cpp44
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gapi_priv.hpp77
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/garray.cpp45
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gbackend.cpp353
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gbackend_priv.hpp53
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gcall.cpp65
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gcall_priv.hpp37
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation.cpp238
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation_priv.hpp29
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gkernel.cpp147
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gmat.cpp78
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode.cpp89
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode.hpp58
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode_priv.hpp52
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto.cpp162
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto_priv.hpp35
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/gscalar.cpp73
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_core.cpp359
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_imgproc.cpp144
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/api/operators.cpp213
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/README.md2
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gbackend.hpp106
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gcompoundbackend.cpp20
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gcompoundkernel.cpp47
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.cpp229
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.hpp72
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpucore.cpp595
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpucore.hpp24
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuimgproc.cpp273
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuimgproc.hpp23
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpukernel.cpp52
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.cpp1383
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.hpp137
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer.cpp760
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer_priv.hpp308
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidcore.cpp2193
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc.cpp1338
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.dispatch.cpp93
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.hpp64
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.simd.hpp562
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidutils.hpp93
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpubackend.cpp226
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpubackend.hpp72
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpucore.cpp582
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpucore.hpp24
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpuimgproc.cpp277
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpuimgproc.hpp23
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpukernel.cpp50
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/README.md1
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled.cpp157
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled_priv.hpp61
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.cpp281
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.hpp51
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.cpp289
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.hpp187
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.cpp247
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.hpp251
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodelbuilder.cpp305
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodelbuilder.hpp77
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gobjref.hpp50
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/dump_dot.cpp223
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/exec.cpp641
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/helpers.cpp122
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/helpers.hpp31
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/islands.cpp233
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/kernels.cpp157
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/meta.cpp125
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/passes.hpp58
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/compiler/transactions.hpp147
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.cpp244
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.hpp97
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/logger.hpp22
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/src/precomp.hpp21
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_compoundkernel_tests.cpp500
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests.cpp9
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests.hpp153
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests_inl.hpp1479
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests.cpp9
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests.hpp42
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp630
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests.cpp9
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests.hpp192
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests_inl.hpp104
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_tests_common.hpp296
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_cpu.cpp405
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_fluid.cpp506
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp238
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_fluid.cpp168
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_cpu.cpp73
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_fluid.cpp72
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_array_tests.cpp166
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_basic_hetero_tests.cpp312
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_desc_tests.cpp202
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_resize_test.cpp720
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_roi_test.cpp197
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test.cpp713
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test_kernels.cpp436
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test_kernels.hpp105
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_gcompiled_tests.cpp173
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_gcomputation_tests.cpp68
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_kernel_tests.cpp284
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_mock_kernels.hpp123
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_sample_pipelines.cpp301
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_scalar_tests.cpp117
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_smoke_test.cpp97
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_typed_tests.cpp185
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gapi_util_tests.cpp43
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_core_tests_gpu.cpp395
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_imgproc_tests_gpu.cpp227
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_operators_tests_gpu.cpp72
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_backend_tests.cpp86
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_executor_tests.cpp83
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_garg_test.cpp100
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_gmetaarg_test.cpp136
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp364
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_island_fusion_tests.cpp527
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_island_tests.cpp653
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_recompilation_test.cpp233
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_resolve_kernel_test.cpp119
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_vectorref_test.cpp207
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_transactions_test.cpp222
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/own/gapi_types_tests.cpp159
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/own/mat_tests.cpp387
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/own/scalar_tests.cpp44
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/test_main.cpp12
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/test_precomp.hpp27
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/util/any_tests.cpp121
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/util/optional_tests.cpp175
-rw-r--r--inference-engine/thirdparty/fluid/modules/gapi/test/util/variant_tests.cpp386
-rw-r--r--inference-engine/thirdparty/fluid/revision.txt1
-rw-r--r--inference-engine/thirdparty/fluid/update.sh73
209 files changed, 43004 insertions, 0 deletions
diff --git a/inference-engine/thirdparty/fluid/README.md b/inference-engine/thirdparty/fluid/README.md
new file mode 100644
index 000000000..3b31555e5
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/README.md
@@ -0,0 +1,45 @@
+# OpenCV G-API (Fluid), standalone edition
+
+This subtree hosts sources of G-API - a new OpenCV module for
+efficient image processing. G-API serves as a preprocessing vehicle
+for Inference Engine. At the moment, only Fluid (CPU) backend is used.
+
+The sources are taken from OpenCV's [main repository](https://github.com/opencv).
+
+There are supplementary scripts which ease and verify the update
+process.
+
+## Usage
+
+Updating to the latest `master`:
+
+ ./update.sh
+
+Updating to a particular revision:
+
+ ./update.sh COMMIT_HASH
+
+During update, this script checks if the source tree was modified
+after the latest update. If it was, update fails -- we want to avoid
+any diverge in the source so _no changes_ should be committed ever to
+this copy of G-API.
+
+One can check manually if sources were diverged from its last "valid"
+copy by running
+
+ ./check.sh
+
+An error message and non-zero exit code indicate possible inconsitency
+with this source copy.
+
+One updated, all changes will be automatically staged.
+
+## Files
+
+In addition to the source tree, the above two scripts maintain two
+files:
+- `revision.txt` -- the OpenCV's revision used to produce this source
+ copy. If the code was taken from `master`, a timestamp is stored
+ otherwise.
+- `checksum.txt` -- latest valid copy's check sum. Don't update this
+ file manually.
diff --git a/inference-engine/thirdparty/fluid/check.sh b/inference-engine/thirdparty/fluid/check.sh
new file mode 100644
index 000000000..e222af611
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/check.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+if [ ! -f modules ] && [ ! -f checksum.txt ]; then
+ exit 0
+fi
+
+THIS_HASH=$(./checksum.sh)
+OLD_HASH=$(cat checksum.txt)
+
+if [ $THIS_HASH != $OLD_HASH ]; then
+ echo "Invalid checksum -- any changes were done to the source tree here?"
+ exit 1
+fi
+
+echo "Check done."
diff --git a/inference-engine/thirdparty/fluid/checksum.sh b/inference-engine/thirdparty/fluid/checksum.sh
new file mode 100644
index 000000000..3c8236177
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/checksum.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+find modules/ -type f -exec md5sum {} \; | sort -k 2 | md5sum | cut -d' ' -f 1
diff --git a/inference-engine/thirdparty/fluid/checksum.txt b/inference-engine/thirdparty/fluid/checksum.txt
new file mode 100644
index 000000000..d912ec087
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/checksum.txt
@@ -0,0 +1 @@
+5d28798fbe1b11d9c9d6fcd28c02f07e
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/CMakeLists.txt b/inference-engine/thirdparty/fluid/modules/gapi/CMakeLists.txt
new file mode 100644
index 000000000..ec05b385c
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/CMakeLists.txt
@@ -0,0 +1,112 @@
+# FIXME: Rework standalone build in more generic maner
+# (Restructure directories, add common pass, etc)
+if (NOT DEFINED OPENCV_INITIAL_PASS)
+ include("cmake/standalone.cmake")
+ return()
+endif()
+
+# FIXME: Remove CXX11 check after complete switch to OpenCV 4 branch
+# (CI, bundle, workloads, etc)
+if (NOT HAVE_CXX11 OR NOT TARGET ade)
+ # can't build G-API because of the above reasons
+ ocv_module_disable(gapi)
+ return()
+endif()
+
+set(the_description "OpenCV G-API Core Module")
+ocv_add_module(gapi opencv_imgproc)
+
+file(GLOB gapi_ext_hdrs
+ "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/*.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/*.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/*.h"
+ "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/util/*.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/cpu/*.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/gpu/*.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/fluid/*.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/own/*.hpp"
+ )
+
+set(gapi_srcs
+ # Front-end part
+ src/api/gapi_priv.cpp
+ src/api/gmat.cpp
+ src/api/garray.cpp
+ src/api/gscalar.cpp
+ src/api/gkernel.cpp
+ src/api/gbackend.cpp
+ src/api/gproto.cpp
+ src/api/gnode.cpp
+ src/api/gcall.cpp
+ src/api/gcomputation.cpp
+ src/api/operators.cpp
+ src/api/kernels_core.cpp
+ src/api/kernels_imgproc.cpp
+
+ # Compiler part
+ src/compiler/gmodel.cpp
+ src/compiler/gmodelbuilder.cpp
+ src/compiler/gislandmodel.cpp
+ src/compiler/gcompiler.cpp
+ src/compiler/gcompiled.cpp
+ src/compiler/passes/helpers.cpp
+ src/compiler/passes/dump_dot.cpp
+ src/compiler/passes/islands.cpp
+ src/compiler/passes/meta.cpp
+ src/compiler/passes/kernels.cpp
+ src/compiler/passes/exec.cpp
+
+ # Executor
+ src/executor/gexecutor.cpp
+
+ # CPU Backend (currently built-in)
+ src/backends/cpu/gcpubackend.cpp
+ src/backends/cpu/gcpukernel.cpp
+ src/backends/cpu/gcpuimgproc.cpp
+ src/backends/cpu/gcpucore.cpp
+
+ # Fluid Backend (also built-in, FIXME:move away)
+ src/backends/fluid/gfluidbuffer.cpp
+ src/backends/fluid/gfluidbackend.cpp
+ src/backends/fluid/gfluidimgproc.cpp
+ src/backends/fluid/gfluidimgproc_func.dispatch.cpp
+ src/backends/fluid/gfluidcore.cpp
+
+ # GPU Backend (currently built-in)
+ src/backends/gpu/ggpubackend.cpp
+ src/backends/gpu/ggpukernel.cpp
+ src/backends/gpu/ggpuimgproc.cpp
+ src/backends/gpu/ggpucore.cpp
+
+ # Compound
+ src/backends/common/gcompoundbackend.cpp
+ src/backends/common/gcompoundkernel.cpp
+ )
+
+ocv_add_dispatched_file(backends/fluid/gfluidimgproc_func SSE4_1 AVX2)
+
+ocv_list_add_prefix(gapi_srcs "${CMAKE_CURRENT_LIST_DIR}/")
+
+# For IDE users
+ocv_source_group("Src" FILES ${gapi_srcs})
+ocv_source_group("Include" FILES ${gapi_ext_hdrs})
+
+ocv_set_module_sources(HEADERS ${gapi_ext_hdrs} SOURCES ${gapi_srcs})
+ocv_module_include_directories("${CMAKE_CURRENT_LIST_DIR}/src")
+
+# Note `ade` is not a module name but link dependency for ${the_module}
+# (which is opencv_gapi)
+ocv_create_module(ade)
+
+ocv_add_accuracy_tests()
+# FIXME: test binary is linked with ADE directly since ADE symbols
+# are not exported from libopencv_gapi.so in any form - thus
+# there're two copies of ADE code in memory when tests run (!)
+# src/ is specified to include dirs for INTERNAL tests only.
+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)
+endif()
+
+ocv_add_perf_tests()
+ocv_add_samples()
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/cmake/DownloadADE.cmake b/inference-engine/thirdparty/fluid/modules/gapi/cmake/DownloadADE.cmake
new file mode 100644
index 000000000..8b6f1176f
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/cmake/DownloadADE.cmake
@@ -0,0 +1,36 @@
+if(ANDROID)
+ # FIXME: Android build will be enabled separately
+ return()
+endif()
+
+set(ade_src_dir "${OpenCV_BINARY_DIR}/3rdparty/ade")
+set(ade_filename "v0.1.1d.zip")
+set(ade_subdir "ade-0.1.1d")
+set(ade_md5 "37479d90e3a5d47f132f512b22cbe206")
+ocv_download(FILENAME ${ade_filename}
+ HASH ${ade_md5}
+ URL
+ "${OPENCV_ADE_URL}"
+ "$ENV{OPENCV_ADE_URL}"
+ "https://github.com/opencv/ade/archive/"
+ DESTINATION_DIR ${ade_src_dir}
+ ID ADE
+ STATUS res
+ UNPACK RELATIVE_URL)
+
+if (NOT res)
+ return()
+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})
+target_include_directories(ade PUBLIC $<BUILD_INTERFACE:${ADE_root}/include>)
+set_target_properties(ade PROPERTIES POSITION_INDEPENDENT_CODE True)
+
+if(NOT BUILD_SHARED_LIBS)
+ ocv_install_target(ade EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)
+endif()
+
+ocv_install_3rdparty_licenses(ade "${ade_src_dir}/${ade_subdir}/LICENSE")
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/cmake/init.cmake b/inference-engine/thirdparty/fluid/modules/gapi/cmake/init.cmake
new file mode 100644
index 000000000..9f6ebeff4
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/cmake/init.cmake
@@ -0,0 +1,11 @@
+if (ade_DIR)
+ # if ade_DIR is set, use ADE-supplied CMake script
+ # to set up variables to the prebuilt ADE
+ find_package(ade 0.1.0)
+endif()
+
+if(NOT TARGET ade)
+ # if ade_DIR is not set, try to use automatically
+ # downloaded one (if there any)
+ include("${CMAKE_CURRENT_LIST_DIR}/DownloadADE.cmake")
+endif()
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/cmake/standalone.cmake b/inference-engine/thirdparty/fluid/modules/gapi/cmake/standalone.cmake
new file mode 100644
index 000000000..dd6e8cc00
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/cmake/standalone.cmake
@@ -0,0 +1,34 @@
+if (NOT TARGET ade )
+ find_package(ade 0.1.0 REQUIRED)
+endif()
+
+set(FLUID_TARGET fluid)
+set(FLUID_ROOT "${CMAKE_CURRENT_LIST_DIR}/../")
+
+file(GLOB FLUID_includes "${FLUID_ROOT}/include/opencv2/*.hpp"
+ "${FLUID_ROOT}/include/opencv2/gapi/g*.hpp"
+ "${FLUID_ROOT}/include/opencv2/gapi/util/*.hpp"
+ "${FLUID_ROOT}/include/opencv2/gapi/own/*.hpp"
+ "${FLUID_ROOT}/include/opencv2/gapi/fluid/*.hpp")
+file(GLOB FLUID_sources "${FLUID_ROOT}/src/api/g*.cpp"
+ "${FLUID_ROOT}/src/compiler/*.cpp"
+ "${FLUID_ROOT}/src/compiler/passes/*.cpp"
+ "${FLUID_ROOT}/src/executor/*.cpp"
+ "${FLUID_ROOT}/src/backends/fluid/*.cpp"
+ "${FLUID_ROOT}/src/backends/common/*.cpp")
+
+add_library(${FLUID_TARGET} STATIC ${FLUID_includes} ${FLUID_sources})
+
+target_include_directories(${FLUID_TARGET}
+ PUBLIC $<BUILD_INTERFACE:${FLUID_ROOT}/include>
+ PRIVATE ${FLUID_ROOT}/src)
+
+target_compile_definitions(${FLUID_TARGET} PUBLIC -DGAPI_STANDALONE
+# This preprocessor definition resolves symbol clash when
+# standalone fluid meets gapi ocv module in one application
+ PUBLIC cv=fluidcv)
+
+set_target_properties(${FLUID_TARGET} PROPERTIES POSITION_INDEPENDENT_CODE True)
+set_property(TARGET ${FLUID_TARGET} PROPERTY CXX_STANDARD 11)
+
+target_link_libraries(${FLUID_TARGET} PRIVATE ade)
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/doc/00-root.markdown b/inference-engine/thirdparty/fluid/modules/gapi/doc/00-root.markdown
new file mode 100644
index 000000000..bbc90ab44
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/doc/00-root.markdown
@@ -0,0 +1,113 @@
+# Graph API {#gapi}
+
+# Introduction {#gapi_root_intro}
+
+OpenCV Graph API (or G-API) is a new OpenCV module targeted to make
+regular image processing fast and portable. These two goals are
+achieved by introducing a new graph-based model of execution.
+
+G-API is a special module in OpenCV -- in contrast with the majority
+of other main modules, this one acts as a framework rather than some
+specific CV algorithm. G-API provides means to define CV operations,
+construct graphs (in form of expressions) using it, and finally
+implement and run the operations for a particular backend.
+
+@note G-API is a new module and now is in active development. It's API
+is volatile at the moment and there may be minor but
+compatibility-breaking changes in the future.
+
+# Contents
+
+G-API documentation is organized into the following chapters:
+
+- @subpage gapi_purposes
+
+ The motivation behind G-API and its goals.
+
+- @subpage gapi_hld
+
+ General overview of G-API architecture and its major internal
+ components.
+
+- @subpage gapi_kernel_api
+
+ Learn how to introduce new operations in G-API and implement it for
+ various backends.
+
+- @subpage gapi_impl
+
+ Low-level implementation details of G-API, for those who want to
+ contribute.
+
+- API Reference: functions and classes
+
+ - @subpage gapi_core
+
+ Core G-API operations - arithmetic, boolean, and other matrix
+ operations;
+
+ - @subpage gapi_imgproc
+
+ Image processing functions: color space conversions, various
+ filters, etc.
+
+# API Example {#gapi_example}
+
+A very basic example of G-API pipeline is shown below:
+
+@include modules/gapi/samples/api_example.cpp
+
+<!-- TODO align this code with text using marks and itemized list -->
+
+G-API is a separate OpenCV module so its header files have to be
+included explicitly. The first four lines of `main()` create and
+initialize OpenCV's standard video capture object, which fetches
+video frames from either an attached camera or a specified file.
+
+G-API pipelie is constructed next. In fact, it is a series of G-API
+operation calls on cv::GMat data. The important aspect of G-API is
+that this code block is just a declaration of actions, but not the
+actions themselves. No processing happens at this point, G-API only
+tracks which operations form pipeline and how it is connected. G-API
+_Data objects_ (here it is cv::GMat) are used to connect operations
+each other. `in` is an _empty_ cv::GMat signalling that it is a
+beginning of computation.
+
+After G-API code is written, it is captured into a call graph with
+instantiation of cv::GComputation object. This object takes
+input/output data references (in this example, `in` and `out`
+cv::GMat objects, respectively) as parameters and reconstructs the
+call graph based on all the data flow between `in` and `out`.
+
+cv::GComputation is a thin object in sense that it just captures which
+operations form up a computation. However, it can be used to execute
+computations -- in the following processing loop, every captured frame (a
+cv::Mat `input_frame`) is passed to cv::GComputation::apply().
+
+![Example pipeline running on sample video 'vtest.avi'](pics/demo.jpg)
+
+cv::GComputation::apply() is a polimorphic method which accepts a
+variadic number of arguments. Since this computation is defined on one
+input, one output, a special overload of cv::GComputation::apply() is
+used to pass input data and get output data.
+
+Internally, cv::GComputation::apply() compiles the captured graph for
+the given input parameters and executes the compiled graph on data
+immediately.
+
+There is a number important concepts can be outlines with this examle:
+* Graph declaration and graph execution are distinct steps;
+* Graph is built implicitly from a sequence of G-API expressions;
+* G-API supports function-like calls -- e.g. cv::gapi::resize(), and
+ operators, e.g operator|() which is used to compute bitwise OR;
+* G-API syntax aims to look pure: every operation call within a graph
+ yields a new result, thus forming a directed acyclic graph (DAG);
+* Graph declaration is not bound to any data -- real data objects
+ (cv::Mat) come into picture after the graph is already declared.
+
+<!-- FIXME: The above operator|() link links to MatExpr not GAPI -->
+
+See [tutorials and porting examples](@ref tutorial_table_of_content_gapi)
+to learn more on various G-API features and concepts.
+
+<!-- TODO Add chapter on declaration, compilation, execution -->
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/doc/01-background.markdown b/inference-engine/thirdparty/fluid/modules/gapi/doc/01-background.markdown
new file mode 100644
index 000000000..65983cd7a
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/doc/01-background.markdown
@@ -0,0 +1,76 @@
+# Why Graph API? {#gapi_purposes}
+
+# Motivation behind G-API {#gapi_intro_why}
+
+G-API module brings graph-based model of execution to OpenCV. This
+chapter briefly describes how this new model can help software
+developers in two aspects: optimizing and porting image processing
+algorithms.
+
+## Optimizing with Graph API {#gapi_intro_opt}
+
+Traditionally OpenCV provided a lot of stand-alone image processing
+functions (see modules `core` and `imgproc`). Many of that functions
+are well-optimized (e.g. vectorized for specific CPUs, parallel, etc)
+but still the out-of-box optimization scope has been limited to a
+single function only -- optimizing the whole algorithm built atop of that
+functions was a responsibility of a programmer.
+
+OpenCV 3.0 introduced _Transparent API_ (or _T-API_) which allowed to
+offload OpenCV function calls transparently to OpenCL devices and save
+on Host/Device data transfers with cv::UMat -- and it was a great step
+forward. However, T-API is a dynamic API -- user code still remains
+unconstrained and OpenCL kernels are enqueued in arbitrary order, thus
+eliminating further pipeline-level optimization potential.
+
+G-API brings implicit graph model to OpenCV 4.0. Graph model captures
+all operations and its data dependencies in a pipeline and so provides
+G-API framework with extra information to do pipeline-level
+optimizations.
+
+The cornerstone of graph-based optimizations is _Tiling_. Tiling
+allows to break the processing into smaller parts and reorganize
+operations to enable data parallelism, improve data locality, and save
+memory footprint. Data locality is an especially important aspect of
+software optimization due to diffent costs of memory access on modern
+computer architectures -- the more data is reused in the first level
+cache, the more efficient pipeline is.
+
+Definitely the aforementioned techinques can be applied manually --
+but it requires extra skills and knowledge of the target platform and
+the algorithm implementation changes irrevocably -- becoming more
+specific, less flexible, and harder to extend and maintain.
+
+G-API takes this responsiblity and complexity from user and does the
+majority of the work by itself, keeping the algorithm code clean from
+device or optimization details. This approach has its own limitations,
+though, as graph model is a _constrained_ model and not every
+algorithm can be represented as a graph, so the G-API scope is limited
+only to regular image processing -- various filters, arithmentic,
+binary operations, and well-defined geometrical transformations.
+
+## Porting with Graph API {#gapi_intro_port}
+
+The essense of G-API is declaring a sequence of operations to run, and
+then executing that sequence. G-API is a constrained API, so it puts a
+number of limitations on which operations can form a pipeline and
+which data these operations may exchange each other.
+
+This formalization in fact helps to make an algorithm portable. G-API
+clearly separates operation _interfaces_ from its _implementations_.
+
+One operation (_kernel_) may have multiple implementations even for a
+single device (e.g., OpenCV-based "reference" implementation and a
+tiled optimized implementation, both running on CPU). Graphs (or
+_Computations_ in G-API terms) are built only using operation
+interfaces, not implementations -- thus the same graph can be executed
+on different devices (and, of course, using different optimization
+techniques) with little-to-no changes in the graph itself.
+
+G-API supports plugins (_Backends_) which aggreate logic and
+intelligence on what is the best way to execute on a particular
+platform. Once a pipeline is built with G-API, it can be parametrized
+to use either of the backends (or a combination of it) and so a graph
+can be ported easily to a new platform.
+
+@sa @ref gapi_hld
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/doc/10-hld-overview.md b/inference-engine/thirdparty/fluid/modules/gapi/doc/10-hld-overview.md
new file mode 100644
index 000000000..1dc5b505d
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/doc/10-hld-overview.md
@@ -0,0 +1,159 @@
+# High-level design overview {#gapi_hld}
+
+# G-API High-level design overview
+
+[TOC]
+
+G-API is a heterogeneous framework and provides single API to program
+image processing pipelines with a number of supported backends.
+
+The key design idea is to keep pipeline code itself platform-neutral
+while specifying which kernels to use and which devices to utilize
+using extra parameters at graph compile (configuration) time. This
+requirement has led to the following architecture:
+
+<!-- FIXME: Render from dot directly -->
+
+![G-API framework architecture](pics/gapi_scheme.png)
+
+There are three layers in this architecture:
+* **API Layer** -- this is the top layer, which implements G-API
+ public interface, its building blocks and semantics.
+ When user constructs a pipeline with G-API, he interacts with this
+ layer directly, and the entities the user operates on (like cv::GMat
+ or cv::GComputation) are provided by this layer.
+* **Graph Compiler Layer** -- this is the intermediate layer which
+ unrolls user computation into a graph and then applies a number of
+ transformations to it (e.g. optimizations). This layer is built atop
+ of [ADE Framework](@ref gapi_detail_ade).
+* **Backends Layer** -- this is the lowest level layer, which lists a
+ number of _Backends_. In contrast with the above two layers,
+ backends are highly coupled with low-level platform details, with
+ every backend standing for every platform. A backend operates on a
+ processed graph (coming from the graph compiler) and executes this
+ graph optimally for a specific platform or device.
+
+# API layer {#gapi_api_layer}
+
+API layer is what user interacts with when defining and using a
+pipeline (a Computation in G-API terms). API layer defines a set of
+G-API _dynamic_ objects which can be used as inputs, outputs, and
+intermediate data objects within a graph:
+* cv::GMat
+* cv::GScalar
+* cv::GArray (template class)
+
+API layer specifies a list of Operations which are defined on these
+data objects -- so called kernels. See G-API [core](@ref gapi_core)
+and [imgproc](@ref gapi_imgproc) namespaces for details on which
+operations G-API provides by default.
+
+G-API is not limited to these operations only -- users can define
+their own kernels easily using a special macro G_TYPED_KERNEL().
+
+API layer is also responsible for marshalling and storing operation
+parameters on pipeline creation. In addition to the aforementioned
+G-API dynamic objects, operations may also accept arbitrary
+parameters (more on this [below](@ref gapi_detail_params)), so API
+layer captures its values and stores internally upon the moment of
+execution.
+
+Finally, cv::GComputation and cv::GCompiled are the remaining
+important components of API layer. The former wraps a series of G-API
+expressions into an object (graph), and the latter is a product of
+graph _compilation_ (see [this chapter](@ref gapi_detail_compiler) for
+details).
+
+# Graph compiler layer {#gapi_compiler}
+
+Every G-API computation is compiled before it executes. Compilation
+process is triggered in two ways:
+* _implicitly_, when cv::GComputation::apply() is used. In this case,
+ graph compilation is then immediately followed by execution.
+* _explicitly_, when cv::GComputation::compile() is used. In this case,
+ a cv::GCompiled object is returned which then can be invoked as a
+ C++ functor.
+
+The first way is recommended for cases when input data format is not
+known in advance -- e.g. when it comes from an arbitrary input file.
+The second way is recommended for deployment (production) scenarios
+where input data characteristics are usually predefined.
+
+Graph compilation process is built atop of ADE Framework. Initially, a
+bipartite graph is generated from expressions captured by API layer.
+This graph contains nodes of two types: _Data_ and _Operations_. Graph
+always starts and ends with a Data node(s), with Operations nodes
+in-between. Every Operation node has inputs and outputs, both are Data
+nodes.
+
+After the initial graph is generated, it is actually processed by a
+number of graph transformations, called _passes_. ADE Framework acts
+as a compiler pass management engine, and passes are written
+specifically for G-API.
+
+There are different passes which check graph validity, refine details
+on operations and data, organize nodes into clusters ("Islands") based
+on affinity or user-specified regioning[TBD], and more. Backends also
+are able to inject backend-specific passes into the compilation
+process, see more on this in the [dedicated chapter](@ref gapi_detail_meta).
+
+Result of graph compilation is a compiled object, represented by class
+cv::GCompiled. A new cv::GCompiled object is always created regardless
+if there was an explicit or implicit compilation request (see
+above). Actual graph execution happens within cv::GCompiled and is
+determined by backends which participated in the graph compilation.
+
+@sa cv::GComputation::apply(), cv::GComputation::compile(), cv::GCompiled
+
+# Backends layer {#gapi_backends}
+
+The above diagram lists two backends, _OpenCV_ and _Fluid_. _OpenCV_
+is so-called "reference backend", which implements G-API operations
+using plain old OpenCV functions. This backend is useful for
+prototyping on a familiar development system. _Fluid_ is a plugin for
+cache-efficient execution on CPU -- it implements a different
+execution policy and operates with its own, special kernels. Fluid
+backend allows to achieve less memory footprint and better memory
+locality when running on CPU.
+
+There may be more backends available, e.g. Halide, OpenCL, etc. --
+G-API provides an uniform internal API to develop backends so any
+enthusiast or a company are free to scale G-API on a new platform or
+accelerator. In terms of OpenCV infrastructure, every new backend is a
+new distinct OpenCV module, which extends G-API when build as a part
+of OpenCV.
+
+# Graph execution {#gapi_compiled}
+
+The way graph executed is defined by backends selected for
+compilation. In fact, every backend builds its own execution script as
+the final stage of graph compilation process, when an executable
+(compiled) object is being generated. For example, in OpenCV backend,
+this script is just a topologically-sorted sequence of OpenCV
+functions to call; for Fluid backend, it is a similar thing -- a
+topologically sorted list of _Agents_ processing lines of input on
+every iteration.
+
+Graph execution is triggered in two ways:
+* via cv::GComputation::apply(), with graph compiled in-place exactly
+ for the given input data;
+* via cv::GCompiled::operator()(), when the graph has been precompiled.
+
+Both methods are polimorphic and take a variadic number of arguments,
+with validity checks performed in runtime. If a number, shapes, and
+formats of passed data objects differ from expected, a run-time
+exception is thrown. G-API also provides _typed_ wrappers to move
+these checks to the compile time -- see cv::GComputationT<>.
+
+G-API graph execution is declared stateless -- it means that a
+compiled functor (cv::GCompiled) acts like a pure C++ function and
+provides the same result for the same set of input arguments.
+
+Both execution methods take \f$N+M\f$ parameters, where \f$N\f$ is a
+number of inputs, and \f$M\f$ is a number of outputs on which a
+cv::GComputation is defined. Note that while G-API types (cv::GMat,
+etc) are used in definition, the execution methods accept OpenCV's
+traditional data types (like cv::Mat) which hold actual data -- see
+table in [parameter marshalling](@#gapi_detail_params).
+
+@sa @ref gapi_impl, @ref gapi_kernel_api
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/doc/20-kernel-api.markdown b/inference-engine/thirdparty/fluid/modules/gapi/doc/20-kernel-api.markdown
new file mode 100644
index 000000000..93b852f6a
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/doc/20-kernel-api.markdown
@@ -0,0 +1,170 @@
+# Kernel API {#gapi_kernel_api}
+
+[TOC]
+
+# G-API Kernel API
+
+The core idea behind G-API is portability -- a pipeline built with
+G-API must be portable (or at least able to be portable). It means
+that either it works out-of-the box when compiled for new platform,
+_or_ G-API provides necessary tools to make it running there, with
+little-to-no changes in the algorithm itself.
+
+This idea can be achieved by separating kernel interface from its
+implementation. Once a pipeline is built using kernel interfaces, it
+becomes implementation-neutral -- the implementation details
+(i.e. which kernels to use) are passed on a separate stage (graph
+compilation).
+
+Kernel-implementation hierarchy may look like:
+
+![Kernel API/implementation hierarchy example](pics/kernel_hierarchy.png)
+
+A pipeline itself then can be expressed only in terms of `A`, `B`, and
+so on, and choosing which implementation to use in execution becomes
+an external parameter.
+
+# Defining a kernel {#gapi_defining_kernel}
+
+G-API provides a macro to define a new kernel interface --
+G_TYPED_KERNEL():
+
+@snippet modules/gapi/samples/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
+(see [below](@ref gapi_kernel_supp_info)). The macro arguments are:
+1. Kernel interface name -- also serves as a name of new type defined
+ with this macro;
+2. Kernel signature -- an `std::function<>`-like signature which defines
+ API of the kernel;
+3. Kernel's unique name -- used to identify kernel when its type
+ informattion is stripped within the system.
+
+Kernel declaration may be seen as function declaration -- in both cases
+a new entity must be used then according to the way it was defined.
+
+Kernel signature defines kernel's usage syntax -- which parameters
+it takes during graph construction. Implementations can also use this
+signature to derive it into backend-specific callback signatures (see
+next chapter).
+
+Kernel may accept values of any type, and G-API _dynamic_ types are
+handled in a special way. All other types are opaque to G-API and
+passed to kernel in `outMeta()` or in execution callbacks as-is.
+
+Kernel's return value can _only_ be of G-API dynamic type -- cv::GMat,
+cv::GScalar, or cv::GArray<T>. If an operation has more than one output,
+it should be wrapped into an `std::tuple<>` (which can contain only
+mentioned G-API types). Arbitrary-output-number operations are not
+supported.
+
+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
+
+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
+
+so now it can be used like:
+
+@snippet modules/gapi/samples/kernel_api_snippets.cpp filter2d_wrap_call
+
+# Extra information {#gapi_kernel_supp_info}
+
+In the current version, kernel declaration body (everything within the
+curly braces) must contain a static function `outMeta()`. This function
+establishes a functional dependency between operation's input and
+output metadata.
+
+_Metadata_ is an information about data kernel operates on. Since
+non-G-API types are opaque to G-API, G-API cares only about `G*` data
+descriptors (i.e. dimensions and format of cv::GMat, etc).
+
+`outMeta()` is also an example of how kernel's signature can be
+transformed into a derived callback -- note that in this example,
+`outMeta()` signature exactly follows the kernel signature (defined
+within the macro) but is different -- where kernel expects cv::GMat,
+`outMeta()` takes and returns cv::GMatDesc (a G-API structure metadata
+for cv::GMat).
+
+The point of `outMeta()` is to propagate metadata information within
+computation from inputs to outputs and infer metadata of internal
+(intermediate, temporary) data objects. This information is required
+for further pipeline optimizations, memory allocation, and other
+operations done by G-API framework during graph compilation.
+
+<!-- TODO add examples -->
+
+# Implementing a kernel {#gapi_kernel_implementing}
+
+Once a kernel is declared, its interface can be used to implement
+versions of this kernel in different backends. This concept is
+naturally projected from object-oriented programming
+"Interface/Implementation" idiom: an interface can be implemented
+multiple times, and different implementations of a kernel should be
+substitutable with each other without breaking the algorithm
+(pipeline) logic (Liskov Substitution Principle).
+
+Every backend defines its own way to implement a kernel interface.
+This way is regular, though -- whatever plugin is, its kernel
+implementation must be "derived" from a kernel interface type.
+
+Kernel implementation are then organized into _kernel
+packages_. Kernel packages are passed to cv::GComputation::compile()
+as compile arguments, with some hints to G-API on how to select proper
+kernels (see more on this in "Heterogeneity"[TBD]).
+
+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
+
+Note how CPU (OpenCV) plugin has transformed the original kernel
+signature:
+- Input cv::GMat has been substituted with cv::Mat, holding actual input
+ data for the underlying OpenCV function call;
+- Output cv::GMat has been transformed into extra output parameter, thus
+ `GCPUFilter2D::run()` takes one argument more than the original
+ kernel signature.
+
+The basic intuition for kernel developer here is _not to care_ where
+that cv::Mat objects come from instead of the original cv::GMat -- and
+just follow the signature conventions defined by the plugin. G-API
+will call this method during execution and supply all the necessary
+information (and forward the original opaque data as-is).
+
+# Compound kernels
+
+Sometimes kernel is a single thing only on API level. It is convenient
+for users, but on a particular implementation side it would be better to
+have multiple kernels (a subgraph) doing the thing instead. An example
+is goodFeaturesToTrack() -- while in OpenCV backend it may remain a
+single kernel, with Fluid it becomes compound -- Fluid can handle Harris
+response calculation but can't do sparse non-maxima suppression and
+point extraction to an STL vector:
+
+<!-- PIC -->
+
+A compound kernel _implementation_ can be defined using a generic
+macro GAPI_COMPOUND_KERNEL():
+
+@snippet modules/gapi/samples/kernel_api_snippets.cpp compound
+
+<!-- TODO: ADD on how Compound kernels may simplify dispatching -->
+<!-- TODO: Add details on when expand() is called! -->
+
+It is important to distinguish a compound kernel from G-API high-order
+function, i.e. a C++ function which looks like a kernel but in fact
+generates a subgraph. The core difference is that a compound kernel is
+an _implementation detail_ and a kernel implementation may be either
+compound or not (depending on backend capabilities), while a
+high-order function is a "macro" in terms of G-API and so cannot act as
+an interface which then needs to be implemented by a backend.
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/doc/30-implementation.markdown b/inference-engine/thirdparty/fluid/modules/gapi/doc/30-implementation.markdown
new file mode 100644
index 000000000..b1ad3bae9
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/doc/30-implementation.markdown
@@ -0,0 +1,27 @@
+# Implementation details {#gapi_impl}
+
+[TOC]
+
+# G-API Implementation details {#gapi_impl_header}
+
+## Api layer details {#gapi_detail_api}
+
+### Expression unrolling {#gapi_detail_expr}
+
+### Parameter marshalling {#gapi_detail_params}
+
+### Operations representation {#gapi_detail_operations}
+
+## Graph compiler details {#gapi_detail_compiler}
+
+### ADE basics {#gapi_detail_ade}
+
+### Graph model representation {#gapi_detail_gmodel}
+
+### G-API metadata and passes {#gapi_detail_meta}
+
+## Backends details {#gapi_detail_backends}
+
+### Backend scope of work {#gapi_backend_scope}
+
+### Graph transformation {#gapi_backend_pass}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/doc/dot/kernel_hierarchy.dot b/inference-engine/thirdparty/fluid/modules/gapi/doc/dot/kernel_hierarchy.dot
new file mode 100644
index 000000000..0eb92bc40
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/doc/dot/kernel_hierarchy.dot
@@ -0,0 +1,17 @@
+digraph {
+ rankdir=BT;
+ node [shape=record];
+
+ ki_a [label="{<f0> interface\nA}"];
+ ki_b [label="{<f0> interface\nB}"];
+
+ {rank=same; ki_a ki_b};
+
+ "CPU::A" -> ki_a [dir="forward"];
+ "OpenCL::A" -> ki_a [dir="forward"];
+ "Halide::A" -> ki_a [dir="forward"];
+
+ "CPU::B" -> ki_b [dir="forward"];
+ "OpenCL::B" -> ki_b [dir="forward"];
+ "Halide::B" -> ki_b [dir="forward"];
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/doc/pics/demo.jpg b/inference-engine/thirdparty/fluid/modules/gapi/doc/pics/demo.jpg
new file mode 100644
index 000000000..742d135f7
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/doc/pics/demo.jpg
Binary files differ
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/doc/pics/gapi_scheme.png b/inference-engine/thirdparty/fluid/modules/gapi/doc/pics/gapi_scheme.png
new file mode 100644
index 000000000..24271e322
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/doc/pics/gapi_scheme.png
Binary files differ
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/doc/pics/kernel_hierarchy.png b/inference-engine/thirdparty/fluid/modules/gapi/doc/pics/kernel_hierarchy.png
new file mode 100644
index 000000000..631f4a10d
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/doc/pics/kernel_hierarchy.png
Binary files differ
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi.hpp
new file mode 100644
index 000000000..a043a83fc
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi.hpp
@@ -0,0 +1,33 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_HPP
+#define OPENCV_GAPI_HPP
+
+#include <memory>
+
+/** \defgroup gapi G-API framework
+@{
+ @defgroup gapi_main_classes G-API Main Classes
+ @defgroup gapi_data_objects G-API Data Objects
+ @{
+ @defgroup gapi_meta_args G-API Metadata Descriptors
+ @}
+ @defgroup gapi_std_backends G-API Standard backends
+ @defgroup gapi_compile_args G-API Graph Compilation Arguments
+@}
+ */
+
+#include "opencv2/gapi/gmat.hpp"
+#include "opencv2/gapi/garray.hpp"
+#include "opencv2/gapi/gcomputation.hpp"
+#include "opencv2/gapi/gcompiled.hpp"
+#include "opencv2/gapi/gtyped.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+#include "opencv2/gapi/operators.hpp"
+
+#endif // OPENCV_GAPI_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/core.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/core.hpp
new file mode 100644
index 000000000..9af3620fe
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/core.hpp
@@ -0,0 +1,1600 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_CORE_HPP
+#define OPENCV_GAPI_CORE_HPP
+
+#include <utility> // std::tuple
+
+#include <opencv2/imgproc.hpp>
+
+#include "opencv2/gapi/gmat.hpp"
+#include "opencv2/gapi/gscalar.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+
+/** \defgroup gapi_core G-API core (basic) functionality
+@{
+ @defgroup gapi_math Graph API: Math operations
+ @defgroup gapi_pixelwise Graph API: Pixelwise operations
+ @defgroup gapi_matrixop Graph API: Operations on matrices
+ @defgroup gapi_transform Graph API: Geometric, depth and LUT-like image transformations
+@}
+ */
+namespace cv { namespace gapi {
+namespace core {
+ using GMat2 = std::tuple<GMat,GMat>;
+ using GMat3 = std::tuple<GMat,GMat,GMat>; // FIXME: how to avoid this?
+ using GMat4 = std::tuple<GMat,GMat,GMat,GMat>;
+ using GMatScalar = std::tuple<GMat, GScalar>;
+
+ G_TYPED_KERNEL(GAdd, <GMat(GMat, GMat, int)>, "org.opencv.core.math.add") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc b, int ddepth) {
+ if (ddepth == -1)
+ {
+ // OpenCV: When the input arrays in add/subtract/multiply/divide
+ // functions have different depths, the output array depth must be
+ // explicitly specified!
+ // See artim_op() @ arithm.cpp
+ GAPI_Assert(a.chan == b.chan);
+ GAPI_Assert(a.depth == b.depth);
+ return a;
+ }
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GAddC, <GMat(GMat, GScalar, int)>, "org.opencv.core.math.addC") {
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc, int ddepth) {
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GSub, <GMat(GMat, GMat, int)>, "org.opencv.core.math.sub") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc b, int ddepth) {
+ if (ddepth == -1)
+ {
+ // This macro should select a larger data depth from a and b
+ // considering the number of channels in the same
+ // FIXME!!! Clarify if it is valid for sub()
+ GAPI_Assert(a.chan == b.chan);
+ ddepth = std::max(a.depth, b.depth);
+ }
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GSubC, <GMat(GMat, GScalar, int)>, "org.opencv.core.math.subC") {
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc, int ddepth) {
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GSubRC,<GMat(GScalar, GMat, int)>, "org.opencv.core.math.subRC") {
+ static GMatDesc outMeta(GScalarDesc, GMatDesc b, int ddepth) {
+ return b.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GMul, <GMat(GMat, GMat, double, int)>, "org.opencv.core.math.mul") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc, double, int ddepth) {
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GMulCOld, <GMat(GMat, double, int)>, "org.opencv.core.math.mulCOld") {
+ static GMatDesc outMeta(GMatDesc a, double, int ddepth) {
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GMulC, <GMat(GMat, GScalar, int)>, "org.opencv.core.math.mulC"){
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc, int ddepth) {
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GMulS, <GMat(GMat, GScalar)>, "org.opencv.core.math.muls") {
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a;
+ }
+ }; // FIXME: Merge with MulC
+
+ G_TYPED_KERNEL(GDiv, <GMat(GMat, GMat, double, int)>, "org.opencv.core.math.div") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc b, double, int ddepth) {
+ if (ddepth == -1)
+ {
+ GAPI_Assert(a.depth == b.depth);
+ return b;
+ }
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GDivC, <GMat(GMat, GScalar, double, int)>, "org.opencv.core.math.divC") {
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc, double, int ddepth) {
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GDivRC, <GMat(GScalar, GMat, double, int)>, "org.opencv.core.math.divRC") {
+ static GMatDesc outMeta(GScalarDesc, GMatDesc b, double, int ddepth) {
+ return b.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GMean, <GScalar(GMat)>, "org.opencv.core.math.mean") {
+ static GScalarDesc outMeta(GMatDesc) {
+ return empty_scalar_desc();
+ }
+ };
+
+ G_TYPED_KERNEL_M(GPolarToCart, <GMat2(GMat, GMat, bool)>, "org.opencv.core.math.polarToCart") {
+ static std::tuple<GMatDesc, GMatDesc> outMeta(GMatDesc, GMatDesc a, bool) {
+ return std::make_tuple(a, a);
+ }
+ };
+
+ G_TYPED_KERNEL_M(GCartToPolar, <GMat2(GMat, GMat, bool)>, "org.opencv.core.math.cartToPolar") {
+ static std::tuple<GMatDesc, GMatDesc> outMeta(GMatDesc x, GMatDesc, bool) {
+ return std::make_tuple(x, x);
+ }
+ };
+
+ G_TYPED_KERNEL(GPhase, <GMat(GMat, GMat, bool)>, "org.opencv.core.math.phase") {
+ static GMatDesc outMeta(const GMatDesc &inx, const GMatDesc &, bool) {
+ return inx;
+ }
+ };
+
+ G_TYPED_KERNEL(GMask, <GMat(GMat,GMat)>, "org.opencv.core.pixelwise.mask") {
+ static GMatDesc outMeta(GMatDesc in, GMatDesc) {
+ return in;
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpGT, <GMat(GMat, GMat)>, "org.opencv.core.pixelwise.compare.cmpGT") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpGE, <GMat(GMat, GMat)>, "org.opencv.core.pixelwise.compare.cmpGE") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpLE, <GMat(GMat, GMat)>, "org.opencv.core.pixelwise.compare.cmpLE") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpLT, <GMat(GMat, GMat)>, "org.opencv.core.pixelwise.compare.cmpLT") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpEQ, <GMat(GMat, GMat)>, "org.opencv.core.pixelwise.compare.cmpEQ") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpNE, <GMat(GMat, GMat)>, "org.opencv.core.pixelwise.compare.cmpNE") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpGTScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpGTScalar"){
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpGEScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpGEScalar"){
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpLEScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpLEScalar"){
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpLTScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpLTScalar"){
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpEQScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpEQScalar"){
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GCmpNEScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpNEScalar"){
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a.withDepth(CV_8U);
+ }
+ };
+
+ G_TYPED_KERNEL(GAnd, <GMat(GMat, GMat)>, "org.opencv.core.pixelwise.bitwise_and") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GAndS, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.bitwise_andS") {
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GOr, <GMat(GMat, GMat)>, "org.opencv.core.pixelwise.bitwise_or") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GOrS, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.bitwise_orS") {
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GXor, <GMat(GMat, GMat)>, "org.opencv.core.pixelwise.bitwise_xor") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GXorS, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.bitwise_xorS") {
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GNot, <GMat(GMat)>, "org.opencv.core.pixelwise.bitwise_not") {
+ static GMatDesc outMeta(GMatDesc a) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GSelect, <GMat(GMat, GMat, GMat)>, "org.opencv.core.pixelwise.select") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc, GMatDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GMin, <GMat(GMat, GMat)>, "org.opencv.core.matrixop.min") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GMax, <GMat(GMat, GMat)>, "org.opencv.core.matrixop.max") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GAbsDiff, <GMat(GMat, GMat)>, "org.opencv.core.matrixop.absdiff") {
+ static GMatDesc outMeta(GMatDesc a, GMatDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GAbsDiffC, <GMat(GMat, GScalar)>, "org.opencv.core.matrixop.absdiffC") {
+ static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
+ return a;
+ }
+ };
+
+ G_TYPED_KERNEL(GSum, <GScalar(GMat)>, "org.opencv.core.matrixop.sum") {
+ static GScalarDesc outMeta(GMatDesc) {
+ return empty_scalar_desc();
+ }
+ };
+
+ G_TYPED_KERNEL(GAddW, <GMat(GMat, double, GMat, double, double, int)>, "org.opencv.core.matrixop.addweighted") {
+ static GMatDesc outMeta(GMatDesc a, double, GMatDesc b, double, double, int ddepth) {
+ if (ddepth == -1)
+ {
+ // OpenCV: When the input arrays in add/subtract/multiply/divide
+ // functions have different depths, the output array depth must be
+ // explicitly specified!
+ // See artim_op() @ arithm.cpp
+ GAPI_Assert(a.chan == b.chan);
+ GAPI_Assert(a.depth == b.depth);
+ return a;
+ }
+ return a.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GNormL1, <GScalar(GMat)>, "org.opencv.core.matrixop.norml1") {
+ static GScalarDesc outMeta(GMatDesc) {
+ return empty_scalar_desc();
+ }
+ };
+
+ G_TYPED_KERNEL(GNormL2, <GScalar(GMat)>, "org.opencv.core.matrixop.norml2") {
+ static GScalarDesc outMeta(GMatDesc) {
+ return empty_scalar_desc();
+ }
+ };
+
+ G_TYPED_KERNEL(GNormInf, <GScalar(GMat)>, "org.opencv.core.matrixop.norminf") {
+ static GScalarDesc outMeta(GMatDesc) {
+ return empty_scalar_desc();
+ }
+ };
+
+ G_TYPED_KERNEL_M(GIntegral, <GMat2(GMat, int, int)>, "org.opencv.core.matrixop.integral") {
+ static std::tuple<GMatDesc, GMatDesc> outMeta(GMatDesc in, int sd, int sqd) {
+ return std::make_tuple(in.withSizeDelta(1,1).withDepth(sd),
+ in.withSizeDelta(1,1).withDepth(sqd));
+ }
+ };
+
+ G_TYPED_KERNEL(GThreshold, <GMat(GMat, GScalar, GScalar, int)>, "org.opencv.core.matrixop.threshold") {
+ static GMatDesc outMeta(GMatDesc in, GScalarDesc, GScalarDesc, int) {
+ return in;
+ }
+ };
+
+
+ G_TYPED_KERNEL_M(GThresholdOT, <GMatScalar(GMat, GScalar, int)>, "org.opencv.core.matrixop.thresholdOT") {
+ static std::tuple<GMatDesc,GScalarDesc> outMeta(GMatDesc in, GScalarDesc, int) {
+ return std::make_tuple(in, empty_scalar_desc());
+ }
+ };
+
+ G_TYPED_KERNEL(GInRange, <GMat(GMat, GScalar, GScalar)>, "org.opencv.core.matrixop.inrange") {
+ static GMatDesc outMeta(GMatDesc in, GScalarDesc, GScalarDesc) {
+ return in.withType(CV_8U, 1);
+ }
+ };
+
+ G_TYPED_KERNEL_M(GSplit3, <GMat3(GMat)>, "org.opencv.core.transform.split3") {
+ static std::tuple<GMatDesc, GMatDesc, GMatDesc> outMeta(GMatDesc in) {
+ const auto out_depth = in.depth;
+ const auto out_desc = in.withType(out_depth, 1);
+ return std::make_tuple(out_desc, out_desc, out_desc);
+ }
+ };
+
+ G_TYPED_KERNEL_M(GSplit4, <GMat4(GMat)>,"org.opencv.core.transform.split4") {
+ static std::tuple<GMatDesc, GMatDesc, GMatDesc, GMatDesc> outMeta(GMatDesc in) {
+ const auto out_depth = in.depth;
+ const auto out_desc = in.withType(out_depth, 1);
+ return std::make_tuple(out_desc, out_desc, out_desc, out_desc);
+ }
+ };
+
+ G_TYPED_KERNEL(GResize, <GMat(GMat,Size,double,double,int)>, "org.opencv.core.transform.resize") {
+ static GMatDesc outMeta(GMatDesc in, Size sz, double fx, double fy, int) {
+ if (sz.width != 0 && sz.height != 0)
+ {
+ return in.withSize(sz);
+ }
+ else
+ {
+ GAPI_Assert(fx != 0. && fy != 0.);
+ return in.withSize
+ (Size(static_cast<int>(std::round(in.size.width * fx)),
+ static_cast<int>(std::round(in.size.height * fy))));
+ }
+ }
+ };
+
+ G_TYPED_KERNEL(GMerge3, <GMat(GMat,GMat,GMat)>, "org.opencv.core.transform.merge3") {
+ static GMatDesc outMeta(GMatDesc in, GMatDesc, GMatDesc) {
+ // Preserve depth and add channel component
+ return in.withType(in.depth, 3);
+ }
+ };
+
+ G_TYPED_KERNEL(GMerge4, <GMat(GMat,GMat,GMat,GMat)>, "org.opencv.core.transform.merge4") {
+ static GMatDesc outMeta(GMatDesc in, GMatDesc, GMatDesc, GMatDesc) {
+ // Preserve depth and add channel component
+ return in.withType(in.depth, 4);
+ }
+ };
+
+ G_TYPED_KERNEL(GRemap, <GMat(GMat, Mat, Mat, int, int, Scalar)>, "org.opencv.core.transform.remap") {
+ static GMatDesc outMeta(GMatDesc in, Mat m1, Mat, int, int, Scalar) {
+ return in.withSize(m1.size());
+ }
+ };
+
+ G_TYPED_KERNEL(GFlip, <GMat(GMat, int)>, "org.opencv.core.transform.flip") {
+ static GMatDesc outMeta(GMatDesc in, int) {
+ return in;
+ }
+ };
+
+ G_TYPED_KERNEL(GCrop, <GMat(GMat, Rect)>, "org.opencv.core.transform.crop") {
+ static GMatDesc outMeta(GMatDesc in, Rect rc) {
+ return in.withSize(Size(rc.width, rc.height));
+ }
+ };
+
+ G_TYPED_KERNEL(GConcatHor, <GMat(GMat, GMat)>, "org.opencv.imgproc.transform.concatHor") {
+ static GMatDesc outMeta(GMatDesc l, GMatDesc r) {
+ return l.withSizeDelta(+r.size.width, 0);
+ }
+ };
+
+ G_TYPED_KERNEL(GConcatVert, <GMat(GMat, GMat)>, "org.opencv.imgproc.transform.concatVert") {
+ static GMatDesc outMeta(GMatDesc t, GMatDesc b) {
+ return t.withSizeDelta(0, +b.size.height);
+ }
+ };
+
+ G_TYPED_KERNEL(GLUT, <GMat(GMat, Mat)>, "org.opencv.core.transform.LUT") {
+ static GMatDesc outMeta(GMatDesc in, Mat) {
+ return in;
+ }
+ };
+
+ G_TYPED_KERNEL(GConvertTo, <GMat(GMat, int, double, double)>, "org.opencv.core.transform.convertTo") {
+ static GMatDesc outMeta(GMatDesc in, int rdepth, double, double) {
+ return rdepth < 0 ? in : in.withDepth(rdepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GSqrt, <GMat(GMat)>, "org.opencv.core.math.sqrt") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in;
+ }
+ };
+}
+
+//! @addtogroup gapi_math
+//! @{
+
+/** @brief Calculates the per-element sum of two matrices.
+
+The function add calculates sum of two matrices of the same size and the same number of channels:
+\f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1}(I) + \texttt{src2}(I)) \quad \texttt{if mask}(I) \ne0\f]
+
+The function can be replaced with matrix expressions:
+ \f[\texttt{dst} = \texttt{src1} + \texttt{src2}\f]
+
+The input matrices and the output matrix can all have the same or different depths. For example, you
+can add a 16-bit unsigned matrix to a 8-bit signed matrix and store the sum as a 32-bit
+floating-point matrix. Depth of the output matrix is determined by the ddepth parameter.
+If src1.depth() == src2.depth(), ddepth can be set to the default -1. In this case, the output matrix will have
+the same depth as the input matrices.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.add"
+@param src1 first input matrix.
+@param src2 second input matrix.
+@param ddepth optional depth of the output matrix.
+@sa sub, addWeighted
+*/
+GAPI_EXPORTS GMat add(const GMat& src1, const GMat& src2, int ddepth = -1);
+
+/** @brief Calculates the per-element sum of matrix and given scalar.
+
+The function addC adds a given scalar value to each element of given matrix.
+The function can be replaced with matrix expressions:
+
+ \f[\texttt{dst} = \texttt{src1} + \texttt{c}\f]
+
+Depth of the output matrix is determined by the ddepth parameter.
+If ddepth is set to default -1, the depth of output matrix will be the same as the depth of input matrix.
+The matrices can be single or multi channel. Output matrix must have the same size and number of channels as the input matrix.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.addC"
+@param src1 first input matrix.
+@param c scalar value to be added.
+@param ddepth optional depth of the output matrix.
+@sa sub, addWeighted
+*/
+GAPI_EXPORTS 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);
+
+/** @brief Calculates the per-element difference between two matrices.
+
+The function sub calculates difference between two matrices, when both matrices have the same size and the same number of
+channels:
+ \f[\texttt{dst}(I) = \texttt{src1}(I) - \texttt{src2}(I)\f]
+
+The function can be replaced with matrix expressions:
+\f[\texttt{dst} = \texttt{src1} - \texttt{src2}\f]
+
+The input matrices and the output matrix can all have the same or different depths. For example, you
+can subtract two 8-bit unsigned matrices store the result as a 16-bit signed matrix.
+Depth of the output matrix is determined by the ddepth parameter.
+If src1.depth() == src2.depth(), ddepth can be set to the default -1. In this case, the output matrix will have
+the same depth as the input matrices. The matrices can be single or multi channel.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.sub"
+@param src1 first input matrix.
+@param src2 second input matrix.
+@param ddepth optional depth of the output matrix.
+@sa add, addC
+ */
+GAPI_EXPORTS GMat sub(const GMat& src1, const GMat& src2, int ddepth = -1);
+
+/** @brief Calculates the per-element difference between matrix and given scalar.
+
+The function can be replaced with matrix expressions:
+ \f[\texttt{dst} = \texttt{src} - \texttt{c}\f]
+
+Depth of the output matrix is determined by the ddepth parameter.
+If ddepth is set to default -1, the depth of output matrix will be the same as the depth of input matrix.
+The matrices can be single or multi channel. Output matrix must have the same size as src.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.subC"
+@param src first input matrix.
+@param c scalar value to subtracted.
+@param ddepth optional depth of the output matrix.
+@sa add, addC, subRC
+ */
+GAPI_EXPORTS GMat subC(const GMat& src, const GScalar& c, int ddepth = -1);
+
+/** @brief Calculates the per-element difference between given scalar and the matrix.
+
+The function can be replaced with matrix expressions:
+ \f[\texttt{dst} = \texttt{val} - \texttt{src}\f]
+
+Depth of the output matrix is determined by the ddepth parameter.
+If ddepth is set to default -1, the depth of output matrix will be the same as the depth of input matrix.
+The matrices can be single or multi channel. Output matrix must have the same size as src.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.subRC"
+@param c scalar value to subtract from.
+@param src input matrix to be subtracted.
+@param ddepth optional depth of the output matrix.
+@sa add, addC, subC
+ */
+GAPI_EXPORTS GMat subRC(const GScalar& c, const GMat& src, int ddepth = -1);
+
+/** @brief Calculates the per-element scaled product of two matrices.
+
+The function mul calculates the per-element product of two matrices:
+
+\f[\texttt{dst} (I)= \texttt{saturate} ( \texttt{scale} \cdot \texttt{src1} (I) \cdot \texttt{src2} (I))\f]
+
+If src1.depth() == src2.depth(), ddepth can be set to the default -1. In this case, the output matrix will have
+the same depth as the input matrices. The matrices can be single or multi channel.
+Output matrix must have the same size as input matrices.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.mul"
+@param src1 first input matrix.
+@param src2 second input matrix of the same size and the same depth as src1.
+@param scale optional scale factor.
+@param ddepth optional depth of the output matrix.
+@sa add, sub, div, addWeighted
+*/
+GAPI_EXPORTS GMat mul(const GMat& src1, const GMat& src2, double scale = 1.0, int ddepth = -1);
+
+/** @brief Multiplies matrix by scalar.
+
+The function mulC multiplies each element of matrix src by given scalar value:
+
+\f[\texttt{dst} (I)= \texttt{saturate} ( \texttt{src1} (I) \cdot \texttt{multiplier} )\f]
+
+The matrices can be single or multi channel. Output matrix must have the same size as src.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.mulC"
+@param src input matrix.
+@param multiplier factor to be multiplied.
+@param ddepth optional depth of the output matrix. If -1, the depth of output matrix will be the same as input matrix depth.
+@sa add, sub, div, addWeighted
+*/
+GAPI_EXPORTS GMat mulC(const GMat& src, double multiplier, int ddepth = -1);
+//! @overload
+GAPI_EXPORTS GMat mulC(const GMat& src, const GScalar& multiplier, int ddepth = -1); // FIXME: merge with mulc
+//! @overload
+GAPI_EXPORTS GMat mulC(const GScalar& multiplier, const GMat& src, int ddepth = -1); // FIXME: merge with mulc
+
+/** @brief Performs per-element division of two matrices.
+
+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
+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.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.div"
+@param src1 first input matrix.
+@param src2 second input matrix of the same size and depth as src1.
+@param scale scalar factor.
+@param ddepth optional depth of the output matrix; you can only pass -1 when src1.depth() == src2.depth().
+@sa mul, add, sub
+*/
+GAPI_EXPORTS GMat div(const GMat& src1, const GMat& src2, double scale, int ddepth = -1);
+
+/** @brief Divides matrix by scalar.
+
+The function divC divides each element of matrix src by given scalar value:
+
+\f[\texttt{dst(I) = saturate(src(I)*scale/divisor)}\f]
+
+When divisor is zero, dst(I) will also be zero. 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.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.divC"
+@param src input matrix.
+@param divisor number to be divided by.
+@param ddepth optional depth of the output matrix. If -1, the depth of output matrix will be the same as input matrix depth.
+@param scale scale factor.
+@sa add, sub, div, addWeighted
+*/
+GAPI_EXPORTS GMat divC(const GMat& src, const GScalar& divisor, double scale, int ddepth = -1);
+
+/** @brief Divides scalar by matrix.
+
+The function divRC divides given scalar by each element of matrix src and keep the division result in new matrix of the same size and type as src:
+
+\f[\texttt{dst(I) = saturate(divident*scale/src(I))}\f]
+
+When src(I) is zero, dst(I) will also be zero. 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.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.divRC"
+@param src input matrix.
+@param divident number to be divided.
+@param ddepth optional depth of the output matrix. If -1, the depth of output matrix will be the same as input matrix depth.
+@param scale scale factor
+@sa add, sub, div, addWeighted
+*/
+GAPI_EXPORTS GMat divRC(const GScalar& divident, const GMat& src, double scale, int ddepth = -1);
+
+/** @brief Applies a mask to a matrix.
+
+The function mask set value from given matrix if the corresponding pixel value in mask matrix set to true,
+and set the matrix value to 0 overwise.
+
+Supported src matrix data types are @ref CV_8UC1, @ref CV_16SC1, @ref CV_16UC1. Supported mask data type is @ref CV_8UC1.
+
+@note Function textual ID is "org.opencv.core.math.mask"
+@param src input matrix.
+@param mask input mask matrix.
+*/
+GAPI_EXPORTS GMat mask(const GMat& src, const GMat& mask);
+
+/** @brief Calculates an average (mean) of matrix elements.
+
+The function mean calculates the mean value M of matrix elements,
+independently for each channel, and return it.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.math.mean"
+@param src input matrix.
+*/
+GAPI_EXPORTS GScalar mean(const GMat& src);
+
+/** @brief Calculates x and y coordinates of 2D vectors from their magnitude and angle.
+
+The function polarToCart calculates the Cartesian coordinates of each 2D
+vector represented by the corresponding elements of magnitude and angle:
+\f[\begin{array}{l} \texttt{x} (I) = \texttt{magnitude} (I) \cos ( \texttt{angle} (I)) \\ \texttt{y} (I) = \texttt{magnitude} (I) \sin ( \texttt{angle} (I)) \\ \end{array}\f]
+
+The relative accuracy of the estimated coordinates is about 1e-6.
+
+First output is a matrix of x-coordinates of 2D vectors.
+Second output is a matrix of y-coordinates of 2D vectors.
+Both output must have the same size and depth as input matrices.
+
+@note Function textual ID is "org.opencv.core.math.polarToCart"
+
+@param magnitude input floating-point @ref CV_32FC1 matrix (1xN) of magnitudes of 2D vectors;
+@param angle input floating-point @ref CV_32FC1 matrix (1xN) of angles of 2D vectors.
+@param angleInDegrees when true, the input angles are measured in
+degrees, otherwise, they are measured in radians.
+@sa cartToPolar, exp, log, pow, sqrt
+*/
+GAPI_EXPORTS std::tuple<GMat, GMat> polarToCart(const GMat& magnitude, const GMat& angle,
+ bool angleInDegrees = false);
+
+/** @brief Calculates the magnitude and angle of 2D vectors.
+
+The function cartToPolar calculates either the magnitude, angle, or both
+for every 2D vector (x(I),y(I)):
+\f[\begin{array}{l} \texttt{magnitude} (I)= \sqrt{\texttt{x}(I)^2+\texttt{y}(I)^2} , \\ \texttt{angle} (I)= \texttt{atan2} ( \texttt{y} (I), \texttt{x} (I))[ \cdot180 / \pi ] \end{array}\f]
+
+The angles are calculated with accuracy about 0.3 degrees. For the point
+(0,0), the angle is set to 0.
+
+First output is a matrix of magnitudes of the same size and depth as input x.
+Second output is a matrix of angles that has the same size and depth as
+x; the angles are measured in radians (from 0 to 2\*Pi) or in degrees (0 to 360 degrees).
+
+@note Function textual ID is "org.opencv.core.math.cartToPolar"
+
+@param x matrix of @ref CV_32FC1 x-coordinates.
+@param y array of @ref CV_32FC1 y-coordinates.
+@param angleInDegrees a flag, indicating whether the angles are measured
+in radians (which is by default), or in degrees.
+@sa polarToCart
+*/
+GAPI_EXPORTS std::tuple<GMat, GMat> cartToPolar(const GMat& x, const GMat& y,
+ bool angleInDegrees = false);
+
+/** @brief Calculates the rotation angle of 2D vectors.
+
+The function cv::phase calculates the rotation angle of each 2D vector that
+is formed from the corresponding elements of x and y :
+\f[\texttt{angle} (I) = \texttt{atan2} ( \texttt{y} (I), \texttt{x} (I))\f]
+
+The angle estimation accuracy is about 0.3 degrees. When x(I)=y(I)=0 ,
+the corresponding angle(I) is set to 0.
+@param x input floating-point array of x-coordinates of 2D vectors.
+@param y input array of y-coordinates of 2D vectors; it must have the
+same size and the same type as x.
+@param angleInDegrees when true, the function calculates the angle in
+degrees, otherwise, they are measured in radians.
+@return array of vector angles; it has the same size and same type as x.
+*/
+GAPI_EXPORTS GMat phase(const GMat& x, const GMat &y, bool angleInDegrees = false);
+
+/** @brief Calculates a square root of array elements.
+
+The function cv::gapi::sqrt calculates a square root of each input array element.
+In case of multi-channel arrays, each channel is processed
+independently. The accuracy is approximately the same as of the built-in
+std::sqrt .
+@param src input floating-point array.
+@return output array of the same size and type as src.
+*/
+GAPI_EXPORTS GMat sqrt(const GMat &src);
+
+//! @} gapi_math
+//!
+//! @addtogroup gapi_pixelwise
+//! @{
+
+/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are greater compare to elements in second.
+
+The function compares elements of two matrices src1 and src2 of the same size:
+ \f[\texttt{dst} (I) = \texttt{src1} (I) > \texttt{src2} (I)\f]
+
+When the comparison result is true, the corresponding element of output
+array is set to 255. The comparison operations can be replaced with the
+equivalent matrix expressions:
+\f[\texttt{dst} = \texttt{src1} > \texttt{src2}\f]
+
+Output matrix of depth @ref CV_8U must have the same size and the same number of channels as
+ the input matrices/matrix.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpGT"
+@param src1 first input matrix.
+@param src2 second input matrix/scalar of the same depth as first input matrix.
+@sa min, max, threshold, cmpLE, cmpGE, cmpLS
+*/
+GAPI_EXPORTS GMat cmpGT(const GMat& src1, const GMat& src2);
+/** @overload
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpGTScalar"
+*/
+GAPI_EXPORTS GMat cmpGT(const GMat& src1, const GScalar& src2);
+
+/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are less than elements in second.
+
+The function compares elements of two matrices src1 and src2 of the same size:
+ \f[\texttt{dst} (I) = \texttt{src1} (I) < \texttt{src2} (I)\f]
+
+When the comparison result is true, the corresponding element of output
+array is set to 255. The comparison operations can be replaced with the
+equivalent matrix expressions:
+ \f[\texttt{dst} = \texttt{src1} < \texttt{src2}\f]
+
+Output matrix of depth @ref CV_8U must have the same size and the same number of channels as
+ the input matrices/matrix.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLT"
+@param src1 first input matrix.
+@param src2 second input matrix/scalar of the same depth as first input matrix.
+@sa min, max, threshold, cmpLE, cmpGE, cmpGT
+*/
+GAPI_EXPORTS GMat cmpLT(const GMat& src1, const GMat& src2);
+/** @overload
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLTScalar"
+*/
+GAPI_EXPORTS GMat cmpLT(const GMat& src1, const GScalar& src2);
+
+/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are greater or equal compare to elements in second.
+
+The function compares elements of two matrices src1 and src2 of the same size:
+ \f[\texttt{dst} (I) = \texttt{src1} (I) >= \texttt{src2} (I)\f]
+
+When the comparison result is true, the corresponding element of output
+array is set to 255. The comparison operations can be replaced with the
+equivalent matrix expressions:
+ \f[\texttt{dst} = \texttt{src1} >= \texttt{src2}\f]
+
+Output matrix of depth @ref CV_8U must have the same size and the same number of channels as
+ the input matrices.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpGE"
+@param src1 first input matrix.
+@param src2 second input matrix/scalar of the same depth as first input matrix.
+@sa min, max, threshold, cmpLE, cmpGT, cmpLS
+*/
+GAPI_EXPORTS GMat cmpGE(const GMat& src1, const GMat& src2);
+/** @overload
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLGEcalar"
+*/
+GAPI_EXPORTS GMat cmpGE(const GMat& src1, const GScalar& src2);
+
+/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are less or equal compare to elements in second.
+
+The function compares elements of two matrices src1 and src2 of the same size:
+ \f[\texttt{dst} (I) = \texttt{src1} (I) <= \texttt{src2} (I)\f]
+
+When the comparison result is true, the corresponding element of output
+array is set to 255. The comparison operations can be replaced with the
+equivalent matrix expressions:
+ \f[\texttt{dst} = \texttt{src1} <= \texttt{src2}\f]
+
+Output matrix of depth @ref CV_8U must have the same size and the same number of channels as
+ the input matrices.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLE"
+@param src1 first input matrix.
+@param src2 second input matrix/scalar of the same depth as first input matrix.
+@sa min, max, threshold, cmpGT, cmpGE, cmpLS
+*/
+GAPI_EXPORTS GMat cmpLE(const GMat& src1, const GMat& src2);
+/** @overload
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpLEScalar"
+*/
+GAPI_EXPORTS GMat cmpLE(const GMat& src1, const GScalar& src2);
+
+/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are equal to elements in second.
+
+The function compares elements of two matrices src1 and src2 of the same size:
+ \f[\texttt{dst} (I) = \texttt{src1} (I) == \texttt{src2} (I)\f]
+
+When the comparison result is true, the corresponding element of output
+array is set to 255. The comparison operations can be replaced with the
+equivalent matrix expressions:
+ \f[\texttt{dst} = \texttt{src1} == \texttt{src2}\f]
+
+Output matrix of depth @ref CV_8U must have the same size and the same number of channels as
+ the input matrices.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpEQ"
+@param src1 first input matrix.
+@param src2 second input matrix/scalar of the same depth as first input matrix.
+@sa min, max, threshold, cmpNE
+*/
+GAPI_EXPORTS GMat cmpEQ(const GMat& src1, const GMat& src2);
+/** @overload
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpEQScalar"
+*/
+GAPI_EXPORTS GMat cmpEQ(const GMat& src1, const GScalar& src2);
+
+/** @brief Performs the per-element comparison of two matrices checking if elements from first matrix are not equal to elements in second.
+
+The function compares elements of two matrices src1 and src2 of the same size:
+ \f[\texttt{dst} (I) = \texttt{src1} (I) != \texttt{src2} (I)\f]
+
+When the comparison result is true, the corresponding element of output
+array is set to 255. The comparison operations can be replaced with the
+equivalent matrix expressions:
+ \f[\texttt{dst} = \texttt{src1} != \texttt{src2}\f]
+
+Output matrix of depth @ref CV_8U must have the same size and the same number of channels as
+ the input matrices.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpNE"
+@param src1 first input matrix.
+@param src2 second input matrix/scalar of the same depth as first input matrix.
+@sa min, max, threshold, cmpEQ
+*/
+GAPI_EXPORTS GMat cmpNE(const GMat& src1, const GMat& src2);
+/** @overload
+@note Function textual ID is "org.opencv.core.pixelwise.compare.cmpNEScalar"
+*/
+GAPI_EXPORTS GMat cmpNE(const GMat& src1, const GScalar& src2);
+
+/** @brief computes bitwise conjunction of the two matrixes (src1 & src2)
+Calculates the per-element bit-wise logical conjunction of two matrices of the same size.
+
+In case of floating-point matrices, their machine-specific bit
+representations (usually IEEE754-compliant) are used for the operation.
+In case of multi-channel matrices, each channel is processed
+independently. Output matrix must have the same size and depth as the input
+matrices.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.bitwise_and"
+
+@param src1 first input matrix.
+@param src2 second input matrix.
+*/
+GAPI_EXPORTS GMat bitwise_and(const GMat& src1, const GMat& src2);
+/** @overload
+@note Function textual ID is "org.opencv.core.pixelwise.compare.bitwise_andS"
+@param src1 first input matrix.
+@param src2 scalar, which will be per-lemenetly conjuncted with elements of src1.
+*/
+GAPI_EXPORTS GMat bitwise_and(const GMat& src1, const GScalar& src2);
+
+/** @brief computes bitwise disjunction of the two matrixes (src1 | src2)
+Calculates the per-element bit-wise logical disjunction of two matrices of the same size.
+
+In case of floating-point matrices, their machine-specific bit
+representations (usually IEEE754-compliant) are used for the operation.
+In case of multi-channel matrices, each channel is processed
+independently. Output matrix must have the same size and depth as the input
+matrices.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.bitwise_or"
+
+@param src1 first input matrix.
+@param src2 second input matrix.
+*/
+GAPI_EXPORTS GMat bitwise_or(const GMat& src1, const GMat& src2);
+/** @overload
+@note Function textual ID is "org.opencv.core.pixelwise.compare.bitwise_orS"
+@param src1 first input matrix.
+@param src2 scalar, which will be per-lemenetly disjuncted with elements of src1.
+*/
+GAPI_EXPORTS GMat bitwise_or(const GMat& src1, const GScalar& src2);
+
+
+/** @brief computes bitwise logical "exclusive or" of the two matrixes (src1 ^ src2)
+Calculates the per-element bit-wise logical "exclusive or" of two matrices of the same size.
+
+In case of floating-point matrices, their machine-specific bit
+representations (usually IEEE754-compliant) are used for the operation.
+In case of multi-channel matrices, each channel is processed
+independently. Output matrix must have the same size and depth as the input
+matrices.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.bitwise_xor"
+
+@param src1 first input matrix.
+@param src2 second input matrix.
+*/
+GAPI_EXPORTS GMat bitwise_xor(const GMat& src1, const GMat& src2);
+/** @overload
+@note Function textual ID is "org.opencv.core.pixelwise.compare.bitwise_xorS"
+@param src1 first input matrix.
+@param src2 scalar, for which per-lemenet "logical or" operation on elements of src1 will be performed.
+*/
+GAPI_EXPORTS GMat bitwise_xor(const GMat& src1, const GScalar& src2);
+
+
+/** @brief Inverts every bit of an array.
+The function bitwise_not calculates per-element bit-wise inversion of the input
+matrix:
+\f[\texttt{dst} (I) = \neg \texttt{src} (I)\f]
+
+In case of floating-point matrices, their machine-specific bit
+representations (usually IEEE754-compliant) are used for the operation.
+In case of multi-channel matrices, each channel is processed
+independently. Output matrix must have the same size and depth as the input
+matrix.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.bitwise_not"
+
+@param src input matrix.
+*/
+GAPI_EXPORTS GMat bitwise_not(const GMat& src);
+
+/** @brief Select values from either first or second of input matrices by given mask.
+The function set to the output matrix either the value from the first input matrix if corresponding value of mask matrix is 255,
+ or value from the second input matrix (if value of mask matrix set to 0).
+
+Input mask matrix must be of @ref CV_8UC1 type, two other inout matrices and output matrix should be of the same type. The size should
+be the same for all input and output matrices.
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.pixelwise.select"
+
+@param src1 first input matrix.
+@param src2 second input matrix.
+@param mask mask input matrix.
+*/
+GAPI_EXPORTS GMat select(const GMat& src1, const GMat& src2, const GMat& mask);
+
+//! @} gapi_pixelwise
+
+
+//! @addtogroup gapi_matrixop
+//! @{
+/** @brief Calculates per-element minimum of two matrices.
+
+The function min calculates the per-element minimum of two matrices of the same size, number of channels and depth:
+\f[\texttt{dst} (I)= \min ( \texttt{src1} (I), \texttt{src2} (I))\f]
+ where I is a multi-dimensional index of matrix elements. In case of
+ multi-channel matrices, each channel is processed independently.
+Output matrix must be of the same size and depth as src1.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.matrixop.min"
+@param src1 first input matrix.
+@param src2 second input matrix of the same size and depth as src1.
+@sa max, compareEqual, compareLess, compareLessEqual
+*/
+GAPI_EXPORTS GMat min(const GMat& src1, const GMat& src2);
+
+/** @brief Calculates per-element maximum of two matrices.
+
+The function max calculates the per-element maximum of two matrices of the same size, number of channels and depth:
+\f[\texttt{dst} (I)= \max ( \texttt{src1} (I), \texttt{src2} (I))\f]
+ where I is a multi-dimensional index of matrix elements. In case of
+ multi-channel matrices, each channel is processed independently.
+Output matrix must be of the same size and depth as src1.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.matrixop.max"
+@param src1 first input matrix.
+@param src2 second input matrix of the same size and depth as src1.
+@sa min, compare, compareEqual, compareGreater, compareGreaterEqual
+*/
+GAPI_EXPORTS GMat max(const GMat& src1, const GMat& src2);
+
+/** @brief Calculates the per-element absolute difference between two matrices.
+
+The function absDiff calculates absolute difference between two matrices of the same size and depth:
+ \f[\texttt{dst}(I) = \texttt{saturate} (| \texttt{src1}(I) - \texttt{src2}(I)|)\f]
+ where I is a multi-dimensional index of matrix elements. In case of
+ multi-channel matrices, each channel is processed independently.
+Output matrix must have the same size and depth as input matrices.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.matrixop.absdiff"
+@param src1 first input matrix.
+@param src2 second input matrix.
+@sa abs
+*/
+GAPI_EXPORTS GMat absDiff(const GMat& src1, const GMat& src2);
+
+/** @brief Calculates absolute value of matrix elements.
+
+The function abs calculates absolute difference between matrix elements and given scalar value:
+ \f[\texttt{dst}(I) = \texttt{saturate} (| \texttt{src1}(I) - \texttt{matC}(I)|)\f]
+ where matC is constructed from given scalar c and has the same sizes and depth as input matrix src.
+
+Output matrix must be of the same size and depth as src.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.matrixop.absdiffC"
+@param src input matrix.
+@param c scalar to be subtracted.
+@sa min, max
+*/
+GAPI_EXPORTS GMat absDiffC(const GMat& src, const GScalar& c);
+
+/** @brief Calculates sum of all matrix elements.
+
+The function sum calculates sum of all matrix elements, independently for each channel.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.matrixop.sum"
+@param src input matrix.
+@sa min, max
+*/
+GAPI_EXPORTS GScalar sum(const GMat& src);
+
+/** @brief Calculates the weighted sum of two matrices.
+
+The function addWeighted calculates the weighted sum of two matrices as follows:
+\f[\texttt{dst} (I)= \texttt{saturate} ( \texttt{src1} (I)* \texttt{alpha} + \texttt{src2} (I)* \texttt{beta} + \texttt{gamma} )\f]
+where I is a multi-dimensional index of array elements. In case of multi-channel matrices, each
+channel is processed independently.
+
+The function can be replaced with a matrix expression:
+ \f[\texttt{dst}(I) = \texttt{alpha} * \texttt{src1}(I) - \texttt{beta} * \texttt{src2}(I) + \texttt{gamma} \f]
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.matrixop.addweighted"
+@param src1 first input matrix.
+@param alpha weight of the first matrix elements.
+@param src2 second input matrix of the same size and channel number as src1.
+@param beta weight of the second matrix elements.
+@param gamma scalar added to each sum.
+@param ddepth optional depth of the output matrix.
+@sa add, sub
+*/
+GAPI_EXPORTS GMat addWeighted(const GMat& src1, double alpha, const GMat& src2, double beta, double gamma, int ddepth = -1);
+
+/** @brief Calculates the absolute L1 norm of a matrix.
+
+This version of normL1 calculates the absolute L1 norm of src.
+
+As example for one array consider the function \f$r(x)= \begin{pmatrix} x \\ 1-x \end{pmatrix}, x \in [-1;1]\f$.
+The \f$ L_{1} \f$ norm for the sample value \f$r(-1) = \begin{pmatrix} -1 \\ 2 \end{pmatrix}\f$
+is calculated as follows
+\f{align*}
+ \| r(-1) \|_{L_1} &= |-1| + |2| = 3 \\
+\f}
+and for \f$r(0.5) = \begin{pmatrix} 0.5 \\ 0.5 \end{pmatrix}\f$ the calculation is
+\f{align*}
+ \| r(0.5) \|_{L_1} &= |0.5| + |0.5| = 1 \\
+\f}
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.matrixop.norml1"
+@param src input matrix.
+@sa normL2, normInf
+*/
+GAPI_EXPORTS GScalar normL1(const GMat& src);
+
+/** @brief Calculates the absolute L2 norm of a matrix.
+
+This version of normL2 calculates the absolute L2 norm of src.
+
+As example for one array consider the function \f$r(x)= \begin{pmatrix} x \\ 1-x \end{pmatrix}, x \in [-1;1]\f$.
+The \f$ L_{2} \f$ norm for the sample value \f$r(-1) = \begin{pmatrix} -1 \\ 2 \end{pmatrix}\f$
+is calculated as follows
+\f{align*}
+ \| r(-1) \|_{L_2} &= \sqrt{(-1)^{2} + (2)^{2}} = \sqrt{5} \\
+\f}
+and for \f$r(0.5) = \begin{pmatrix} 0.5 \\ 0.5 \end{pmatrix}\f$ the calculation is
+\f{align*}
+ \| r(0.5) \|_{L_2} &= \sqrt{(0.5)^{2} + (0.5)^{2}} = \sqrt{0.5} \\
+\f}
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+@note Function textual ID is "org.opencv.core.matrixop.norml2"
+@param src input matrix.
+@sa normL1, normInf
+*/
+GAPI_EXPORTS GScalar normL2(const GMat& src);
+
+/** @brief Calculates the absolute infinite norm of a matrix.
+
+This version of normInf calculates the absolute infinite norm of src.
+
+As example for one array consider the function \f$r(x)= \begin{pmatrix} x \\ 1-x \end{pmatrix}, x \in [-1;1]\f$.
+The \f$ L_{\infty} \f$ norm for the sample value \f$r(-1) = \begin{pmatrix} -1 \\ 2 \end{pmatrix}\f$
+is calculated as follows
+\f{align*}
+ \| r(-1) \|_{L_\infty} &= \max(|-1|,|2|) = 2
+\f}
+and for \f$r(0.5) = \begin{pmatrix} 0.5 \\ 0.5 \end{pmatrix}\f$ the calculation is
+\f{align*}
+ \| r(0.5) \|_{L_\infty} &= \max(|0.5|,|0.5|) = 0.5.
+\f}
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.core.matrixop.norminf"
+@param src input matrix.
+@sa normL1, normL2
+*/
+GAPI_EXPORTS GScalar normInf(const GMat& src);
+
+/** @brief Calculates the integral of an image.
+
+The function calculates one or more integral images for the source image as follows:
+
+\f[\texttt{sum} (X,Y) = \sum _{x<X,y<Y} \texttt{image} (x,y)\f]
+
+\f[\texttt{sqsum} (X,Y) = \sum _{x<X,y<Y} \texttt{image} (x,y)^2\f]
+
+The function return integral image as \f$(W+1)\times (H+1)\f$ , 32-bit integer or floating-point (32f or 64f) and
+ integral image for squared pixel values; it is \f$(W+1)\times (H+)\f$, double-precision floating-point (64f) array.
+
+@note Function textual ID is "org.opencv.core.matrixop.integral"
+
+@param src input image.
+@param sdepth desired depth of the integral and the tilted integral images, CV_32S, CV_32F, or
+CV_64F.
+@param sqdepth desired depth of the integral image of squared pixel values, CV_32F or CV_64F.
+ */
+GAPI_EXPORTS std::tuple<GMat, GMat> integral(const GMat& src, int sdepth = -1, int sqdepth = -1);
+
+/** @brief Applies a fixed-level threshold to each matrix element.
+
+The function applies fixed-level thresholding to a single- or multiple-channel matrix.
+The function is typically used to get a bi-level (binary) image out of a grayscale image ( cmp funtions could be also used for
+this purpose) or for removing a noise, that is, filtering out pixels with too small or too large
+values. There are several depths of thresholding supported by the function. They are determined by
+depth parameter.
+
+Also, the special values cv::THRESH_OTSU or cv::THRESH_TRIANGLE may be combined with one of the
+above values. In these cases, the function determines the optimal threshold value using the Otsu's
+or Triangle algorithm and uses it instead of the specified thresh . The function returns the
+computed threshold value in addititon to thresholded matrix.
+The Otsu's and Triangle methods are implemented only for 8-bit matrices.
+
+Input image should be single channel only in case of cv::THRESH_OTSU or cv::THRESH_TRIANGLE flags.
+Output matrix must be of the same size and depth as src.
+
+@note Function textual ID is "org.opencv.core.matrixop.threshold"
+
+@param src input matrix (@ref CV_8UC1, @ref CV_8UC3, or @ref CV_32FC1).
+@param thresh threshold value.
+@param maxval maximum value to use with the cv::THRESH_BINARY and cv::THRESH_BINARY_INV thresholding
+depths.
+@param depth thresholding depth (see the cv::ThresholdTypes).
+
+@sa min, max, cmpGT, cmpLE, cmpGE, cmpLS
+ */
+GAPI_EXPORTS GMat threshold(const GMat& src, const GScalar& thresh, const GScalar& maxval, int depth);
+/** @overload
+This function appicable for all threshold depths except CV_THRESH_OTSU and CV_THRESH_TRIANGLE
+@note Function textual ID is "org.opencv.core.matrixop.thresholdOT"
+*/
+GAPI_EXPORTS std::tuple<GMat, GScalar> threshold(const GMat& src, const GScalar& maxval, int depth);
+
+/** @brief Applies a range-level threshold to each matrix element.
+
+The function applies range-level thresholding to a single- or multiple-channel matrix.
+It sets output pixel value to OxFF if the corresponding pixel value of input matrix is in specified range,or 0 otherwise.
+
+Input and output matrices must be CV_8UC1.
+
+@note Function textual ID is "org.opencv.core.matrixop.inRange"
+
+@param src input matrix (CV_8UC1).
+@param threshLow lower boundary value.
+@param threshUp upper boundary value.
+
+@sa threshold
+ */
+GAPI_EXPORTS GMat inRange(const GMat& src, const GScalar& threshLow, const GScalar& threshUp);
+
+//! @} gapi_matrixop
+
+//! @addtogroup gapi_transform
+//! @{
+/** @brief Resizes an image.
+
+The function resizes the image src down to or up to the specified size.
+
+Output image size will have the size dsize (when dsize is non-zero) or the size computed from
+src.size(), fx, and fy; the depth of output is the same as of src.
+
+If you want to resize src so that it fits the pre-created dst,
+you may call the function as follows:
+@code
+ // explicitly specify dsize=dst.size(); fx and fy will be computed from that.
+ resize(src, dst, dst.size(), 0, 0, interpolation);
+@endcode
+If you want to decimate the image by factor of 2 in each direction, you can call the function this
+way:
+@code
+ // specify fx and fy and let the function compute the destination image size.
+ resize(src, dst, Size(), 0.5, 0.5, interpolation);
+@endcode
+To shrink an image, it will generally look best with cv::INTER_AREA interpolation, whereas to
+enlarge an image, it will generally look best with cv::INTER_CUBIC (slow) or cv::INTER_LINEAR
+(faster but still looks OK).
+
+@note Function textual ID is "org.opencv.core.transform.resize"
+
+@param src input image.
+@param dsize output image size; if it equals zero, it is computed as:
+ \f[\texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))}\f]
+ Either dsize or both fx and fy must be non-zero.
+@param fx scale factor along the horizontal axis; when it equals 0, it is computed as
+\f[\texttt{(double)dsize.width/src.cols}\f]
+@param fy scale factor along the vertical axis; when it equals 0, it is computed as
+\f[\texttt{(double)dsize.height/src.rows}\f]
+@param interpolation interpolation method, see cv::InterpolationFlags
+
+@sa warpAffine, warpPerspective, remap
+ */
+GAPI_EXPORTS GMat resize(const GMat& src, const Size& dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR);
+
+/** @brief Creates one 3-channel (4-channel) matrix out of 3(4) single-channel ones.
+
+The function merges several matrices to make a single multi-channel matrix. That is, each
+element of the output matrix will be a concatenation of the elements of the input matrices, where
+elements of i-th input matrix are treated as mv[i].channels()-element vectors.
+Input matrix must be of @ref CV_8UC3 (@ref CV_8UC4) type.
+
+The function split3/split4 does the reverse operation.
+
+@note Function textual ID for merge3 is "org.opencv.core.transform.merge3"
+@note Function textual ID for merge4 is "org.opencv.core.transform.merge4"
+
+@param src1 first input matrix to be merged
+@param src2 second input matrix to be merged
+@param src3 third input matrix to be merged
+@param src4 fourth input matrix to be merged
+@sa split4, split3
+*/
+GAPI_EXPORTS GMat merge4(const GMat& src1, const GMat& src2, const GMat& src3, const GMat& src4);
+GAPI_EXPORTS GMat merge3(const GMat& src1, const GMat& src2, const GMat& src3);
+
+/** @brief Divides a 3-channel (4-channel) matrix into 3(4) single-channel matrices.
+
+The function splits a 3-channel (4-channel) matrix into 3(4) single-channel matrices:
+\f[\texttt{mv} [c](I) = \texttt{src} (I)_c\f]
+
+All output matrices must be in @ref CV_8UC1.
+
+@note Function textual for split3 ID is "org.opencv.core.transform.split3"
+@note Function textual for split4 ID is "org.opencv.core.transform.split4"
+
+@param src input @ref CV_8UC4 (@ref CV_8UC3) matrix.
+@sa merge3, merge4
+*/
+GAPI_EXPORTS std::tuple<GMat, GMat, GMat,GMat> split4(const GMat& src);
+GAPI_EXPORTS std::tuple<GMat, GMat, GMat> split3(const GMat& src);
+
+/** @brief Applies a generic geometrical transformation to an image.
+
+The function remap transforms the source image using the specified map:
+
+\f[\texttt{dst} (x,y) = \texttt{src} (map_x(x,y),map_y(x,y))\f]
+
+where values of pixels with non-integer coordinates are computed using one of available
+interpolation methods. \f$map_x\f$ and \f$map_y\f$ can be encoded as separate floating-point maps
+in \f$map_1\f$ and \f$map_2\f$ respectively, or interleaved floating-point maps of \f$(x,y)\f$ in
+\f$map_1\f$, or fixed-point maps created by using convertMaps. The reason you might want to
+convert from floating to fixed-point representations of a map is that they can yield much faster
+(\~2x) remapping operations. In the converted case, \f$map_1\f$ contains pairs (cvFloor(x),
+cvFloor(y)) and \f$map_2\f$ contains indices in a table of interpolation coefficients.
+Output image must be of the same size and depth as input one.
+
+@note Function textual ID is "org.opencv.core.transform.remap"
+
+@param src Source image.
+@param map1 The first map of either (x,y) points or just x values having the type CV_16SC2,
+CV_32FC1, or CV_32FC2.
+@param map2 The second map of y values having the type CV_16UC1, CV_32FC1, or none (empty map
+if map1 is (x,y) points), respectively.
+@param interpolation Interpolation method (see cv::InterpolationFlags). The method INTER_AREA is
+not supported by this function.
+@param borderMode Pixel extrapolation method (see cv::BorderTypes). When
+borderMode=BORDER_TRANSPARENT, it means that the pixels in the destination image that
+corresponds to the "outliers" in the source image are not modified by the function.
+@param borderValue Value used in case of a constant border. By default, it is 0.
+@note
+Due to current implementation limitations the size of an input and output images should be less than 32767x32767.
+ */
+GAPI_EXPORTS GMat remap(const GMat& src, const Mat& map1, const Mat& map2,
+ int interpolation, int borderMode = BORDER_CONSTANT,
+ const Scalar& borderValue = Scalar());
+
+/** @brief Flips a 2D matrix around vertical, horizontal, or both axes.
+
+The function flips the matrix in one of three different ways (row
+and column indices are 0-based):
+\f[\texttt{dst} _{ij} =
+\left\{
+\begin{array}{l l}
+\texttt{src} _{\texttt{src.rows}-i-1,j} & if\; \texttt{flipCode} = 0 \\
+\texttt{src} _{i, \texttt{src.cols} -j-1} & if\; \texttt{flipCode} > 0 \\
+\texttt{src} _{ \texttt{src.rows} -i-1, \texttt{src.cols} -j-1} & if\; \texttt{flipCode} < 0 \\
+\end{array}
+\right.\f]
+The example scenarios of using the function are the following:
+* Vertical flipping of the image (flipCode == 0) to switch between
+ top-left and bottom-left image origin. This is a typical operation
+ in video processing on Microsoft Windows\* OS.
+* Horizontal flipping of the image with the subsequent horizontal
+ shift and absolute difference calculation to check for a
+ vertical-axis symmetry (flipCode \> 0).
+* Simultaneous horizontal and vertical flipping of the image with
+ the subsequent shift and absolute difference calculation to check
+ for a central symmetry (flipCode \< 0).
+* Reversing the order of point arrays (flipCode \> 0 or
+ flipCode == 0).
+Output image must be of the same depth as input one, size should be correct for given flipCode.
+
+@note Function textual ID is "org.opencv.core.transform.flip"
+
+@param src input matrix.
+@param flipCode a flag to specify how to flip the array; 0 means
+flipping around the x-axis and positive value (for example, 1) means
+flipping around y-axis. Negative value (for example, -1) means flipping
+around both axes.
+@sa remap
+*/
+GAPI_EXPORTS GMat flip(const GMat& src, int flipCode);
+
+/** @brief Crops a 2D matrix.
+
+The function crops the matrix by given cv::Rect.
+
+Output matrix must be of the same depth as input one, size is specified by given rect size.
+
+@note Function textual ID is "org.opencv.core.transform.crop"
+
+@param src input matrix.
+@param rect a rect to crop a matrix to
+@sa resize
+*/
+GAPI_EXPORTS GMat crop(const GMat& src, const Rect& rect);
+
+/** @brief Applies horizontal concatenation to given matrices.
+
+The function horizontally concatenates two GMat matrices (with the same number of rows).
+@code{.cpp}
+ GMat A = { 1, 4,
+ 2, 5,
+ 3, 6 };
+ GMat B = { 7, 10,
+ 8, 11,
+ 9, 12 };
+
+ GMat C = gapi::concatHor(A, B);
+ //C:
+ //[1, 4, 7, 10;
+ // 2, 5, 8, 11;
+ // 3, 6, 9, 12]
+@endcode
+Output matrix must the same number of rows and depth as the src1 and src2, and the sum of cols of the src1 and src2.
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.imgproc.transform.concatHor"
+
+@param src1 first input matrix to be considered for horizontal concatenation.
+@param src2 second input matrix to be considered for horizontal concatenation.
+@sa concatVert
+*/
+GAPI_EXPORTS GMat concatHor(const GMat& src1, const GMat& src2);
+
+/** @overload
+The function horizontally concatenates given number of GMat matrices (with the same number of columns).
+Output matrix must the same number of columns and depth as the input matrices, and the sum of rows of input matrices.
+
+@param v vector of input matrices to be concatenated horizontally.
+*/
+GAPI_EXPORTS GMat concatHor(const std::vector<GMat> &v);
+
+/** @brief Applies vertical concatenation to given matrices.
+
+The function vertically concatenates two GMat matrices (with the same number of cols).
+ @code{.cpp}
+ GMat A = { 1, 7,
+ 2, 8,
+ 3, 9 };
+ GMat B = { 4, 10,
+ 5, 11,
+ 6, 12 };
+
+ GMat C = gapi::concatVert(A, B);
+ //C:
+ //[1, 7;
+ // 2, 8;
+ // 3, 9;
+ // 4, 10;
+ // 5, 11;
+ // 6, 12]
+ @endcode
+
+Output matrix must the same number of cols and depth as the src1 and src2, and the sum of rows of the src1 and src2.
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+
+@note Function textual ID is "org.opencv.imgproc.transform.concatVert"
+
+@param src1 first input matrix to be considered for vertical concatenation.
+@param src2 second input matrix to be considered for vertical concatenation.
+@sa concatHor
+*/
+GAPI_EXPORTS GMat concatVert(const GMat& src1, const GMat& src2);
+
+/** @overload
+The function vertically concatenates given number of GMat matrices (with the same number of columns).
+Output matrix must the same number of columns and depth as the input matrices, and the sum of rows of input matrices.
+
+@param v vector of input matrices to be concatenated vertically.
+*/
+GAPI_EXPORTS GMat concatVert(const std::vector<GMat> &v);
+
+
+/** @brief Performs a look-up table transform of a matrix.
+
+The function LUT fills the output matrix with values from the look-up table. Indices of the entries
+are taken from the input matrix. That is, the function processes each element of src as follows:
+\f[\texttt{dst} (I) \leftarrow \texttt{lut(src(I))}\f]
+
+Supported matrix data types are @ref CV_8UC1.
+Output is a matrix of the same size and number of channels as src, and the same depth as lut.
+
+@note Function textual ID is "org.opencv.core.transform.LUT"
+
+@param src input matrix of 8-bit elements.
+@param lut look-up table of 256 elements; in case of multi-channel input array, the table should
+either have a single channel (in this case the same table is used for all channels) or the same
+number of channels as in the input matrix.
+*/
+GAPI_EXPORTS GMat LUT(const GMat& src, const Mat& lut);
+
+/** @brief Performs a 3D look-up table transform of a multi-channel matrix.
+
+The function LUT3D fills the output matrix with values from the look-up table. Indices of the entries
+are taken from the input matrix. Interpolation is applied for mapping 0-255 range values to 0-16 range of 3DLUT table.
+The function processes each element of src as follows:
+@code{.cpp}
+ dst[i][j][k] = lut3D[~src_r][~src_g][~src_b];
+@endcode
+where ~ means approximation.
+Output is a matrix of of @ref CV_8UC3.
+
+@note Function textual ID is "org.opencv.core.transform.LUT3D"
+
+@param src input matrix of @ref CV_8UC3.
+@param lut3D look-up table 17x17x17 3-channel elements.
+@param interpolation The depth of interpoolation to be used.
+*/
+GAPI_EXPORTS GMat LUT3D(const GMat& src, const GMat& lut3D, int interpolation = INTER_NEAREST);
+
+/** @brief Converts a matrix to another data depth with optional scaling.
+
+The method converts source pixel values to the target data depth. saturate_cast\<\> is applied at
+the end to avoid possible overflows:
+
+\f[m(x,y) = saturate \_ cast<rType>( \alpha (*this)(x,y) + \beta )\f]
+Output matrix must be of the same size as input one.
+
+@note Function textual ID is "org.opencv.core.transform.convertTo"
+@param src input matrix to be converted from.
+@param rdepth desired output matrix depth or, rather, the depth since the number of channels are the
+same as the input has; if rdepth is negative, the output matrix will have the same depth as the input.
+@param alpha optional scale factor.
+@param beta optional delta added to the scaled values.
+ */
+GAPI_EXPORTS GMat convertTo(const GMat& src, int rdepth, double alpha=1, double beta=0);
+//! @} gapi_transform
+
+} //namespace gapi
+} //namespace cv
+
+#endif //OPENCV_GAPI_CORE_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/core.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/core.hpp
new file mode 100644
index 000000000..ec76fe5d5
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/core.hpp
@@ -0,0 +1,27 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_CPU_CORE_API_HPP
+#define OPENCV_GAPI_CPU_CORE_API_HPP
+
+#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
+#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS
+
+namespace cv {
+namespace gapi {
+namespace core {
+namespace cpu {
+
+GAPI_EXPORTS GKernelPackage kernels();
+
+} // namespace cpu
+} // namespace core
+} // namespace gapi
+} // namespace cv
+
+
+#endif // OPENCV_GAPI_CPU_CORE_API_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp
new file mode 100644
index 000000000..facaab6aa
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp
@@ -0,0 +1,266 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCPUKERNEL_HPP
+#define OPENCV_GAPI_GCPUKERNEL_HPP
+
+#include <functional>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <opencv2/core/mat.hpp>
+#include <opencv2/gapi/gcommon.hpp>
+#include <opencv2/gapi/gkernel.hpp>
+#include <opencv2/gapi/garg.hpp>
+#include <opencv2/gapi/own/convert.hpp> //to_ocv
+#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
+
+// FIXME: namespace scheme for backends?
+namespace cv {
+
+namespace gimpl
+{
+ // Forward-declare an internal class
+ class GCPUExecutable;
+} // namespace gimpl
+
+namespace gapi
+{
+namespace cpu
+{
+ /**
+ * \addtogroup gapi_std_backends
+ * @{
+ *
+ * @brief G-API backends available in this OpenCV version
+ *
+ * G-API backends play a corner stone role in G-API execution
+ * stack. Every backend is hardware-oriented and thus can run its
+ * kernels efficiently on the target platform.
+ *
+ * Backends are usually "back boxes" for G-API users -- on the API
+ * side, all backends are represented as different objects of the
+ * same class cv::gapi::GBackend. User can manipulate with backends
+ * mainly by specifying which kernels to use or where to look up
+ * for kernels first.
+ *
+ * @sa @ref gapi_hld, cv::gapi::lookup_order()
+ */
+
+ /**
+ * @brief Get a reference to CPU (OpenCV) backend.
+ *
+ * This is the default backend in G-API at the moment, providing
+ * broader functional coverage but losing some graph model
+ * advantages. Provided mostly for reference and prototyping
+ * purposes.
+ *
+ * @sa gapi_std_backends
+ */
+ GAPI_EXPORTS cv::gapi::GBackend backend();
+ /** @} */
+} // namespace cpu
+} // namespace gapi
+
+// Represents arguments which are passed to a wrapped CPU function
+// FIXME: put into detail?
+class GAPI_EXPORTS GCPUContext
+{
+public:
+ // Generic accessor API
+ template<typename T>
+ const T& inArg(int input) { return m_args.at(input).get<T>(); }
+
+ // Syntax sugar
+ const cv::gapi::own::Mat& inMat(int input);
+ cv::gapi::own::Mat& outMatR(int output); // FIXME: Avoid cv::gapi::own::Mat m = ctx.outMatR()
+
+ const cv::gapi::own::Scalar& inVal(int input);
+ cv::gapi::own::Scalar& outValR(int output); // FIXME: Avoid cv::gapi::own::Scalar s = ctx.outValR()
+ template<typename T> std::vector<T>& outVecR(int output) // FIXME: the same issue
+ {
+ return outVecRef(output).wref<T>();
+ }
+
+protected:
+ detail::VectorRef& outVecRef(int output);
+
+ std::vector<GArg> m_args;
+
+ //FIXME: avoid conversion of arguments from internal representaion to OpenCV one on each call
+ //to OCV kernel. (This can be achieved by a two single time conversions in GCPUExecutable::run,
+ //once on enter for input and output arguments, and once before return for output arguments only
+ std::unordered_map<std::size_t, GRunArgP> m_results;
+
+ friend class gimpl::GCPUExecutable;
+};
+
+class GAPI_EXPORTS GCPUKernel
+{
+public:
+ // This function is kernel's execution entry point (does the processing work)
+ using F = std::function<void(GCPUContext &)>;
+
+ GCPUKernel();
+ explicit GCPUKernel(const F& f);
+
+ void apply(GCPUContext &ctx);
+
+protected:
+ F m_f;
+};
+
+// FIXME: This is an ugly ad-hoc imlpementation. TODO: refactor
+
+namespace detail
+{
+template<class T> struct get_in;
+template<> struct get_in<cv::GMat>
+{
+ static cv::Mat get(GCPUContext &ctx, int idx) { return to_ocv(ctx.inMat(idx)); }
+};
+template<> struct get_in<cv::GScalar>
+{
+ static cv::Scalar get(GCPUContext &ctx, int idx) { return to_ocv(ctx.inVal(idx)); }
+};
+template<typename U> struct get_in<cv::GArray<U> >
+{
+ static const std::vector<U>& get(GCPUContext &ctx, int idx) { return ctx.inArg<VectorRef>(idx).rref<U>(); }
+};
+template<class T> struct get_in
+{
+ static T get(GCPUContext &ctx, int idx) { return ctx.inArg<T>(idx); }
+};
+
+struct tracked_cv_mat{
+ tracked_cv_mat(cv::gapi::own::Mat& m) : r{to_ocv(m)}, original_data{m.data} {}
+ cv::Mat r;
+ uchar* original_data;
+
+ operator cv::Mat& (){ return r;}
+ void validate() const{
+ if (r.data != original_data)
+ {
+ util::throw_error
+ (std::logic_error
+ ("OpenCV kernel output parameter was reallocated. \n"
+ "Incorrect meta data was provided ?"));
+ }
+ }
+};
+
+struct scalar_wrapper
+{
+ scalar_wrapper(cv::gapi::own::Scalar& s) : m_s{cv::gapi::own::to_ocv(s)}, m_org_s(s) {};
+ operator cv::Scalar& () { return m_s; }
+ void writeBack() const { m_org_s = to_own(m_s); }
+
+ cv::Scalar m_s;
+ cv::gapi::own::Scalar& m_org_s;
+};
+
+template<typename... Outputs>
+void postprocess(Outputs&... outs)
+{
+ struct
+ {
+ void operator()(tracked_cv_mat* bm) { bm->validate(); }
+ void operator()(scalar_wrapper* sw) { sw->writeBack(); }
+ void operator()(...) { }
+
+ } validate;
+ //dummy array to unfold parameter pack
+ int dummy[] = { 0, (validate(&outs), 0)... };
+ cv::util::suppress_unused_warning(dummy);
+}
+
+template<class T> struct get_out;
+template<> struct get_out<cv::GMat>
+{
+ static tracked_cv_mat get(GCPUContext &ctx, int idx)
+ {
+ auto& r = ctx.outMatR(idx);
+ return {r};
+ }
+};
+template<> struct get_out<cv::GScalar>
+{
+ static scalar_wrapper get(GCPUContext &ctx, int idx)
+ {
+ auto& s = ctx.outValR(idx);
+ return {s};
+ }
+};
+template<typename U> struct get_out<cv::GArray<U>>
+{
+ static std::vector<U>& get(GCPUContext &ctx, int idx)
+ {
+ return ctx.outVecR<U>(idx);
+ }
+};
+
+template<typename, typename, typename>
+struct OCVCallHelper;
+
+// FIXME: probably can be simplified with std::apply or analogue.
+template<typename Impl, typename... Ins, typename... Outs>
+struct OCVCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
+{
+ template<typename... Inputs>
+ struct call_and_postprocess
+ {
+ template<typename... Outputs>
+ static void call(Inputs&&... ins, Outputs&&... outs)
+ {
+ //not using a std::forward on outs is deliberate in order to
+ //cause compilation error, by tring to bind rvalue references to lvalue references
+ Impl::run(std::forward<Inputs>(ins)..., outs...);
+
+ postprocess(outs...);
+ }
+ };
+
+ template<int... IIs, int... OIs>
+ static void call_impl(GCPUContext &ctx, detail::Seq<IIs...>, detail::Seq<OIs...>)
+ {
+ //Make sure that OpenCV kernels do not reallocate memory for output parameters
+ //by comparing it's state (data ptr) before and after the call.
+ //This is done by converting each output Mat into tracked_cv_mat object, and binding
+ //them to parameters of ad-hoc function
+ //Convert own::Scalar to cv::Scalar before call kernel and run kernel
+ //convert cv::Scalar to own::Scalar after call kernel and write back results
+ call_and_postprocess<decltype(get_in<Ins>::get(ctx, IIs))...>::call(get_in<Ins>::get(ctx, IIs)..., get_out<Outs>::get(ctx, OIs)...);
+ }
+
+ static void call(GCPUContext &ctx)
+ {
+ call_impl(ctx,
+ typename detail::MkSeq<sizeof...(Ins)>::type(),
+ typename detail::MkSeq<sizeof...(Outs)>::type());
+ }
+};
+
+} // namespace detail
+
+template<class Impl, class K>
+class GCPUKernelImpl: public detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>
+{
+ using P = detail::OCVCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
+
+public:
+ using API = K;
+
+ static cv::gapi::GBackend backend() { return cv::gapi::cpu::backend(); }
+ static cv::GCPUKernel kernel() { return GCPUKernel(&P::call); }
+};
+
+#define GAPI_OCV_KERNEL(Name, API) struct Name: public cv::GCPUKernelImpl<Name, API>
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GCPUKERNEL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/imgproc.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/imgproc.hpp
new file mode 100644
index 000000000..0b96db08a
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/cpu/imgproc.hpp
@@ -0,0 +1,27 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_CPU_IMGPROC_API_HPP
+#define OPENCV_GAPI_CPU_IMGPROC_API_HPP
+
+#include <opencv2/core/cvdef.h> // GAPI_EXPORTS
+#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
+
+namespace cv {
+namespace gapi {
+namespace imgproc {
+namespace cpu {
+
+GAPI_EXPORTS GKernelPackage kernels();
+
+} // namespace cpu
+} // namespace imgproc
+} // namespace gapi
+} // namespace cv
+
+
+#endif // OPENCV_GAPI_CPU_IMGPROC_API_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/core.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/core.hpp
new file mode 100644
index 000000000..8c21f5760
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/core.hpp
@@ -0,0 +1,20 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_FLUID_CORE_HPP
+#define OPENCV_GAPI_FLUID_CORE_HPP
+
+#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
+#include <opencv2/gapi/own/exports.hpp> // GAPI_EXPORTS
+
+namespace cv { namespace gapi { namespace core { namespace fluid {
+
+GAPI_EXPORTS GKernelPackage kernels();
+
+}}}}
+
+#endif // OPENCV_GAPI_FLUID_CORE_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidbuffer.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidbuffer.hpp
new file mode 100644
index 000000000..8965ec75b
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidbuffer.hpp
@@ -0,0 +1,150 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_FLUID_BUFFER_HPP
+#define OPENCV_GAPI_FLUID_BUFFER_HPP
+
+#include <list>
+#include <numeric> // accumulate
+#include <ostream> // ostream
+#include <cstdint> // uint8_t
+
+#include <opencv2/gapi/opencv_includes.hpp>
+#include <opencv2/gapi/own/mat.hpp>
+#include <opencv2/gapi/gmat.hpp>
+
+#include "opencv2/gapi/util/optional.hpp"
+#include "opencv2/gapi/own/scalar.hpp"
+#include "opencv2/gapi/own/mat.hpp"
+
+namespace cv {
+namespace gapi {
+namespace fluid {
+
+struct Border
+{
+#if !defined(GAPI_STANDALONE)
+ // This constructor is required to support existing kernels which are part of G-API
+ Border(int _type, cv::Scalar _val) : type(_type), value(to_own(_val)) {};
+#endif // !defined(GAPI_STANDALONE)
+ Border(int _type, cv::gapi::own::Scalar _val) : type(_type), value(_val) {};
+ int type;
+ cv::gapi::own::Scalar value;
+};
+
+using BorderOpt = util::optional<Border>;
+
+bool operator == (const Border& b1, const Border& b2);
+
+class GAPI_EXPORTS Buffer;
+
+class GAPI_EXPORTS View
+{
+public:
+ struct Cache
+ {
+ std::vector<const uint8_t*> m_linePtrs;
+ GMatDesc m_desc;
+ int m_border_size = 0;
+
+ inline const uint8_t* linePtr(int index) const
+ {
+ return m_linePtrs[index + m_border_size];
+ }
+ };
+
+ View() = default;
+
+ const inline uint8_t* InLineB(int index) const // -(w-1)/2...0...+(w-1)/2 for Filters
+ {
+ return m_cache->linePtr(index);
+ }
+
+ template<typename T> const inline T* InLine(int i) const
+ {
+ const uint8_t* ptr = this->InLineB(i);
+ return reinterpret_cast<const T*>(ptr);
+ }
+
+ inline operator bool() const { return m_priv != nullptr; }
+ bool ready() const;
+ inline int length() const { return m_cache->m_desc.size.width; }
+ int y() const;
+
+ inline const GMatDesc& meta() const { return m_cache->m_desc; }
+
+ class GAPI_EXPORTS Priv; // internal use only
+ Priv& priv(); // internal use only
+ const Priv& priv() const; // internal use only
+
+ View(Priv* p);
+
+private:
+ std::shared_ptr<Priv> m_priv;
+ const Cache* m_cache;
+};
+
+class GAPI_EXPORTS Buffer
+{
+public:
+ struct Cache
+ {
+ std::vector<uint8_t*> m_linePtrs;
+ GMatDesc m_desc;
+ };
+
+ // Default constructor (executable creation stage,
+ // all following initialization performed in Priv::init())
+ Buffer();
+ // Scratch constructor (user kernels)
+ Buffer(const cv::GMatDesc &desc);
+
+ // Constructor for intermediate buffers (for tests)
+ Buffer(const cv::GMatDesc &desc,
+ int max_line_consumption, int border_size,
+ int skew,
+ int wlpi,
+ BorderOpt border);
+ // Constructor for in/out buffers (for tests)
+ Buffer(const cv::gapi::own::Mat &data, bool is_input);
+
+ inline uint8_t* OutLineB(int index = 0)
+ {
+ return m_cache->m_linePtrs[index];
+ }
+
+ template<typename T> inline T* OutLine(int index = 0)
+ {
+ uint8_t* ptr = this->OutLineB(index);
+ return reinterpret_cast<T*>(ptr);
+ }
+
+ int y() const;
+
+ int linesReady() const;
+ void debug(std::ostream &os) const;
+ inline int length() const { return m_cache->m_desc.size.width; }
+ int lpi() const; // LPI for WRITER
+
+ inline const GMatDesc& meta() const { return m_cache->m_desc; }
+
+ View mkView(int borderSize, bool ownStorage);
+
+ class GAPI_EXPORTS Priv; // internal use only
+ Priv& priv(); // internal use only
+ const Priv& priv() const; // internal use only
+
+private:
+ std::shared_ptr<Priv> m_priv;
+ const Cache* m_cache;
+};
+
+} // namespace cv::gapi::fluid
+} // namespace cv::gapi
+} // namespace cv
+
+#endif // OPENCV_GAPI_FLUID_BUFFER_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp
new file mode 100644
index 000000000..c71c5aa2c
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/gfluidkernel.hpp
@@ -0,0 +1,302 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_FLUID_KERNEL_HPP
+#define OPENCV_GAPI_FLUID_KERNEL_HPP
+
+#include <vector>
+#include <functional>
+#include <map>
+#include <unordered_map>
+
+#include <opencv2/gapi/opencv_includes.hpp>
+#include <opencv2/gapi/gcommon.hpp>
+#include <opencv2/gapi/gkernel.hpp>
+#include <opencv2/gapi/garg.hpp>
+#include <opencv2/gapi/own/types.hpp>
+
+#include <opencv2/gapi/fluid/gfluidbuffer.hpp>
+
+// FIXME: namespace scheme for backends?
+namespace cv {
+
+namespace gapi
+{
+namespace fluid
+{
+ /**
+ * \addtogroup gapi_std_backends G-API Standard backends
+ * @{
+ */
+ /**
+ * @brief Get a reference to Fluid backend.
+ *
+ * @sa gapi_std_backends
+ */
+ GAPI_EXPORTS cv::gapi::GBackend backend();
+ /** @} */
+} // namespace flud
+} // namespace gapi
+
+
+class GAPI_EXPORTS GFluidKernel
+{
+public:
+ enum class Kind
+ {
+ Filter,
+ Resize
+ };
+
+ // This function is a generic "doWork" callback
+ using F = std::function<void(const cv::GArgs&, const std::vector<gapi::fluid::Buffer*> &)>;
+
+ // This function is a generic "initScratch" callback
+ using IS = std::function<void(const cv::GMetaArgs &, const cv::GArgs&, gapi::fluid::Buffer &)>;
+
+ // This function is a generic "resetScratch" callback
+ using RS = std::function<void(gapi::fluid::Buffer &)>;
+
+ // This function describes kernel metadata inference rule.
+ using M = std::function<GMetaArgs(const GMetaArgs &, const GArgs &)>;
+
+ // This function is a generic "getBorder" callback (extracts border-related data from kernel's input parameters)
+ using B = std::function<gapi::fluid::BorderOpt(const GMetaArgs&, const GArgs&)>;
+
+ // FIXME: move implementations out of header file
+ GFluidKernel() {}
+ GFluidKernel(int w, Kind k, int l, bool scratch, const F& f, const IS &is, const RS &rs, const B& b)
+ : m_window(w)
+ , m_kind(k)
+ , m_lpi(l)
+ , m_scratch(scratch)
+ , m_f(f)
+ , m_is(is)
+ , m_rs(rs)
+ , m_b(b) {}
+
+ int m_window = -1;
+ Kind m_kind;
+ const int m_lpi = -1;
+ const bool m_scratch = false;
+
+ const F m_f;
+ const IS m_is;
+ const RS m_rs;
+ const B m_b;
+};
+
+// FIXME!!!
+// This is the temporary and experimental API
+// which should be replaced by runtime roi-based scheduling
+struct GFluidOutputRois
+{
+ std::vector<cv::gapi::own::Rect> rois;
+};
+
+namespace detail
+{
+template<> struct CompileArgTag<GFluidOutputRois>
+{
+ static const char* tag() { return "gapi.fluid.outputRois"; }
+};
+} // namespace detail
+
+namespace detail
+{
+template<class T> struct fluid_get_in;
+template<> struct fluid_get_in<cv::GMat>
+{
+ static const cv::gapi::fluid::View& get(const cv::GArgs &in_args, int idx)
+ {
+ return in_args[idx].unsafe_get<cv::gapi::fluid::View>();
+ }
+};
+
+template<> struct fluid_get_in<cv::GScalar>
+{
+ // FIXME: change to return by reference when moved to own::Scalar
+#if !defined(GAPI_STANDALONE)
+ static const cv::Scalar get(const cv::GArgs &in_args, int idx)
+ {
+ return cv::gapi::own::to_ocv(in_args[idx].unsafe_get<cv::gapi::own::Scalar>());
+ }
+#else
+ static const cv::gapi::own::Scalar get(const cv::GArgs &in_args, int idx)
+ {
+ return in_args[idx].get<cv::gapi::own::Scalar>();
+ }
+#endif // !defined(GAPI_STANDALONE)
+};
+template<class T> struct fluid_get_in
+{
+ static const T& get(const cv::GArgs &in_args, int idx)
+ {
+ return in_args[idx].unsafe_get<T>();
+ }
+};
+
+template<bool, typename Impl, typename... Ins>
+struct scratch_helper;
+
+template<typename Impl, typename... Ins>
+struct scratch_helper<true, Impl, Ins...>
+{
+ // Init
+ template<int... IIs>
+ static void help_init_impl(const cv::GMetaArgs &metas,
+ const cv::GArgs &in_args,
+ gapi::fluid::Buffer &scratch_buf,
+ detail::Seq<IIs...>)
+ {
+ Impl::initScratch(get_in_meta<Ins>(metas, in_args, IIs)..., scratch_buf);
+ }
+
+ static void help_init(const cv::GMetaArgs &metas,
+ const cv::GArgs &in_args,
+ gapi::fluid::Buffer &b)
+ {
+ help_init_impl(metas, in_args, b, typename detail::MkSeq<sizeof...(Ins)>::type());
+ }
+
+ // Reset
+ static void help_reset(gapi::fluid::Buffer &b)
+ {
+ Impl::resetScratch(b);
+ }
+};
+
+template<typename Impl, typename... Ins>
+struct scratch_helper<false, Impl, Ins...>
+{
+ static void help_init(const cv::GMetaArgs &,
+ const cv::GArgs &,
+ gapi::fluid::Buffer &)
+ {
+ GAPI_Assert(false);
+ }
+ static void help_reset(gapi::fluid::Buffer &)
+ {
+ GAPI_Assert(false);
+ }
+};
+
+template<typename T> struct is_gmat_type
+{
+ static const constexpr bool value = std::is_same<cv::GMat, T>::value;
+};
+
+template<bool CallCustomGetBorder, typename Impl, typename... Ins>
+struct get_border_helper;
+
+template<typename Impl, typename... Ins>
+struct get_border_helper<true, Impl, Ins...>
+{
+ template<int... IIs>
+ static gapi::fluid::BorderOpt get_border_impl(const GMetaArgs &metas,
+ const cv::GArgs &in_args,
+ cv::detail::Seq<IIs...>)
+ {
+ return util::make_optional(Impl::getBorder(cv::detail::get_in_meta<Ins>(metas, in_args, IIs)...));
+ }
+
+ static gapi::fluid::BorderOpt help(const GMetaArgs &metas,
+ const cv::GArgs &in_args)
+ {
+ return get_border_impl(metas, in_args, typename detail::MkSeq<sizeof...(Ins)>::type());
+ }
+};
+
+template<typename Impl, typename... Ins>
+struct get_border_helper<false, Impl, Ins...>
+{
+ static gapi::fluid::BorderOpt help(const cv::GMetaArgs &,
+ const cv::GArgs &)
+ {
+ return {};
+ }
+};
+
+template<typename, typename, typename, bool UseScratch>
+struct FluidCallHelper;
+
+template<typename Impl, typename... Ins, typename... Outs, bool UseScratch>
+struct FluidCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>, UseScratch>
+{
+ static_assert(all_satisfy<is_gmat_type, Outs...>::value, "return type must be GMat");
+
+ // Execution dispatcher ////////////////////////////////////////////////////
+ template<int... IIs, int... OIs>
+ static void call_impl(const cv::GArgs &in_args,
+ const std::vector<gapi::fluid::Buffer*> &out_bufs,
+ detail::Seq<IIs...>,
+ detail::Seq<OIs...>)
+ {
+ Impl::run(fluid_get_in<Ins>::get(in_args, IIs)..., *out_bufs[OIs]...);
+ }
+
+ static void call(const cv::GArgs &in_args,
+ const std::vector<gapi::fluid::Buffer*> &out_bufs)
+ {
+ constexpr int numOuts = (sizeof...(Outs)) + (UseScratch ? 1 : 0);
+ call_impl(in_args, out_bufs,
+ typename detail::MkSeq<sizeof...(Ins)>::type(),
+ typename detail::MkSeq<numOuts>::type());
+ }
+
+ // Scratch buffer initialization dispatcher ////////////////////////////////
+ static void init_scratch(const GMetaArgs &metas,
+ const cv::GArgs &in_args,
+ gapi::fluid::Buffer &b)
+ {
+ scratch_helper<UseScratch, Impl, Ins...>::help_init(metas, in_args, b);
+ }
+
+ // Scratch buffer reset dispatcher /////////////////////////////////////////
+ static void reset_scratch(gapi::fluid::Buffer &scratch_buf)
+ {
+ scratch_helper<UseScratch, Impl, Ins...>::help_reset(scratch_buf);
+ }
+
+ static gapi::fluid::BorderOpt getBorder(const GMetaArgs &metas, const cv::GArgs &in_args)
+ {
+ // User must provide "init" callback if Window != 1
+ // TODO: move to constexpr if when we enable C++17
+ constexpr bool callCustomGetBorder = (Impl::Window != 1);
+ return get_border_helper<callCustomGetBorder, Impl, Ins...>::help(metas, in_args);
+ }
+};
+} // namespace detail
+
+
+template<class Impl, class K, bool UseScratch>
+class GFluidKernelImpl
+{
+ static const int LPI = 1;
+ static const auto Kind = GFluidKernel::Kind::Filter;
+ using P = detail::FluidCallHelper<Impl, typename K::InArgs, typename K::OutArgs, UseScratch>;
+
+public:
+ using API = K;
+
+ static GFluidKernel kernel()
+ {
+ // FIXME: call() and getOutMeta() needs to be renamed so it is clear these
+ // functions are internal wrappers, not user API
+ return GFluidKernel(Impl::Window, Impl::Kind, Impl::LPI,
+ UseScratch,
+ &P::call, &P::init_scratch, &P::reset_scratch, &P::getBorder);
+ }
+
+ static cv::gapi::GBackend backend() { return cv::gapi::fluid::backend(); }
+};
+
+#define GAPI_FLUID_KERNEL(Name, API, Scratch) struct Name: public cv::GFluidKernelImpl<Name, API, Scratch>
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GCPUKERNEL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/imgproc.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/imgproc.hpp
new file mode 100644
index 000000000..dedfa9dbe
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/fluid/imgproc.hpp
@@ -0,0 +1,20 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_FLUID_IMGPROC_HPP
+#define OPENCV_GAPI_FLUID_IMGPROC_HPP
+
+#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
+#include <opencv2/gapi/own/exports.hpp> // GAPI_EXPORTS
+
+namespace cv { namespace gapi { namespace imgproc { namespace fluid {
+
+GAPI_EXPORTS GKernelPackage kernels();
+
+}}}}
+
+#endif // OPENCV_GAPI_FLUID_IMGPROC_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garg.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garg.hpp
new file mode 100644
index 000000000..f8a317006
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garg.hpp
@@ -0,0 +1,126 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GARG_HPP
+#define OPENCV_GAPI_GARG_HPP
+
+#include <vector>
+#include <type_traits>
+
+#include <opencv2/gapi/opencv_includes.hpp>
+#include "opencv2/gapi/own/mat.hpp"
+
+#include "opencv2/gapi/util/any.hpp"
+#include "opencv2/gapi/util/variant.hpp"
+
+#include "opencv2/gapi/gmat.hpp"
+#include "opencv2/gapi/gscalar.hpp"
+#include "opencv2/gapi/garray.hpp"
+#include "opencv2/gapi/gtype_traits.hpp"
+#include "opencv2/gapi/gmetaarg.hpp"
+#include "opencv2/gapi/own/scalar.hpp"
+
+namespace cv {
+
+class GArg;
+
+namespace detail {
+ template<typename T>
+ using is_garg = std::is_same<GArg, typename std::decay<T>::type>;
+}
+
+// Parameter holder class for a node
+// Depending on platform capabilities, can either support arbitrary types
+// (as `boost::any`) or a limited number of types (as `boot::variant`).
+// FIXME: put into "details" as a user shouldn't use it in his code
+class GAPI_EXPORTS GArg
+{
+public:
+ GArg() {}
+
+ template<typename T, typename std::enable_if<!detail::is_garg<T>::value, int>::type = 0>
+ explicit GArg(const T &t)
+ : kind(detail::GTypeTraits<T>::kind)
+ , value(detail::wrap_gapi_helper<T>::wrap(t))
+ {
+ }
+
+ template<typename T, typename std::enable_if<!detail::is_garg<T>::value, int>::type = 0>
+ explicit GArg(T &&t)
+ : kind(detail::GTypeTraits<typename std::decay<T>::type>::kind)
+ , value(detail::wrap_gapi_helper<T>::wrap(t))
+ {
+ }
+
+ template<typename T> inline T& get()
+ {
+ return util::any_cast<typename std::remove_reference<T>::type>(value);
+ }
+
+ template<typename T> inline const T& get() const
+ {
+ return util::any_cast<typename std::remove_reference<T>::type>(value);
+ }
+
+ template<typename T> inline T& unsafe_get()
+ {
+ return util::unsafe_any_cast<typename std::remove_reference<T>::type>(value);
+ }
+
+ template<typename T> inline const T& unsafe_get() const
+ {
+ return util::unsafe_any_cast<typename std::remove_reference<T>::type>(value);
+ }
+
+ detail::ArgKind kind = detail::ArgKind::OPAQUE;
+
+protected:
+ util::any value;
+};
+
+using GArgs = std::vector<GArg>;
+
+// FIXME: Express as M<GProtoArg...>::type
+// FIXME: Move to a separate file!
+using GRunArg = util::variant<
+#if !defined(GAPI_STANDALONE)
+ cv::Mat,
+ cv::Scalar,
+ cv::UMat,
+#endif // !defined(GAPI_STANDALONE)
+ cv::gapi::own::Mat,
+ cv::gapi::own::Scalar,
+ cv::detail::VectorRef
+ >;
+using GRunArgs = std::vector<GRunArg>;
+
+using GRunArgP = util::variant<
+#if !defined(GAPI_STANDALONE)
+ cv::Mat*,
+ cv::Scalar*,
+ cv::UMat*,
+#endif // !defined(GAPI_STANDALONE)
+ cv::gapi::own::Mat*,
+ cv::gapi::own::Scalar*,
+ cv::detail::VectorRef
+ >;
+using GRunArgsP = std::vector<GRunArgP>;
+
+
+template<typename... Ts> inline GRunArgs gin(const Ts&... args)
+{
+ return GRunArgs{ GRunArg(detail::wrap_host_helper<Ts>::wrap_in(args))... };
+}
+
+template<typename... Ts> inline GRunArgsP gout(Ts&... args)
+{
+ return GRunArgsP{ GRunArgP(detail::wrap_host_helper<Ts>::wrap_out(args))... };
+}
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GARG_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garray.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garray.hpp
new file mode 100644
index 000000000..87d00155b
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/garray.hpp
@@ -0,0 +1,251 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GARRAY_HPP
+#define OPENCV_GAPI_GARRAY_HPP
+
+#include <functional>
+#include <ostream>
+#include <vector>
+#include <memory>
+
+#include <opencv2/gapi/own/exports.hpp>
+#include <opencv2/gapi/opencv_includes.hpp>
+
+#include <opencv2/gapi/util/variant.hpp>
+#include <opencv2/gapi/util/throw.hpp>
+#include "opencv2/gapi/own/assert.hpp"
+
+namespace cv
+{
+// Forward declaration; GNode and GOrigin are an internal
+// (user-inaccessible) classes.
+class GNode;
+struct GOrigin;
+
+template<typename T> class GArray;
+
+/**
+ * \addtogroup gapi_meta_args
+ * @{
+ */
+struct GArrayDesc
+{
+ // FIXME: Body
+ // FIXME: Also implement proper operator== then
+ bool operator== (const GArrayDesc&) const { return true; }
+};
+template<typename U> GArrayDesc descr_of(const std::vector<U> &) { return {};}
+static inline GArrayDesc empty_array_desc() {return {}; }
+/** @} */
+
+std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &desc);
+
+namespace detail
+{
+ // ConstructVec is a callback which stores information about T and is used by
+ // G-API runtime to construct arrays in host memory (T remains opaque for G-API).
+ // ConstructVec is carried into G-API internals by GArrayU.
+ // Currently it is suitable for Host (CPU) plugins only, real offload may require
+ // more information for manual memory allocation on-device.
+ class VectorRef;
+ using ConstructVec = std::function<void(VectorRef&)>;
+
+
+ // This class strips type information from GArray<T> and makes it usable
+ // in the G-API graph compiler (expression unrolling, graph generation, etc).
+ // Part of GProtoArg.
+ class GAPI_EXPORTS GArrayU
+ {
+ public:
+ GArrayU(const GNode &n, std::size_t out); // Operation result constructor
+
+ GOrigin& priv(); // Internal use only
+ const GOrigin& priv() const; // Internal use only
+
+ protected:
+ GArrayU(); // Default constructor
+ template<class> friend class cv::GArray; // (avialable to GArray<T> only)
+
+ void setConstructFcn(ConstructVec &&cv); // Store T-aware constructor
+
+ std::shared_ptr<GOrigin> m_priv;
+ };
+
+ // This class represents a typed STL vector reference.
+ // Depending on origins, this reference may be either "just a" reference to
+ // an object created externally, OR actually own the underlying object
+ // (be value holder).
+ class BasicVectorRef
+ {
+ public:
+ std::size_t m_elemSize = 0ul;
+ cv::GArrayDesc m_desc;
+ virtual ~BasicVectorRef() {}
+ };
+
+ template<typename T> class VectorRefT: public BasicVectorRef
+ {
+ using empty_t = util::monostate;
+ using ro_ext_t = const std::vector<T> *;
+ using rw_ext_t = std::vector<T> *;
+ using rw_own_t = std::vector<T> ;
+ util::variant<empty_t, ro_ext_t, rw_ext_t, rw_own_t> m_ref;
+
+ inline bool isEmpty() const { return util::holds_alternative<empty_t>(m_ref); }
+ inline bool isROExt() const { return util::holds_alternative<ro_ext_t>(m_ref); }
+ inline bool isRWExt() const { return util::holds_alternative<rw_ext_t>(m_ref); }
+ inline bool isRWOwn() const { return util::holds_alternative<rw_own_t>(m_ref); }
+
+ void init(const std::vector<T>* vec = nullptr)
+ {
+ m_elemSize = sizeof(T);
+ if (vec) m_desc = cv::descr_of(*vec);
+ }
+
+ public:
+ VectorRefT() { init(); }
+ virtual ~VectorRefT() {}
+
+ explicit VectorRefT(const std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
+ explicit VectorRefT(std::vector<T>& vec) : m_ref(&vec) { init(&vec); }
+ explicit VectorRefT(std::vector<T>&& vec) : m_ref(std::move(vec)) { init(&vec); }
+
+ // Reset a VectorRefT. Called only for objects instantiated
+ // internally in G-API (e.g. temporary GArray<T>'s within a
+ // computation). Reset here means both initialization
+ // (creating an object) and reset (discarding its existing
+ // content before the next execution). Must never be called
+ // for external VectorRefTs.
+ void reset()
+ {
+ if (isEmpty())
+ {
+ std::vector<T> empty_vector;
+ m_desc = cv::descr_of(empty_vector);
+ m_ref = std::move(empty_vector);
+ GAPI_Assert(isRWOwn());
+ }
+ else if (isRWOwn())
+ {
+ util::get<rw_own_t>(m_ref).clear();
+ }
+ else GAPI_Assert(false); // shouldn't be called in *EXT modes
+ }
+
+ // Obtain a WRITE reference to underlying object
+ // Used by CPU kernel API wrappers when a kernel execution frame
+ // is created
+ std::vector<T>& wref()
+ {
+ GAPI_Assert(isRWExt() || isRWOwn());
+ if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
+ if (isRWOwn()) return util::get<rw_own_t>(m_ref);
+ util::throw_error(std::logic_error("Impossible happened"));
+ }
+
+ // Obtain a READ reference to underlying object
+ // Used by CPU kernel API wrappers when a kernel execution frame
+ // is created
+ const std::vector<T>& rref() const
+ {
+ // ANY vector can be accessed for reading, even if it declared for
+ // output. Example -- a GComputation from [in] to [out1,out2]
+ // where [out2] is a result of operation applied to [out1]:
+ //
+ // GComputation boundary
+ // . . . . . . .
+ // . .
+ // [in] ----> foo() ----> [out1]
+ // . . :
+ // . . . .:. . .
+ // . V .
+ // . bar() ---> [out2]
+ // . . . . . . . . . . . .
+ //
+ if (isROExt()) return *util::get<ro_ext_t>(m_ref);
+ if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
+ if (isRWOwn()) return util::get<rw_own_t>(m_ref);
+ util::throw_error(std::logic_error("Impossible happened"));
+ }
+ };
+
+ // This class strips type information from VectorRefT<> and makes it usable
+ // in the G-API executables (carrying run-time data/information to kernels).
+ // Part of GRunArg.
+ // Its methods are typed proxies to VectorRefT<T>.
+ // VectorRef maintains "reference" semantics so two copies of VectoRef refer
+ // to the same underlying object.
+ // FIXME: Put a good explanation on why cv::OutputArray doesn't fit this role
+ class VectorRef
+ {
+ std::shared_ptr<BasicVectorRef> m_ref;
+
+ template<typename T> inline void check() const
+ {
+ GAPI_DbgAssert(dynamic_cast<VectorRefT<T>*>(m_ref.get()) != nullptr);
+ GAPI_Assert(sizeof(T) == m_ref->m_elemSize);
+ }
+
+ public:
+ VectorRef() = default;
+ template<typename T> explicit VectorRef(const std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
+ template<typename T> explicit VectorRef(std::vector<T>& vec) : m_ref(new VectorRefT<T>(vec)) {}
+ template<typename T> explicit VectorRef(std::vector<T>&& vec) : m_ref(new VectorRefT<T>(vec)) {}
+
+ template<typename T> void reset()
+ {
+ if (!m_ref) m_ref.reset(new VectorRefT<T>());
+
+ check<T>();
+ static_cast<VectorRefT<T>&>(*m_ref).reset();
+ }
+
+ template<typename T> std::vector<T>& wref()
+ {
+ check<T>();
+ return static_cast<VectorRefT<T>&>(*m_ref).wref();
+ }
+
+ template<typename T> const std::vector<T>& rref() const
+ {
+ check<T>();
+ return static_cast<VectorRefT<T>&>(*m_ref).rref();
+ }
+
+ cv::GArrayDesc descr_of() const
+ {
+ return m_ref->m_desc;
+ }
+ };
+} // namespace detail
+
+/** \addtogroup gapi_data_objects
+ * @{
+ */
+
+template<typename T> class GArray
+{
+public:
+ GArray() { putDetails(); } // Empty constructor
+ explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
+ : m_ref(ref) { putDetails(); } // (used by GCall, not for users)
+
+ detail::GArrayU strip() const { return m_ref; }
+
+private:
+ static void VCTor(detail::VectorRef& vref) { vref.reset<T>(); }
+ void putDetails() {m_ref.setConstructFcn(&VCTor); }
+
+ detail::GArrayU m_ref;
+};
+
+/** @} */
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GARRAY_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcall.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcall.hpp
new file mode 100644
index 000000000..baf4f44e2
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcall.hpp
@@ -0,0 +1,63 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCALL_HPP
+#define OPENCV_GAPI_GCALL_HPP
+
+#include "opencv2/gapi/garg.hpp" // GArg
+#include "opencv2/gapi/gmat.hpp" // GMat
+#include "opencv2/gapi/gscalar.hpp" // GScalar
+#include "opencv2/gapi/garray.hpp" // GArray<T>
+
+namespace cv {
+
+struct GKernel;
+
+// The whole idea of this class is to represent an operation
+// which is applied to arguments. This is part of public API,
+// since it is what users should use to define kernel interfaces.
+
+class GAPI_EXPORTS GCall final
+{
+public:
+ class Priv;
+
+ explicit GCall(const GKernel &k);
+ ~GCall();
+
+ template<typename... Ts>
+ GCall& pass(Ts&&... args)
+ {
+ setArgs({cv::GArg(std::move(args))...});
+ return *this;
+ }
+
+ // A generic yield method - obtain a link to operator's particular GMat output
+ GMat yield (int output = 0);
+ GScalar yieldScalar(int output = 0);
+
+ template<class T> GArray<T> yieldArray(int output = 0)
+ {
+ return GArray<T>(yieldArray(output));
+ }
+
+ // Internal use only
+ Priv& priv();
+ const Priv& priv() const;
+
+protected:
+ std::shared_ptr<Priv> m_priv;
+
+ void setArgs(std::vector<GArg> &&args);
+
+ // Public version returns a typed array, this one is implementation detail
+ detail::GArrayU yieldArray(int output = 0);
+};
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GCALL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcommon.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcommon.hpp
new file mode 100644
index 000000000..6a3f51f77
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcommon.hpp
@@ -0,0 +1,166 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCOMMON_HPP
+#define OPENCV_GAPI_GCOMMON_HPP
+
+#include <functional> // std::hash
+#include <vector> // std::vector
+#include <type_traits> // decay
+
+#include <opencv2/gapi/opencv_includes.hpp>
+
+#include "opencv2/gapi/util/any.hpp"
+#include "opencv2/gapi/own/exports.hpp"
+#include "opencv2/gapi/own/assert.hpp"
+
+namespace cv {
+
+namespace detail
+{
+ // This is a trait-like structure to mark backend-specific compile arguments
+ // with tags
+ template<typename T> struct CompileArgTag;
+ template<typename T> struct CompileArgTag
+ {
+ static const char* tag() { return ""; };
+ };
+}
+
+// This definition is here because it is reused by both public(?) and internal
+// modules. Keeping it here wouldn't expose public details (e.g., API-level)
+// to components which are internal and operate on a lower-level entities
+// (e.g., compiler, backends).
+// FIXME: merge with ArgKind?
+// FIXME: replace with variant[format desc]?
+enum class GShape: int
+{
+ GMAT,
+ GSCALAR,
+ GARRAY,
+};
+
+struct GCompileArg;
+
+namespace detail {
+ template<typename T>
+ using is_compile_arg = std::is_same<GCompileArg, typename std::decay<T>::type>;
+}
+// CompileArg is an unified interface over backend-specific compilation
+// information
+// FIXME: Move to a separate file?
+/** \addtogroup gapi_compile_args
+ * @{
+ *
+ * @brief Compilation arguments: a set of data structures which can be
+ * passed to control compilation process
+ *
+ * G-API comes with a number of graph compilation options which can be
+ * passed to cv::GComputation::apply() or
+ * cv::GComputation::compile(). Known compilation options are listed
+ * in this page, while extra backends may introduce their own
+ * compilation options (G-API transparently accepts _everything_ which
+ * can be passed to cv::compile_args(), it depends on underlying
+ * backends if an option would be interpreted or not).
+ *
+ * For example, if an example computation is executed like this:
+ *
+ * @snippet modules/gapi/samples/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
+ */
+
+/**
+ * @brief Represents an arbitrary compilation argument.
+ *
+ * Any value can be wrapped into cv::GCompileArg, but only known ones
+ * (to G-API or its backends) can be interpreted correctly.
+ *
+ * Normally objects of this class shouldn't be created manually, use
+ * cv::compile_args() function which automatically wraps everything
+ * passed in (a variadic template parameter pack) into a vector of
+ * cv::GCompileArg objects.
+ */
+struct GAPI_EXPORTS GCompileArg
+{
+public:
+ std::string tag;
+
+ // FIXME: use decay in GArg/other trait-based wrapper before leg is shot!
+ template<typename T, typename std::enable_if<!detail::is_compile_arg<T>::value, int>::type = 0>
+ explicit GCompileArg(T &&t)
+ : tag(detail::CompileArgTag<typename std::decay<T>::type>::tag())
+ , arg(t)
+ {
+ }
+
+ template<typename T> T& get()
+ {
+ return util::any_cast<T>(arg);
+ }
+
+ template<typename T> const T& get() const
+ {
+ return util::any_cast<T>(arg);
+ }
+
+private:
+ util::any arg;
+};
+
+using GCompileArgs = std::vector<GCompileArg>;
+
+/**
+ * Wraps a list of arguments (a parameter pack) into a vector of
+ * compilation arguments (cv::GCompileArg).
+ */
+template<typename... Ts> GCompileArgs compile_args(Ts&&... args)
+{
+ return GCompileArgs{ GCompileArg(args)... };
+}
+
+/**
+ * @brief Ask G-API to dump compiled graph in Graphviz format under
+ * the given file name.
+ *
+ * Specifies a graph dump path (path to .dot file to be generated).
+ * G-API will dump a .dot file under specified path during a
+ * compilation process if this flag is passed.
+ */
+struct graph_dump_path
+{
+ std::string m_dump_path;
+};
+/** @} */
+
+namespace detail
+{
+ template<> struct CompileArgTag<cv::graph_dump_path>
+ {
+ static const char* tag() { return "gapi.graph_dump_path"; }
+ };
+}
+
+} // namespace cv
+
+// std::hash overload for GShape
+namespace std
+{
+template<> struct hash<cv::GShape>
+{
+ size_t operator() (cv::GShape sh) const
+ {
+ return std::hash<int>()(static_cast<int>(sh));
+ }
+};
+} // namespace std
+
+
+#endif // OPENCV_GAPI_GCOMMON_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompiled.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompiled.hpp
new file mode 100644
index 000000000..ad491b733
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompiled.hpp
@@ -0,0 +1,217 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCOMPILED_HPP
+#define OPENCV_GAPI_GCOMPILED_HPP
+
+#include <vector>
+
+#include "opencv2/gapi/opencv_includes.hpp"
+#include "opencv2/gapi/own/assert.hpp"
+#include "opencv2/gapi/garg.hpp"
+
+namespace cv {
+
+// This class represents a compiled computation.
+// In theory (and ideally), it can be used w/o the rest of APIs.
+// In theory (and ideally), it can be serialized/deserialized.
+// It can enable scenarious like deployment to an autonomous devince, FuSa, etc.
+//
+// Currently GCompiled assumes all GMats you used to pass data to G-API
+// are valid and not destroyed while you use a GCompiled object.
+//
+// FIXME: In future, there should be a way to name I/O objects and specify it
+// to GCompiled externally (for example, when it is loaded on the target system).
+
+/**
+ * \addtogroup gapi_main_classes
+ * @{
+ */
+/**
+ * @brief Represents a compiled computation (graph). Can only be used
+ * with image / data formats & resolutions it was compiled for, with
+ * some exceptions.
+ *
+ * This class represents a product of graph compilation (calling
+ * cv::GComputation::compile()). Objects of this class actually do
+ * data processing, and graph execution is incapsulated into objects
+ * of this class. Execution model itself depends on kernels and
+ * backends which were using during the compilation, see @ref
+ * gapi_compile_args for details.
+ *
+ * In a general case, GCompiled objects can be applied to data only in
+ * that formats/resolutions they were compiled for (see @ref
+ * gapi_meta_args). However, if the underlying backends allow, a
+ * compiled object can be _reshaped_ to handle data (images) of
+ * different resolution, though formats and types must remain the same.
+ *
+ * GCompiled is very similar to `std::function<>` in its semantics --
+ * running it looks like a function call in the user code.
+ *
+ * At the moment, GCompiled objects are not reentrant -- generally,
+ * the objects are stateful since graph execution itself is a stateful
+ * process and this state is now maintained in GCompiled's own memory
+ * (not on the process stack).
+ *
+ * At the same time, two different GCompiled objects produced from the
+ * single cv::GComputation are completely independent and can be used
+ * concurrently.
+ */
+class GAPI_EXPORTS GCompiled
+{
+public:
+ /// @private
+ class GAPI_EXPORTS Priv;
+
+ /**
+ * @brief Constructs an empty object
+ */
+ GCompiled();
+
+ /**
+ * @brief Run the compiled computation, a generic version.
+ *
+ * @param ins vector of inputs to process.
+ * @param outs vector of outputs to produce.
+ *
+ * Input/output vectors must have the same number of elements as
+ * defined in the cv::GComputation protocol (at the moment of its
+ * construction). Shapes of elements also must conform to protocol
+ * (e.g. cv::Mat needs to be passed where cv::GMat has been
+ * declared as input, and so on). Run-time exception is generated
+ * otherwise.
+ *
+ * Objects in output vector may remain empty (like cv::Mat) --
+ * G-API will automatically initialize output objects to proper formats.
+ *
+ * @note Don't construct GRunArgs/GRunArgsP objects manually, use
+ * cv::gin()/cv::gout() wrappers instead.
+ */
+ void operator() (GRunArgs &&ins, GRunArgsP &&outs); // Generic arg-to-arg
+#if !defined(GAPI_STANDALONE)
+
+ /**
+ * @brief Execute an unary computation
+ *
+ * @overload
+ * @param in input cv::Mat for unary computation
+ * @param out output cv::Mat for unary computation
+ * process.
+ */
+ void operator() (cv::Mat in, cv::Mat &out); // Unary overload
+
+ /**
+ * @brief Execute an unary computation
+ *
+ * @overload
+ * @param in input cv::Mat for unary computation
+ * @param out output cv::Scalar for unary computation
+ * process.
+ */
+ void operator() (cv::Mat in, cv::Scalar &out); // Unary overload (scalar)
+
+ /**
+ * @brief Execute a binary computation
+ *
+ * @overload
+ * @param in1 first input cv::Mat for binary computation
+ * @param in2 second input cv::Mat for binary computation
+ * @param out output cv::Mat for binary computation
+ * process.
+ */
+ void operator() (cv::Mat in1, cv::Mat in2, cv::Mat &out); // Binary overload
+
+ /**
+ * @brief Execute an binary computation
+ *
+ * @overload
+ * @param in1 first input cv::Mat for binary computation
+ * @param in2 second input cv::Mat for binary computation
+ * @param out output cv::Scalar for binary computation
+ * process.
+ */
+ void operator() (cv::Mat in1, cv::Mat in2, cv::Scalar &out); // Binary overload (scalar)
+
+ /**
+ * @brief Execute a computation with arbitrary number of
+ * inputs/outputs.
+ *
+ * @overload
+ * @param ins vector of input cv::Mat objects to process by the
+ * computation.
+ * @param outs vector of output cv::Mat objects to produce by the
+ * computation.
+ *
+ * Numbers of elements in ins/outs vectos must match numbers of
+ * inputs/outputs which were used to define the source GComputation.
+ */
+ void operator() (const std::vector<cv::Mat> &ins, // Compatibility overload
+ const std::vector<cv::Mat> &outs);
+#endif // !defined(GAPI_STANDALONE)
+ /// @private
+ Priv& priv();
+
+ /**
+ * @brief Check if compiled object is valid (non-empty)
+ *
+ * @return true if the object is runnable (valid), false otherwise
+ */
+ explicit operator bool () const;
+
+ /**
+ * @brief Vector of metadata this graph was compiled for.
+ *
+ * @return Unless _reshape_ is not supported, return value is the
+ * same vector which was passed to cv::GComputation::compile() to
+ * produce this compiled object. Otherwise, it is the latest
+ * metadata vector passed to reshape() (if that call was
+ * successful).
+ */
+ const GMetaArgs& metas() const; // Meta passed to compile()
+
+ /**
+ * @brief Vector of metadata descriptions of graph outputs
+ *
+ * @return vector with formats/resolutions of graph's output
+ * objects, auto-inferred from input metadata vector by
+ * operations which form this computation.
+ *
+ * @note GCompiled objects produced from the same
+ * cv::GComputiation graph with different input metas may return
+ * different values in this vector.
+ */
+ const GMetaArgs& outMetas() const;
+
+ /**
+ * @brief Check if the underlying backends support reshape or not.
+ *
+ * @return true if supported, false otherwise.
+ */
+ bool canReshape() const;
+
+ /**
+ * @brief Reshape a compiled graph to support new image
+ * resolutions.
+ *
+ * Throws an exception if an error occurs.
+ *
+ * @param inMetas new metadata to reshape on. Vector size and
+ * metadata shapes must match the computation's protocol.
+ * @param args compilation arguments to use.
+ */
+ // FIXME: Why it requires compile args?
+ void reshape(const GMetaArgs& inMetas, const GCompileArgs& args);
+
+protected:
+ /// @private
+ std::shared_ptr<Priv> m_priv;
+};
+/** @} */
+
+}
+
+#endif // OPENCV_GAPI_GCOMPILED_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompoundkernel.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompoundkernel.hpp
new file mode 100644
index 000000000..c5ac8a7d2
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcompoundkernel.hpp
@@ -0,0 +1,123 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCOMPOUNDKERNEL_HPP
+#define OPENCV_GAPI_GCOMPOUNDKERNEL_HPP
+
+#include <opencv2/gapi/opencv_includes.hpp>
+#include <opencv2/gapi/gcommon.hpp>
+#include <opencv2/gapi/gkernel.hpp>
+#include <opencv2/gapi/garg.hpp>
+
+namespace cv {
+namespace gapi
+{
+namespace compound
+{
+ // FIXME User does not need to know about this function
+ // Needs that user may define compound kernels(as cpu kernels)
+ GAPI_EXPORTS cv::gapi::GBackend backend();
+} // namespace compound
+} // namespace gapi
+
+namespace detail
+{
+
+struct GCompoundContext
+{
+ explicit GCompoundContext(const GArgs& in_args);
+ template<typename T>
+ const T& inArg(int input) { return m_args.at(input).get<T>(); }
+
+ GArgs m_args;
+ GArgs m_results;
+};
+
+class GAPI_EXPORTS GCompoundKernel
+{
+// Compound kernel must use all of it's inputs
+public:
+ using F = std::function<void(GCompoundContext& ctx)>;
+
+ explicit GCompoundKernel(const F& f);
+ void apply(GCompoundContext& ctx);
+
+protected:
+ F m_f;
+};
+
+template<typename T> struct get_compound_in
+{
+ static T get(GCompoundContext &ctx, int idx) { return ctx.inArg<T>(idx); }
+};
+
+template<typename U> struct get_compound_in<cv::GArray<U>>
+{
+ static cv::GArray<U> get(GCompoundContext &ctx, int idx)
+ {
+ auto array = cv::GArray<U>();
+ ctx.m_args[idx] = GArg(array);
+ return array;
+ }
+};
+
+// Kernel may return one object(GMat, GScalar) or a tuple of objects.
+// This helper is needed to cast return value to the same form(tuple)
+template<typename>
+struct tuple_wrap_helper;
+
+template<typename T> struct tuple_wrap_helper
+{
+ static std::tuple<T> get(T&& obj) { return std::make_tuple(std::move(obj)); }
+};
+
+template<typename... Objs>
+struct tuple_wrap_helper<std::tuple<Objs...>>
+{
+ static std::tuple<Objs...> get(std::tuple<Objs...>&& objs) { return objs; }
+};
+
+template<typename, typename, typename>
+struct GCompoundCallHelper;
+
+template<typename Impl, typename... Ins, typename... Outs>
+struct GCompoundCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
+{
+ template<int... IIs, int... OIs>
+ static void expand_impl(GCompoundContext &ctx, detail::Seq<IIs...>, detail::Seq<OIs...>)
+ {
+ auto result = Impl::expand(get_compound_in<Ins>::get(ctx, IIs)...);
+ auto tuple_return = tuple_wrap_helper<decltype(result)>::get(std::move(result));
+ ctx.m_results = { cv::GArg(std::get<OIs>(tuple_return))... };
+ }
+
+ static void expand(GCompoundContext &ctx)
+ {
+ expand_impl(ctx,
+ typename detail::MkSeq<sizeof...(Ins)>::type(),
+ typename detail::MkSeq<sizeof...(Outs)>::type());
+ }
+};
+
+template<class Impl, class K>
+class GCompoundKernelImpl: public cv::detail::GCompoundCallHelper<Impl, typename K::InArgs, typename K::OutArgs>
+{
+ using P = cv::detail::GCompoundCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
+
+public:
+ using API = K;
+
+ static cv::gapi::GBackend backend() { return cv::gapi::compound::backend(); }
+ static GCompoundKernel kernel() { return GCompoundKernel(&P::expand); }
+};
+
+} // namespace detail
+#define GAPI_COMPOUND_KERNEL(Name, API) struct Name: public cv::detail::GCompoundKernelImpl<Name, API>
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GCOMPOUNDKERNEL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcomputation.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcomputation.hpp
new file mode 100644
index 000000000..e89b9ae39
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gcomputation.hpp
@@ -0,0 +1,456 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCOMPUTATION_HPP
+#define OPENCV_GAPI_GCOMPUTATION_HPP
+
+#include <functional>
+
+#include "opencv2/gapi/util/util.hpp"
+#include "opencv2/gapi/gcommon.hpp"
+#include "opencv2/gapi/gproto.hpp"
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gcompiled.hpp"
+
+namespace cv {
+
+namespace detail
+{
+ // FIXME: move to algorithm, cover with separate tests
+ // FIXME: replace with O(1) version (both memory and compilation time)
+ template<typename...>
+ struct last_type;
+
+ template<typename T>
+ struct last_type<T> { using type = T;};
+
+ template<typename T, typename... Ts>
+ struct last_type<T, Ts...> { using type = typename last_type<Ts...>::type; };
+
+ template<typename... Ts>
+ using last_type_t = typename last_type<Ts...>::type;
+}
+
+/**
+ * \addtogroup gapi_main_classes
+ * @{
+ */
+/**
+ * @brief GComputation class represents a captured computation
+ * graph. GComputation objects form boundaries for expression code
+ * user writes with G-API, allowing to compile and execute it.
+ *
+ * G-API computations are defined with input/output data
+ * objects. G-API will track automatically which operations connect
+ * specified outputs to the inputs, forming up a call graph to be
+ * 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
+ *
+ * Full pipeline can be now captured with this object declaration:
+ *
+ * @snippet modules/gapi/samples/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
+ * cv::GOut. G-API will track automatically which operations form a
+ * path from inputs to outputs and build the execution graph appropriately.
+ *
+ * Note that cv::GComputation doesn't take ownership on data objects
+ * it is defined. Moreover, multiple GComputation objects may be
+ * defined on the same expressions, e.g. a smaller pipeline which
+ * expects that image gradients are already pre-calculated may be
+ * defined like this:
+ *
+ * @snippet modules/gapi/samples/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
+ * results of cv::gapi::Sobel operators -- G-API will stop unrolling
+ * expressions and building the underlying graph one reaching this
+ * data objects.
+ *
+ * The way how GComputation is defined is important as its definition
+ * specifies graph _protocol_ -- the way how the graph should be
+ * used. Protocol is defined by number of inputs, number of outputs,
+ * and shapes of inputs and outputs.
+ *
+ * In the above example, sobelEdge expects one Mat on input and
+ * produces one Mat; while sobelEdgeSub expects two Mats on input and
+ * produces one Mat. GComputation's protocol defines how other
+ * computaion methods should be used -- cv::GComputation::compile() and
+ * cv::GComputation::apply(). For example, if a graph is defined on
+ * two GMat inputs, two cv::Mat objects have to be passed to apply()
+ * for execution. GComputation checks protocol correctness in runtime
+ * so passing a different number of objects in apply() or passing
+ * cv::Scalar instead of cv::Mat there would compile well as a C++
+ * source but raise an exception in run-time. G-API also comes with a
+ * typed wrapper cv::GComputationT<> which introduces this type-checking in
+ * compile-time.
+ *
+ * cv::GComputation itself is a thin object which just captures what
+ * the graph is. The compiled graph (which actually process data) is
+ * represented by class GCompiled. Use compile() method to generate a
+ * compiled graph with given compile options. cv::GComputation can
+ * also be used to process data with implicit graph compilation
+ * on-the-fly, see apply() for details.
+ *
+ * GComputation is a reference-counted object -- once defined, all its
+ * copies will refer to the same instance.
+ *
+ * @sa GCompiled
+ */
+class GAPI_EXPORTS GComputation
+{
+public:
+ class Priv;
+ typedef std::function<GComputation()> Generator;
+
+ // Various constructors enable different ways to define a computation: /////
+ // 1. Generic constructors
+ /**
+ * @brief Define a computation using a generator function.
+ *
+ * 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
+ *
+ * This may be useful since all temporary objects (cv::GMats) and
+ * namespaces can be localized to scope of lambda, without
+ * contaminating the parent scope with probably unecessary objects
+ * and information.
+ *
+ * @param gen generator function which returns a cv::GComputation,
+ * see Generator.
+ */
+ GComputation(const Generator& gen); // Generator
+ // overload
+
+ /**
+ * @brief Generic GComputation constructor.
+ *
+ * Constructs a new graph with a given protocol, specified as a
+ * flow of operations connecting input/output objects. Throws if
+ * the passed boundaries are invalid, e.g. if there's no
+ * functional dependency (path) between given outputs and inputs.
+ *
+ * @param ins Input data vector.
+ * @param outs Output data vector.
+ *
+ * @note Don't construct GProtoInputArgs/GProtoOutputArgs objects
+ * directly, use cv::GIn()/cv::GOut() wrapper functions instead.
+ *
+ * @sa @ref gapi_data_objects
+ */
+ GComputation(GProtoInputArgs &&ins,
+ GProtoOutputArgs &&outs); // Arg-to-arg overload
+
+ // 2. Syntax sugar and compatibility overloads
+ /**
+ * @brief Defines an unary (one input -- one output) computation
+ *
+ * @overload
+ * @param in input GMat of the defined unary computation
+ * @param out output GMat of the defined unary computation
+ */
+ GComputation(GMat in, GMat out); // Unary overload
+
+ /**
+ * @brief Defines an unary (one input -- one output) computation
+ *
+ * @overload
+ * @param in input GMat of the defined unary computation
+ * @param out output GScalar of the defined unary computation
+ */
+ GComputation(GMat in, GScalar out); // Unary overload (scalar)
+
+ /**
+ * @brief Defines a binary (two inputs -- one output) computation
+ *
+ * @overload
+ * @param in1 first input GMat of the defined binary computation
+ * @param in2 second input GMat of the defined binary computation
+ * @param out output GMat of the defined binary computation
+ */
+ GComputation(GMat in1, GMat in2, GMat out); // Binary overload
+
+ /**
+ * @brief Defines a binary (two inputs -- one output) computation
+ *
+ * @overload
+ * @param in1 first input GMat of the defined binary computation
+ * @param in2 second input GMat of the defined binary computation
+ * @param out output GScalar of the defined binary computation
+ */
+ GComputation(GMat in1, GMat in2, GScalar out); // Binary
+ // overload
+ // (scalar)
+
+ /**
+ * @brief Defines a computation with arbitrary input/output number.
+ *
+ * @overload
+ * @param ins vector of inputs GMats for this computation
+ * @param outs vector of outputs GMats for this computation
+ *
+ * Use this overload for cases when number of computation
+ * inputs/outputs is not known in compile-time -- e.g. when graph
+ * is programmatically generated to build an image pyramid with
+ * the given number of levels, etc.
+ */
+ GComputation(const std::vector<GMat> &ins, // Compatibility overload
+ const std::vector<GMat> &outs);
+
+ // Various versions of apply(): ////////////////////////////////////////////
+ // 1. Generic apply()
+ /**
+ * @brief Compile graph on-the-fly and immediately execute it on
+ * the inputs data vectors.
+ *
+ * Number of input/output data objects must match GComputation's
+ * protocol, also types of host data objects (cv::Mat, cv::Scalar)
+ * must match the shapes of data objects from protocol (cv::GMat,
+ * cv::GScalar). If there's a mismatch, a run-time exception will
+ * be generated.
+ *
+ * Internally, a cv::GCompiled object is created for the given
+ * input format configuration, which then is executed on the input
+ * data immediately. cv::GComputation caches compiled objects
+ * produced within apply() -- if this method would be called next
+ * time with the same input parameters (image formats, image
+ * resolution, etc), the underlying compiled graph will be reused
+ * without recompilation. If new metadata doesn't match the cached
+ * one, the underlying compiled graph is regenerated.
+ *
+ * @note compile() always triggers a compilation process and
+ * produces a new GCompiled object regardless if a similar one has
+ * been cached via apply() or not.
+ *
+ * @param ins vector of input data to process. Don't create
+ * GRunArgs object manually, use cv::gin() wrapper instead.
+ * @param outs vector of output data to fill results in. cv::Mat
+ * objects may be empty in this vector, G-API will automatically
+ * initialize it with the required format & dimensions. Don't
+ * create GRunArgsP object manually, use cv::gout() wrapper instead.
+ * @param args a list of compilation arguments to pass to the
+ * underlying compilation process. Don't create GCompileArgs
+ * object manually, use cv::compile_args() wrapper instead.
+ *
+ * @sa @ref gapi_data_objects, @ref gapi_compile_args
+ */
+ void apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); // Arg-to-arg overload
+
+ /// @private -- Exclude this function from OpenCV documentation
+ void apply(const std::vector<cv::gapi::own::Mat>& ins, // Compatibility overload
+ const std::vector<cv::gapi::own::Mat>& outs,
+ GCompileArgs &&args = {});
+
+ // 2. Syntax sugar and compatibility overloads
+#if !defined(GAPI_STANDALONE)
+ /**
+ * @brief Execute an unary computation (with compilation on the fly)
+ *
+ * @overload
+ * @param in input cv::Mat for unary computation
+ * @param out output cv::Mat for unary computation
+ * @param args compilation arguments for underlying compilation
+ * process.
+ */
+ void apply(cv::Mat in, cv::Mat &out, GCompileArgs &&args = {}); // Unary overload
+
+ /**
+ * @brief Execute an unary computation (with compilation on the fly)
+ *
+ * @overload
+ * @param in input cv::Mat for unary computation
+ * @param out output cv::Scalar for unary computation
+ * @param args compilation arguments for underlying compilation
+ * process.
+ */
+ void apply(cv::Mat in, cv::Scalar &out, GCompileArgs &&args = {}); // Unary overload (scalar)
+
+ /**
+ * @brief Execute a binary computation (with compilation on the fly)
+ *
+ * @overload
+ * @param in1 first input cv::Mat for binary computation
+ * @param in2 second input cv::Mat for binary computation
+ * @param out output cv::Mat for binary computation
+ * @param args compilation arguments for underlying compilation
+ * process.
+ */
+ void apply(cv::Mat in1, cv::Mat in2, cv::Mat &out, GCompileArgs &&args = {}); // Binary overload
+
+ /**
+ * @brief Execute an binary computation (with compilation on the fly)
+ *
+ * @overload
+ * @param in1 first input cv::Mat for binary computation
+ * @param in2 second input cv::Mat for binary computation
+ * @param out output cv::Scalar for binary computation
+ * @param args compilation arguments for underlying compilation
+ * process.
+ */
+ void apply(cv::Mat in1, cv::Mat in2, cv::Scalar &out, GCompileArgs &&args = {}); // Binary overload (scalar)
+
+ /**
+ * @brief Execute a computation with arbitrary number of
+ * inputs/outputs (with compilation on-the-fly).
+ *
+ * @overload
+ * @param ins vector of input cv::Mat objects to process by the
+ * computation.
+ * @param outs vector of output cv::Mat objects to produce by the
+ * computation.
+ * @param args compilation arguments for underlying compilation
+ * process.
+ *
+ * Numbers of elements in ins/outs vectos must match numbers of
+ * inputs/outputs which were used to define this GComputation.
+ */
+ void apply(const std::vector<cv::Mat>& ins, // Compatibility overload
+ const std::vector<cv::Mat>& outs,
+ GCompileArgs &&args = {});
+#endif // !defined(GAPI_STANDALONE)
+ // Various versions of compile(): //////////////////////////////////////////
+ // 1. Generic compile() - requires metas to be passed as vector
+ /**
+ * @brief Compile the computation for specific input format(s).
+ *
+ * This method triggers compilation process and produces a new
+ * GCompiled object which then can process data of the given
+ * format. Passing data with different format to the compiled
+ * computation will generate a run-time exception.
+ *
+ * @param in_metas vector of input metadata configuration. Grab
+ * metadata from real data objects (like cv::Mat or cv::Scalar)
+ * using cv::descr_of(), or create it on your own.
+ * @param args compilation arguments for this compilation
+ * process. Compilation arguments directly affect what kind of
+ * executable object would be produced, e.g. which kernels (and
+ * thus, devices) would be used to execute computation.
+ *
+ * @return GCompiled, an executable computation compiled
+ * specifically for the given input parameters.
+ *
+ * @sa @ref gapi_compile_args
+ */
+ GCompiled compile(GMetaArgs &&in_metas, GCompileArgs &&args = {});
+
+ // 2. Syntax sugar - variadic list of metas, no extra compile args
+ // FIXME: SFINAE looks ugly in the generated documentation
+ /**
+ * @overload
+ *
+ * Takes a variadic parameter pack with metadata
+ * descriptors for which a compiled object needs to be produced.
+ *
+ * @return GCompiled, an executable computation compiled
+ * specifically for the given input parameters.
+ */
+ template<typename... Ts>
+ auto compile(const Ts&... metas) ->
+ typename std::enable_if<detail::are_meta_descrs<Ts...>::value, GCompiled>::type
+ {
+ return compile(GMetaArgs{GMetaArg(metas)...}, GCompileArgs());
+ }
+
+ // 3. Syntax sugar - variadic list of metas, extra compile args
+ // (seems optional parameters don't work well when there's an variadic template
+ // comes first)
+ //
+ // Ideally it should look like:
+ //
+ // template<typename... Ts>
+ // GCompiled compile(const Ts&... metas, GCompileArgs &&args)
+ //
+ // But not all compilers can hande this (and seems they shouldn't be able to).
+ // FIXME: SFINAE looks ugly in the generated documentation
+ /**
+ * @overload
+ *
+ * Takes a variadic parameter pack with metadata
+ * descriptors for which a compiled object needs to be produced,
+ * followed by GCompileArgs object representing compilation
+ * arguments for this process.
+ *
+ * @return GCompiled, an executable computation compiled
+ * specifically for the given input parameters.
+ */
+ template<typename... Ts>
+ auto compile(const Ts&... meta_and_compile_args) ->
+ typename std::enable_if<detail::are_meta_descrs_but_last<Ts...>::value
+ && std::is_same<GCompileArgs, detail::last_type_t<Ts...> >::value,
+ GCompiled>::type
+ {
+ //FIXME: wrapping meta_and_compile_args into a tuple to unwrap them inside a helper function is the overkill
+ return compile(std::make_tuple(meta_and_compile_args...),
+ typename detail::MkSeq<sizeof...(Ts)-1>::type());
+ }
+
+ // Internal use only
+ /// @private
+ Priv& priv();
+ /// @private
+ const Priv& priv() const;
+
+protected:
+
+ // 4. Helper method for (3)
+ /// @private
+ template<typename... Ts, int... IIs>
+ GCompiled compile(const std::tuple<Ts...> &meta_and_compile_args, detail::Seq<IIs...>)
+ {
+ GMetaArgs meta_args = {GMetaArg(std::get<IIs>(meta_and_compile_args))...};
+ GCompileArgs comp_args = std::get<sizeof...(Ts)-1>(meta_and_compile_args);
+ return compile(std::move(meta_args), std::move(comp_args));
+ }
+ /// @private
+ std::shared_ptr<Priv> m_priv;
+};
+/** @} */
+
+namespace gapi
+{
+ // FIXME: all these standalone functions need to be added to some
+ // common documentation section
+ /**
+ * @brief Define an tagged island (subgraph) within a computation.
+ *
+ * Declare an Island tagged with `name` and defined from `ins` to `outs`
+ * (exclusively, as ins/outs are data objects, and regioning is done on
+ * operations level).
+ * Throws if any operation between `ins` and `outs` are already assigned
+ * to another island.
+ *
+ * Islands allow to partition graph into subgraphs, fine-tuning
+ * the way it is scheduled by the underlying executor.
+ *
+ * @param name name of the Island to create
+ * @param ins vector of input data objects where the subgraph
+ * begins
+ * @param outs vector of output data objects where the subgraph
+ * ends.
+ *
+ * The way how an island is defined is similar to how
+ * cv::GComputation is defined on input/output data objects.
+ * Same rules apply here as well -- if there's no functional
+ * dependency between inputs and outputs or there's not enough
+ * input data objects were specified to properly calculate all
+ * outputs, an exception is thrown.
+ *
+ * Use cv::GIn() / cv::GOut() to specify input/output vectors.
+ */
+ void GAPI_EXPORTS island(const std::string &name,
+ GProtoInputArgs &&ins,
+ GProtoOutputArgs &&outs);
+} // namespace gapi
+
+} // namespace cv
+#endif // OPENCV_GAPI_GCOMPUTATION_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gkernel.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gkernel.hpp
new file mode 100644
index 000000000..adc7da3c7
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gkernel.hpp
@@ -0,0 +1,563 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GKERNEL_HPP
+#define OPENCV_GAPI_GKERNEL_HPP
+
+#include <functional>
+#include <iostream>
+#include <string> // string
+#include <type_traits> // false_type, true_type
+#include <unordered_map> // map (for GKernelPackage)
+#include <utility> // tuple
+#include <vector> // lookup order
+
+#include <opencv2/gapi/gcommon.hpp> // CompileArgTag
+#include <opencv2/gapi/util/util.hpp> // Seq
+#include <opencv2/gapi/gcall.hpp>
+#include <opencv2/gapi/garg.hpp> // GArg
+#include <opencv2/gapi/gmetaarg.hpp> // GMetaArg
+#include <opencv2/gapi/gtype_traits.hpp> // GTypeTraits
+#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
+
+
+namespace cv {
+
+using GShapes = std::vector<GShape>;
+
+// GKernel describes kernel API to the system
+// FIXME: add attributes of a kernel, (e.g. number and types
+// of inputs, etc)
+struct GAPI_EXPORTS GKernel
+{
+ using M = std::function<GMetaArgs(const GMetaArgs &, const GArgs &)>;
+
+ const std::string name; // kernel ID, defined by its API (signature)
+ const M outMeta; // generic adaptor to API::outMeta(...)
+ const GShapes outShapes; // types (shapes) kernel's outputs
+};
+
+// GKernelImpl describes particular kernel implementation to the system
+struct GAPI_EXPORTS GKernelImpl
+{
+ util::any opaque; // backend-specific opaque info
+};
+
+template<typename, typename> class GKernelTypeM;
+
+namespace detail
+{
+ ////////////////////////////////////////////////////////////////////////////
+ // yield() is used in graph construction time as a generic method to obtain
+ // lazy "return value" of G-API operations
+ //
+ namespace
+ {
+
+ template<typename T> struct Yield;
+ template<> struct Yield<cv::GMat>
+ {
+ static inline cv::GMat yield(cv::GCall &call, int i) { return call.yield(i); }
+ };
+ template<> struct Yield<cv::GScalar>
+ {
+ static inline cv::GScalar yield(cv::GCall &call, int i) { return call.yieldScalar(i); }
+ };
+ template<typename U> struct Yield<cv::GArray<U> >
+ {
+ static inline cv::GArray<U> yield(cv::GCall &call, int i) { return call.yieldArray<U>(i); }
+ };
+ } // anonymous namespace
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Helper classes which brings outputMeta() marshalling to kernel
+ // implementations
+ //
+ // 1. MetaType establishes G#Type -> G#Meta mapping between G-API dynamic
+ // types and its metadata descriptor types.
+ // This mapping is used to transform types to call outMeta() callback.
+ template<typename T> struct MetaType;
+ template<> struct MetaType<cv::GMat> { using type = GMatDesc; };
+ template<> struct MetaType<cv::GScalar> { using type = GScalarDesc; };
+ template<typename U> struct MetaType<cv::GArray<U> > { using type = GArrayDesc; };
+ template<typename T> struct MetaType { using type = T; }; // opaque args passed as-is
+
+ // 2. Hacky test based on MetaType to check if we operate on G-* type or not
+ template<typename T> using is_nongapi_type = std::is_same<T, typename MetaType<T>::type>;
+
+ // 3. Two ways to transform input arguments to its meta - for G-* and non-G* types:
+ template<typename T>
+ typename std::enable_if<!is_nongapi_type<T>::value, typename MetaType<T>::type>
+ ::type get_in_meta(const GMetaArgs &in_meta, const GArgs &, int idx)
+ {
+ return util::get<typename MetaType<T>::type>(in_meta.at(idx));
+ }
+
+ template<typename T>
+ typename std::enable_if<is_nongapi_type<T>::value, T>
+ ::type get_in_meta(const GMetaArgs &, const GArgs &in_args, int idx)
+ {
+ return in_args.at(idx).template get<T>();
+ }
+
+ // 4. The MetaHelper itself: an entity which generates outMeta() call
+ // based on kernel signature, with arguments properly substituted.
+ // 4.1 - case for multiple return values
+ // FIXME: probably can be simplified with std::apply or analogue.
+ template<typename, typename, typename>
+ struct MetaHelper;
+
+ template<typename K, typename... Ins, typename... Outs>
+ struct MetaHelper<K, std::tuple<Ins...>, std::tuple<Outs...> >
+ {
+ template<int... IIs, int... OIs>
+ static GMetaArgs getOutMeta_impl(const GMetaArgs &in_meta,
+ const GArgs &in_args,
+ detail::Seq<IIs...>,
+ detail::Seq<OIs...>)
+ {
+ // FIXME: decay?
+ using R = std::tuple<typename MetaType<Outs>::type...>;
+ const R r = K::outMeta( get_in_meta<Ins>(in_meta, in_args, IIs)... );
+ return GMetaArgs{ GMetaArg(std::get<OIs>(r))... };
+ }
+ // FIXME: help users identify how outMeta must look like (via default impl w/static_assert?)
+
+ static GMetaArgs getOutMeta(const GMetaArgs &in_meta,
+ const GArgs &in_args)
+ {
+ return getOutMeta_impl(in_meta,
+ in_args,
+ typename detail::MkSeq<sizeof...(Ins)>::type(),
+ typename detail::MkSeq<sizeof...(Outs)>::type());
+ }
+ };
+
+ // 4.1 - case for a single return value
+ // FIXME: How to avoid duplication here?
+ template<typename K, typename... Ins, typename Out>
+ struct MetaHelper<K, std::tuple<Ins...>, Out >
+ {
+ template<int... IIs>
+ static GMetaArgs getOutMeta_impl(const GMetaArgs &in_meta,
+ const GArgs &in_args,
+ detail::Seq<IIs...>)
+ {
+ // FIXME: decay?
+ using R = typename MetaType<Out>::type;
+ const R r = K::outMeta( get_in_meta<Ins>(in_meta, in_args, IIs)... );
+ return GMetaArgs{ GMetaArg(r) };
+ }
+ // FIXME: help users identify how outMeta must look like (via default impl w/static_assert?)
+
+ static GMetaArgs getOutMeta(const GMetaArgs &in_meta,
+ const GArgs &in_args)
+ {
+ return getOutMeta_impl(in_meta,
+ in_args,
+ typename detail::MkSeq<sizeof...(Ins)>::type());
+ }
+ };
+
+} // namespace detail
+
+// GKernelType and GKernelTypeM are base classes which implement typed ::on()
+// method based on kernel signature. GKernelTypeM stands for multiple-return-value kernels
+//
+// G_TYPED_KERNEL and G_TYPED_KERNEK_M macros inherit user classes from GKernelType and
+// GKernelTypeM respectively.
+
+template<typename K, typename... R, typename... Args>
+class GKernelTypeM<K, std::function<std::tuple<R...>(Args...)> >:
+ public detail::MetaHelper<K, std::tuple<Args...>, std::tuple<R...> >
+{
+ template<int... IIs>
+ static std::tuple<R...> yield(cv::GCall &call, detail::Seq<IIs...>)
+ {
+ return std::make_tuple(detail::Yield<R>::yield(call, IIs)...);
+ }
+
+public:
+ using InArgs = std::tuple<Args...>;
+ using OutArgs = std::tuple<R...>;
+
+ static std::tuple<R...> on(Args... args)
+ {
+ cv::GCall call(GKernel{K::id(), &K::getOutMeta, {detail::GTypeTraits<R>::shape...}});
+ call.pass(args...);
+ return yield(call, typename detail::MkSeq<sizeof...(R)>::type());
+ }
+};
+
+template<typename, typename> class GKernelType;
+
+template<typename K, typename R, typename... Args>
+class GKernelType<K, std::function<R(Args...)> >:
+ public detail::MetaHelper<K, std::tuple<Args...>, R >
+{
+public:
+ using InArgs = std::tuple<Args...>;
+ using OutArgs = std::tuple<R>;
+
+ static R on(Args... args)
+ {
+ cv::GCall call(GKernel{K::id(), &K::getOutMeta, {detail::GTypeTraits<R>::shape}});
+ call.pass(args...);
+ return detail::Yield<R>::yield(call, 0);
+ }
+};
+
+} // namespace cv
+
+
+// FIXME: I don't know a better way so far. Feel free to suggest one
+// The problem is that every typed kernel should have ::id() but body
+// of the class is defined by user (with outMeta, other stuff)
+
+#define G_ID_HELPER_CLASS(Class) Class##IdHelper
+
+#define G_ID_HELPER_BODY(Class, Id) \
+ namespace detail \
+ { \
+ struct G_ID_HELPER_CLASS(Class) \
+ { \
+ static constexpr const char * id() {return Id;}; \
+ }; \
+ }
+
+#define G_TYPED_KERNEL(Class, API, Id) \
+ G_ID_HELPER_BODY(Class, Id) \
+ struct Class final: public cv::GKernelType<Class, std::function API >, \
+ public detail::G_ID_HELPER_CLASS(Class)
+// {body} is to be defined by user
+
+#define G_TYPED_KERNEL_M(Class, API, Id) \
+ G_ID_HELPER_BODY(Class, Id) \
+ struct Class final: public cv::GKernelTypeM<Class, std::function API >, \
+ public detail::G_ID_HELPER_CLASS(Class) \
+// {body} is to be defined by user
+
+namespace cv
+{
+// Declare <unite> in cv:: namespace
+enum class unite_policy
+{
+ REPLACE,
+ KEEP
+};
+
+namespace gapi
+{
+ // Prework: model "Device" API before it gets to G-API headers.
+ // FIXME: Don't mix with internal Backends class!
+ class GAPI_EXPORTS GBackend
+ {
+ public:
+ class Priv;
+
+ // TODO: make it template (call `new` within??)
+ GBackend();
+ explicit GBackend(std::shared_ptr<Priv> &&p);
+
+ Priv& priv();
+ const Priv& priv() const;
+ std::size_t hash() const;
+
+ bool operator== (const GBackend &rhs) const;
+
+ private:
+ std::shared_ptr<Priv> m_priv;
+ };
+
+ inline bool operator != (const GBackend &lhs, const GBackend &rhs)
+ {
+ return !(lhs == rhs);
+ }
+} // namespace gapi
+} // namespace cv
+
+namespace std
+{
+ template<> struct hash<cv::gapi::GBackend>
+ {
+ std::size_t operator() (const cv::gapi::GBackend &b) const
+ {
+ return b.hash();
+ }
+ };
+} // namespace std
+
+
+namespace cv {
+namespace gapi {
+ /** \addtogroup gapi_compile_args
+ * @{
+ */
+
+ // Lookup order is in fact a vector of Backends to traverse during look-up
+ /**
+ * @brief Priority list of backends to use during kernel
+ * resolution process.
+ *
+ * Priority is descending -- the first backend in the list has the
+ * top priority, and the last one has the lowest priority.
+ *
+ * If there's multiple implementations available for a kernel at
+ * the moment of graph compilation, a kernel (and thus a backend)
+ * will be selected according to this order (if the parameter is passed).
+ *
+ * Default order is not specified (and by default, only
+ * CPU(OpenCV) backend is involved in graph compilation).
+ */
+ using GLookupOrder = std::vector<GBackend>;
+ /**
+ * @brief Create a backend lookup order -- priority list of
+ * backends to use during graph compilation process.
+ *
+ * @sa GLookupOrder, @ref gapi_std_backends
+ */
+ inline GLookupOrder lookup_order(std::initializer_list<GBackend> &&list)
+ {
+ return GLookupOrder(std::move(list));
+ }
+
+ // FIXME: Hide implementation
+ /**
+ * @brief A container class for heterogeneous kernel
+ * implementation collections.
+ *
+ * GKernelPackage is a special container class which stores kernel
+ * _implementations_. Objects of this class are created and passed
+ * to cv::GComputation::compile() to specify which kernels to use
+ * in the compiled graph. GKernelPackage may contain kernels of
+ * different backends, e.g. be heterogeneous.
+ *
+ * The most easy way to create a kernel package is to use function
+ * cv::gapi::kernels(). This template functions takes kernel
+ * implementations in form of type list (variadic template) and
+ * generates a kernel package atop of that.
+ *
+ * Kernel packages can be also generated programatically, starting
+ * with an empty package (created with the default constructor)
+ * and then by populating it with kernels via call to
+ * GKernelPackage::include(). Note this method is also a template
+ * one since G-API kernel implementations are _types_, not objects.
+ *
+ * Finally, two kernel packages can be combined into a new one
+ * with function cv::gapi::combine(). There are different rules
+ * apply to this process, see also cv::gapi::unite_policy for
+ * details.
+ */
+ class GAPI_EXPORTS GKernelPackage
+ {
+ /// @private
+ using S = std::unordered_map<std::string, GKernelImpl>;
+
+ /// @private
+ using M = std::unordered_map<GBackend, S>;
+
+ /// @private
+ M m_backend_kernels;
+
+ protected:
+ /// @private
+ // Check if package contains ANY implementation of a kernel API
+ // by API textual id.
+ bool includesAPI(const std::string &id) const;
+
+ /// @private
+ // Remove ALL implementations of the given API (identified by ID)
+ void removeAPI(const std::string &id);
+
+ public:
+ /**
+ * @brief Returns total number of kernels in the package
+ * (accross all backends included)
+ *
+ * @return a number of kernels in the package
+ */
+ std::size_t size() const;
+
+ /**
+ * @brief Test if a particular kernel _implementation_ KImpl is
+ * included in this kernel package.
+ *
+ * @sa includesAPI()
+ *
+ * @return true if there is such kernel, false otherwise.
+ */
+ template<typename KImpl>
+ bool includes() const
+ {
+ const auto set_iter = m_backend_kernels.find(KImpl::backend());
+ return (set_iter != m_backend_kernels.end())
+ ? (set_iter->second.count(KImpl::API::id()) > 0)
+ : false;
+ }
+
+ /**
+ * @brief Remove all kernels associated with the given backend
+ * from the package.
+ *
+ * Does nothing if there's no kernels of this backend in the package.
+ *
+ * @param backend backend which kernels to remove
+ */
+ void remove(const GBackend& backend);
+
+ /**
+ * @brief Remove all kernels implementing the given API from
+ * the package.
+ *
+ * Does nothing if there's no kernels implementing the given interface.
+ */
+ template<typename KAPI>
+ void remove()
+ {
+ removeAPI(KAPI::id());
+ }
+
+ // FIXME: Rename to includes() and distinguish API/impl case by
+ // statically?
+ /**
+ * Check if package contains ANY implementation of a kernel API
+ * by API type.
+ */
+ template<typename KAPI>
+ bool includesAPI() const
+ {
+ return includesAPI(KAPI::id());
+ }
+
+ /**
+ * @brief Find a kernel (by its API), given the look-up order.
+ *
+ * If order is empty, returns first suitable implementation.
+ * Throws if nothing found.
+ *
+ * @return Backend which hosts matching kernel implementation.
+ *
+ * @sa cv::gapi::lookup_order
+ */
+ template<typename KAPI>
+ GBackend lookup(const GLookupOrder &order = {}) const
+ {
+ return lookup(KAPI::id(), order).first;
+ }
+
+ /// @private
+ std::pair<cv::gapi::GBackend, cv::GKernelImpl>
+ lookup(const std::string &id, const GLookupOrder &order = {}) const;
+
+ // FIXME: No overwrites allowed?
+ /**
+ * @brief Put a new kernel implementation KImpl into package.
+ *
+ * @param up unite policy to use. If the package has already
+ * implementation for this kernel (probably from another
+ * backend), and cv::unite_policy::KEEP is passed, the
+ * existing implementation remains in package; on
+ * cv::unite_policy::REPLACE all other existing
+ * implementations are first dropped from the package.
+ */
+ template<typename KImpl>
+ void include(const cv::unite_policy up = cv::unite_policy::KEEP)
+ {
+ auto backend = KImpl::backend();
+ auto kernel_id = KImpl::API::id();
+ auto kernel_impl = GKernelImpl{KImpl::kernel()};
+ if (up == cv::unite_policy::REPLACE) removeAPI(kernel_id);
+ else GAPI_Assert(up == cv::unite_policy::KEEP);
+
+ // Regardless of the policy, store new impl in its storage slot.
+ m_backend_kernels[backend][kernel_id] = std::move(kernel_impl);
+ }
+
+ /**
+ * @brief Lists all backends which are included into package
+ *
+ * @return vector of backends
+ */
+ std::vector<GBackend> backends() const;
+
+ // TODO: Doxygen bug -- it wants me to place this comment
+ // here, not below.
+ /**
+ * @brief Create a new package based on `lhs` and `rhs`,
+ * with unity policy defined by `policy`.
+ *
+ * @param lhs "Left-hand-side" package in the process
+ * @param rhs "Right-hand-side" package in the process
+ * @param policy Unite policy which is used in case of conflicts
+ * -- when the same kernel API is implemented in both packages by
+ * different backends; cv::unite_policy::KEEP keeps both
+ * implementation in the resulting package, while
+ * cv::unite_policy::REPLACE gives precedence two kernels from
+ * "Right-hand-side".
+ *
+ * @return a new kernel package.
+ */
+ friend GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &lhs,
+ const GKernelPackage &rhs,
+ const cv::unite_policy policy);
+ };
+
+ /**
+ * @brief Create a kernel package object containing kernels
+ * specified in variadic template argument.
+ *
+ * In G-API, kernel implementations are _types_. Every backend has
+ * its own kernel API (like GAPI_OCV_KERNEL() and
+ * GAPI_FLUID_KERNEL()) but all of that APIs define a new type for
+ * each kernel implementation.
+ *
+ * Use this function to pass kernel implementations (defined in
+ * either way) to the system. Example:
+ *
+ * @snippet modules/gapi/samples/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
+ * function call.
+ */
+ template<typename... KK> GKernelPackage kernels()
+ {
+ GKernelPackage pkg;
+
+ // For those who wonder - below is a trick to call a number of
+ // methods based on parameter pack (zeroes just help hiding these
+ // calls into a sequence which helps to expand this parameter pack).
+ // Just note that `f(),a` always equals to `a` (with f() called!)
+ // and parentheses are used to hide function call in the expanded sequence.
+ // Leading 0 helps to handle case when KK is an empty list (kernels<>()).
+
+ int unused[] = { 0, (pkg.include<KK>(), 0)... };
+ cv::util::suppress_unused_warning(unused);
+ return pkg;
+ };
+
+ /** @} */
+
+ GAPI_EXPORTS GKernelPackage combine(const GKernelPackage &lhs,
+ const GKernelPackage &rhs,
+ const cv::unite_policy policy);
+} // namespace gapi
+
+namespace detail
+{
+ template<> struct CompileArgTag<cv::gapi::GKernelPackage>
+ {
+ static const char* tag() { return "gapi.kernel_package"; }
+ };
+ template<> struct CompileArgTag<cv::gapi::GLookupOrder>
+ {
+ static const char* tag() { return "gapi.lookup_order"; }
+ };
+} // namespace detail
+} // namespace cv
+
+#endif // OPENCV_GAPI_GKERNEL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmat.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmat.hpp
new file mode 100644
index 000000000..0fa53427d
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmat.hpp
@@ -0,0 +1,149 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GMAT_HPP
+#define OPENCV_GAPI_GMAT_HPP
+
+#include <ostream>
+#include <memory> // std::shared_ptr
+
+#include <opencv2/gapi/opencv_includes.hpp>
+#include <opencv2/gapi/gcommon.hpp> // GShape
+
+#include "opencv2/gapi/own/types.hpp" // cv::gapi::own::Size
+#include "opencv2/gapi/own/convert.hpp" // to_own
+#include "opencv2/gapi/own/assert.hpp"
+
+// TODO GAPI_EXPORTS or so
+namespace cv
+{
+// Forward declaration; GNode and GOrigin are an internal
+// (user-inaccessible) classes.
+class GNode;
+struct GOrigin;
+
+/** \addtogroup gapi_data_objects
+ * @{
+ *
+ * @brief Data-representing objects which can be used to build G-API
+ * expressions.
+ */
+
+class GAPI_EXPORTS GMat
+{
+public:
+ GMat(); // Empty constructor
+ GMat(const GNode &n, std::size_t out); // Operation result constructor
+
+ GOrigin& priv(); // Internal use only
+ const GOrigin& priv() const; // Internal use only
+
+private:
+ std::shared_ptr<GOrigin> m_priv;
+};
+
+/** @} */
+
+/**
+ * \addtogroup gapi_meta_args
+ * @{
+ */
+struct GAPI_EXPORTS GMatDesc
+{
+ // FIXME: Default initializers in C++14
+ int depth;
+ int chan;
+ cv::gapi::own::Size size; // NB.: no multi-dimensional cases covered yet
+
+ inline bool operator== (const GMatDesc &rhs) const
+ {
+ return depth == rhs.depth && chan == rhs.chan && size == rhs.size;
+ }
+
+ inline bool operator!= (const GMatDesc &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ // 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::gapi::own::Size delta) const
+ {
+ GMatDesc desc(*this);
+ desc.size += delta;
+ return desc;
+ }
+#if !defined(GAPI_STANDALONE)
+ GMatDesc withSizeDelta(cv::Size delta) const
+ {
+ return withSizeDelta(to_own(delta));
+ }
+
+ GMatDesc withSize(cv::Size sz) const
+ {
+ return withSize(to_own(sz));
+ }
+#endif // !defined(GAPI_STANDALONE)
+ // Meta combinator: return a new GMatDesc which differs in size by delta
+ // (all other fields are taken unchanged from this GMatDesc)
+ //
+ // This is an overload.
+ GMatDesc withSizeDelta(int dx, int dy) const
+ {
+ return withSizeDelta(cv::gapi::own::Size{dx,dy});
+ }
+
+ GMatDesc withSize(cv::gapi::own::Size sz) const
+ {
+ GMatDesc desc(*this);
+ desc.size = sz;
+ return desc;
+ }
+
+ // 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_Assert(CV_MAT_CN(ddepth) == 1 || ddepth == -1);
+ GMatDesc desc(*this);
+ if (ddepth != -1) desc.depth = ddepth;
+ return desc;
+ }
+
+ // 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_Assert(CV_MAT_CN(ddepth) == 1 || ddepth == -1);
+ GMatDesc desc = withDepth(ddepth);
+ desc.chan = dchan;
+ return desc;
+ }
+};
+
+static inline GMatDesc empty_gmat_desc() { return GMatDesc{-1,-1,{-1,-1}}; }
+
+#if !defined(GAPI_STANDALONE)
+class Mat;
+GAPI_EXPORTS GMatDesc descr_of(const cv::Mat &mat);
+GAPI_EXPORTS GMatDesc descr_of(const cv::UMat &mat);
+#endif // !defined(GAPI_STANDALONE)
+
+/** @} */
+
+namespace gapi { namespace own {
+ class Mat;
+ GAPI_EXPORTS GMatDesc descr_of(const Mat &mat);
+}}//gapi::own
+
+std::ostream& operator<<(std::ostream& os, const cv::GMatDesc &desc);
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GMAT_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmetaarg.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmetaarg.hpp
new file mode 100644
index 000000000..473be342e
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gmetaarg.hpp
@@ -0,0 +1,66 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GMETAARG_HPP
+#define OPENCV_GAPI_GMETAARG_HPP
+
+#include <vector>
+#include <type_traits>
+
+#include "opencv2/gapi/util/util.hpp"
+#include "opencv2/gapi/util/variant.hpp"
+
+#include "opencv2/gapi/gmat.hpp"
+#include "opencv2/gapi/gscalar.hpp"
+#include "opencv2/gapi/garray.hpp"
+
+namespace cv
+{
+// FIXME: Rename to GMeta?
+// FIXME: user shouldn't deal with it - put to detail?
+// GMetaArg is an union type over descriptions of G-types which can serve as
+// GComputation's in/output slots.
+//
+// GMetaArg objects are passed as arguments to GComputation::compile()
+// to specify which data a compiled computation should be specialized on.
+// For manual compile(), user must supply this metadata, in case of apply()
+// this metadata is taken from arguments computation should operate on.
+//
+// The first type (monostate) is equal to "uninitialized"/"unresolved" meta.
+using GMetaArg = util::variant
+ < util::monostate
+ , GMatDesc
+ , GScalarDesc
+ , GArrayDesc
+ >;
+std::ostream& operator<<(std::ostream& os, const GMetaArg &);
+
+using GMetaArgs = std::vector<GMetaArg>;
+
+namespace detail
+{
+ // These traits are used by GComputation::compile()
+
+ // FIXME: is_constructible<T> doesn't work as variant doesn't do any SFINAE
+ // in its current template constructor
+
+ template<typename T> struct is_meta_descr : std::false_type {};
+ template<> struct is_meta_descr<GMatDesc> : std::true_type {};
+ template<> struct is_meta_descr<GScalarDesc> : std::true_type {};
+ template<> struct is_meta_descr<GArrayDesc> : std::true_type {};
+
+ template<typename... Ts>
+ using are_meta_descrs = all_satisfy<is_meta_descr, Ts...>;
+
+ template<typename... Ts>
+ using are_meta_descrs_but_last = all_satisfy<is_meta_descr, typename all_but_last<Ts...>::type>;
+
+} // namespace detail
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GMETAARG_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gproto.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gproto.hpp
new file mode 100644
index 000000000..8b53d9b64
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gproto.hpp
@@ -0,0 +1,96 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GPROTO_HPP
+#define OPENCV_GAPI_GPROTO_HPP
+
+#include <type_traits>
+#include <vector>
+#include <ostream>
+
+#include "opencv2/gapi/util/variant.hpp"
+
+#include "opencv2/gapi/gmat.hpp"
+#include "opencv2/gapi/gscalar.hpp"
+#include "opencv2/gapi/garray.hpp"
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gmetaarg.hpp"
+
+namespace cv {
+
+// FIXME: user shouldn't deal with it - put to detail?
+// GProtoArg is an union type over G-types which can serve as
+// GComputation's in/output slots. In other words, GProtoArg
+// wraps any type which can serve as G-API exchange type.
+//
+// In Runtime, GProtoArgs are substituted with appropriate GRunArgs.
+//
+// GProtoArg objects are constructed in-place when user describes
+// (captures) computations, user doesn't interact with these types
+// directly.
+using GProtoArg = util::variant
+ < GMat
+ , GScalar
+ , detail::GArrayU // instead of GArray<T>
+ >;
+
+using GProtoArgs = std::vector<GProtoArg>;
+
+namespace detail
+{
+template<typename... Ts> inline GProtoArgs packArgs(Ts... args)
+{
+ return GProtoArgs{ GProtoArg(wrap_gapi_helper<Ts>::wrap(args))... };
+}
+
+}
+
+template<class Tag>
+struct GIOProtoArgs
+{
+public:
+ explicit GIOProtoArgs(const GProtoArgs& args) : m_args(args) {}
+ explicit GIOProtoArgs(GProtoArgs &&args) : m_args(std::move(args)) {}
+
+ GProtoArgs m_args;
+};
+
+struct In_Tag{};
+struct Out_Tag{};
+
+using GProtoInputArgs = GIOProtoArgs<In_Tag>;
+using GProtoOutputArgs = GIOProtoArgs<Out_Tag>;
+
+// Perfect forwarding
+template<typename... Ts> inline GProtoInputArgs GIn(Ts&&... ts)
+{
+ return GProtoInputArgs(detail::packArgs(std::forward<Ts>(ts)...));
+}
+
+template<typename... Ts> inline GProtoOutputArgs GOut(Ts&&... ts)
+{
+ return GProtoOutputArgs(detail::packArgs(std::forward<Ts>(ts)...));
+}
+
+// Extract run-time arguments from node origin
+// Can be used to extract constant values associated with G-objects
+// (like GScalar) at graph construction time
+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 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
+GMetaArg GAPI_EXPORTS descr_of(const GRunArgP& argp);
+
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GPROTO_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/core.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/core.hpp
new file mode 100644
index 000000000..98d49b5b8
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/core.hpp
@@ -0,0 +1,27 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GPU_CORE_API_HPP
+#define OPENCV_GAPI_GPU_CORE_API_HPP
+
+#include <opencv2/core/cvdef.h> // GAPI_EXPORTS
+#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
+
+namespace cv {
+namespace gapi {
+namespace core {
+namespace gpu {
+
+GAPI_EXPORTS GKernelPackage kernels();
+
+} // namespace gpu
+} // namespace core
+} // namespace gapi
+} // namespace cv
+
+
+#endif // OPENCV_GAPI_GPU_CORE_API_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/ggpukernel.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/ggpukernel.hpp
new file mode 100644
index 000000000..e5a6215e3
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/ggpukernel.hpp
@@ -0,0 +1,244 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GGPUKERNEL_HPP
+#define OPENCV_GAPI_GGPUKERNEL_HPP
+
+#include <vector>
+#include <functional>
+#include <map>
+#include <unordered_map>
+
+#include <opencv2/core/mat.hpp>
+#include <opencv2/gapi/gcommon.hpp>
+#include <opencv2/gapi/gkernel.hpp>
+#include <opencv2/gapi/garg.hpp>
+
+// FIXME: namespace scheme for backends?
+namespace cv {
+
+namespace gimpl
+{
+ // Forward-declare an internal class
+ class GGPUExecutable;
+} // namespace gimpl
+
+namespace gapi
+{
+namespace gpu
+{
+ /**
+ * \addtogroup gapi_std_backends G-API Standard backends
+ * @{
+ */
+ /**
+ * @brief Get a reference to GPU backend.
+ *
+ * At the moment, the GPU backend is built atop of OpenCV
+ * "Transparent API" (T-API), see cv::UMat for details.
+ *
+ * @sa gapi_std_backends
+ */
+ GAPI_EXPORTS cv::gapi::GBackend backend();
+ /** @} */
+} // namespace gpu
+} // namespace gapi
+
+
+// Represents arguments which are passed to a wrapped GPU function
+// FIXME: put into detail?
+class GAPI_EXPORTS GGPUContext
+{
+public:
+ // Generic accessor API
+ template<typename T>
+ const T& inArg(int input) { return m_args.at(input).get<T>(); }
+
+ // Syntax sugar
+ const cv::UMat& inMat(int input);
+ cv::UMat& outMatR(int output); // FIXME: Avoid cv::Mat m = ctx.outMatR()
+
+ const cv::gapi::own::Scalar& inVal(int input);
+ cv::gapi::own::Scalar& outValR(int output); // FIXME: Avoid cv::gapi::own::Scalar s = ctx.outValR()
+ template<typename T> std::vector<T>& outVecR(int output) // FIXME: the same issue
+ {
+ return outVecRef(output).wref<T>();
+ }
+
+protected:
+ detail::VectorRef& outVecRef(int output);
+
+ std::vector<GArg> m_args;
+ std::unordered_map<std::size_t, GRunArgP> m_results;
+
+
+ friend class gimpl::GGPUExecutable;
+};
+
+class GAPI_EXPORTS GGPUKernel
+{
+public:
+ // This function is kernel's execution entry point (does the processing work)
+ using F = std::function<void(GGPUContext &)>;
+
+ GGPUKernel();
+ explicit GGPUKernel(const F& f);
+
+ void apply(GGPUContext &ctx);
+
+protected:
+ F m_f;
+};
+
+// FIXME: This is an ugly ad-hoc imlpementation. TODO: refactor
+
+namespace detail
+{
+template<class T> struct gpu_get_in;
+template<> struct gpu_get_in<cv::GMat>
+{
+ static cv::UMat get(GGPUContext &ctx, int idx) { return ctx.inMat(idx); }
+};
+template<> struct gpu_get_in<cv::GScalar>
+{
+ static cv::Scalar get(GGPUContext &ctx, int idx) { return to_ocv(ctx.inVal(idx)); }
+};
+template<typename U> struct gpu_get_in<cv::GArray<U> >
+{
+ static const std::vector<U>& get(GGPUContext &ctx, int idx) { return ctx.inArg<VectorRef>(idx).rref<U>(); }
+};
+template<class T> struct gpu_get_in
+{
+ static T get(GGPUContext &ctx, int idx) { return ctx.inArg<T>(idx); }
+};
+
+struct tracked_cv_umat{
+ //TODO Think if T - API could reallocate UMat to a proper size - how do we handle this ?
+ //tracked_cv_umat(cv::UMat& m) : r{(m)}, original_data{m.getMat(ACCESS_RW).data} {}
+ tracked_cv_umat(cv::UMat& m) : r{ (m) }, original_data{ nullptr } {}
+ cv::UMat r;
+ uchar* original_data;
+
+ operator cv::UMat& (){ return r;}
+ void validate() const{
+ //if (r.getMat(ACCESS_RW).data != original_data)
+ //{
+ // util::throw_error
+ // (std::logic_error
+ // ("OpenCV kernel output parameter was reallocated. \n"
+ // "Incorrect meta data was provided ?"));
+ //}
+
+ }
+};
+
+struct scalar_wrapper_gpu
+{
+ //FIXME reuse CPU (OpenCV) plugin code
+ scalar_wrapper_gpu(cv::gapi::own::Scalar& s) : m_s{cv::gapi::own::to_ocv(s)}, m_org_s(s) {};
+ operator cv::Scalar& () { return m_s; }
+ void writeBack() const { m_org_s = to_own(m_s); }
+
+ cv::Scalar m_s;
+ cv::gapi::own::Scalar& m_org_s;
+};
+
+template<typename... Outputs>
+void postprocess_gpu(Outputs&... outs)
+{
+ struct
+ {
+ void operator()(tracked_cv_umat* bm) { bm->validate(); }
+ void operator()(scalar_wrapper_gpu* sw) { sw->writeBack(); }
+ void operator()(...) { }
+
+ } validate;
+ //dummy array to unfold parameter pack
+ int dummy[] = { 0, (validate(&outs), 0)... };
+ cv::util::suppress_unused_warning(dummy);
+}
+
+template<class T> struct gpu_get_out;
+template<> struct gpu_get_out<cv::GMat>
+{
+ static tracked_cv_umat get(GGPUContext &ctx, int idx)
+ {
+ auto& r = ctx.outMatR(idx);
+ return{ r };
+ }
+};
+template<> struct gpu_get_out<cv::GScalar>
+{
+ static scalar_wrapper_gpu get(GGPUContext &ctx, int idx)
+ {
+ auto& s = ctx.outValR(idx);
+ return{ s };
+ }
+};
+template<typename U> struct gpu_get_out<cv::GArray<U> >
+{
+ static std::vector<U>& get(GGPUContext &ctx, int idx) { return ctx.outVecR<U>(idx); }
+};
+
+template<typename, typename, typename>
+struct GPUCallHelper;
+
+// FIXME: probably can be simplified with std::apply or analogue.
+template<typename Impl, typename... Ins, typename... Outs>
+struct GPUCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...> >
+{
+ template<typename... Inputs>
+ struct call_and_postprocess
+ {
+ template<typename... Outputs>
+ static void call(Inputs&&... ins, Outputs&&... outs)
+ {
+ //not using a std::forward on outs is deliberate in order to
+ //cause compilation error, by tring to bind rvalue references to lvalue references
+ Impl::run(std::forward<Inputs>(ins)..., outs...);
+
+ postprocess_gpu(outs...);
+ }
+ };
+
+ template<int... IIs, int... OIs>
+ static void call_impl(GGPUContext &ctx, detail::Seq<IIs...>, detail::Seq<OIs...>)
+ {
+ //TODO: Make sure that OpenCV kernels do not reallocate memory for output parameters
+ //by comparing it's state (data ptr) before and after the call.
+ //Convert own::Scalar to cv::Scalar before call kernel and run kernel
+ //convert cv::Scalar to own::Scalar after call kernel and write back results
+ call_and_postprocess<decltype(gpu_get_in<Ins>::get(ctx, IIs))...>::call(gpu_get_in<Ins>::get(ctx, IIs)..., gpu_get_out<Outs>::get(ctx, OIs)...);
+ }
+
+ static void call(GGPUContext &ctx)
+ {
+ call_impl(ctx,
+ typename detail::MkSeq<sizeof...(Ins)>::type(),
+ typename detail::MkSeq<sizeof...(Outs)>::type());
+ }
+};
+
+} // namespace detail
+
+template<class Impl, class K>
+class GGPUKernelImpl: public detail::GPUCallHelper<Impl, typename K::InArgs, typename K::OutArgs>
+{
+ using P = detail::GPUCallHelper<Impl, typename K::InArgs, typename K::OutArgs>;
+
+public:
+ using API = K;
+
+ static cv::gapi::GBackend backend() { return cv::gapi::gpu::backend(); }
+ static cv::GGPUKernel kernel() { return GGPUKernel(&P::call); }
+};
+
+#define GAPI_GPU_KERNEL(Name, API) struct Name: public cv::GGPUKernelImpl<Name, API>
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GGPUKERNEL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/imgproc.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/imgproc.hpp
new file mode 100644
index 000000000..6071dda98
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gpu/imgproc.hpp
@@ -0,0 +1,27 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GPU_IMGPROC_API_HPP
+#define OPENCV_GAPI_GPU_IMGPROC_API_HPP
+
+#include <opencv2/core/cvdef.h> // GAPI_EXPORTS
+#include <opencv2/gapi/gkernel.hpp> // GKernelPackage
+
+namespace cv {
+namespace gapi {
+namespace imgproc {
+namespace gpu {
+
+GAPI_EXPORTS GKernelPackage kernels();
+
+} // namespace gpu
+} // namespace imgproc
+} // namespace gapi
+} // namespace cv
+
+
+#endif // OPENCV_GAPI_GPU_IMGPROC_API_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gscalar.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gscalar.hpp
new file mode 100644
index 000000000..dd1205b63
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gscalar.hpp
@@ -0,0 +1,83 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GSCALAR_HPP
+#define OPENCV_GAPI_GSCALAR_HPP
+
+#include <ostream>
+
+#include <opencv2/gapi/opencv_includes.hpp>
+#include <opencv2/gapi/gcommon.hpp> // GShape
+#include <opencv2/gapi/util/optional.hpp>
+#include "opencv2/gapi/own/scalar.hpp"
+
+namespace cv
+{
+// Forward declaration; GNode and GOrigin are an internal
+// (user-inaccessible) classes.
+class GNode;
+struct GOrigin;
+
+/** \addtogroup gapi_data_objects
+ * @{
+ */
+
+class GAPI_EXPORTS GScalar
+{
+public:
+ GScalar(); // Empty constructor
+ explicit GScalar(const cv::gapi::own::Scalar& s); // Constant value constructor from cv::gapi::own::Scalar
+ explicit GScalar(cv::gapi::own::Scalar&& s); // Constant value move-constructor from cv::gapi::own::Scalar
+#if !defined(GAPI_STANDALONE)
+ explicit GScalar(const cv::Scalar& s); // Constant value constructor from cv::Scalar
+#endif // !defined(GAPI_STANDALONE)
+ GScalar(double v0); // Constant value constructor from double
+ GScalar(const GNode &n, std::size_t out); // Operation result constructor
+
+ GOrigin& priv(); // Internal use only
+ const GOrigin& priv() const; // Internal use only
+
+private:
+ std::shared_ptr<GOrigin> m_priv;
+};
+
+/** @} */
+
+/**
+ * \addtogroup gapi_meta_args
+ * @{
+ */
+struct GScalarDesc
+{
+ // NB.: right now it is empty
+
+ inline bool operator== (const GScalarDesc &) const
+ {
+ return true; // NB: implement this method if GScalar meta appears
+ }
+
+ inline bool operator!= (const GScalarDesc &rhs) const
+ {
+ return !(*this == rhs);
+ }
+};
+
+static inline GScalarDesc empty_scalar_desc() { return GScalarDesc(); }
+
+#if !defined(GAPI_STANDALONE)
+GAPI_EXPORTS GScalarDesc descr_of(const cv::Scalar &scalar);
+#endif // !defined(GAPI_STANDALONE)
+/** @} */
+
+GAPI_EXPORTS GScalarDesc descr_of(const cv::gapi::own::Scalar &scalar);
+
+std::ostream& operator<<(std::ostream& os, const cv::GScalarDesc &desc);
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GSCALAR_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtype_traits.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtype_traits.hpp
new file mode 100644
index 000000000..d05e02e0e
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtype_traits.hpp
@@ -0,0 +1,152 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GTYPE_TRAITS_HPP
+#define OPENCV_GAPI_GTYPE_TRAITS_HPP
+
+#include <vector>
+#include <type_traits>
+
+#include <opencv2/gapi/gmat.hpp>
+#include <opencv2/gapi/gscalar.hpp>
+#include <opencv2/gapi/garray.hpp>
+#include <opencv2/gapi/gcommon.hpp>
+#include <opencv2/gapi/own/convert.hpp>
+
+namespace cv
+{
+namespace detail
+{
+ // FIXME: These traits and enum and possible numerous switch(kind)
+ // block may be replaced with a special Handler<T> object or with
+ // a double dispatch
+ enum class ArgKind: int
+ {
+ OPAQUE, // Unknown, generic, opaque-to-GAPI data type - STATIC
+ GOBJREF, // <internal> reference to object
+ GMAT, // a cv::GMat
+ GSCALAR, // a cv::GScalar
+ GARRAY, // a cv::GArrayU (note - exactly GArrayU, not GArray<T>!)
+ };
+
+ // Describe G-API types (G-types) with traits. Mostly used by
+ // cv::GArg to store meta information about types passed into
+ // operation arguments. Please note that cv::GComputation is
+ // defined on GProtoArgs, not GArgs!
+ template<typename T> struct GTypeTraits;
+ template<typename T> struct GTypeTraits
+ {
+ static constexpr const ArgKind kind = ArgKind::OPAQUE;
+ };
+ template<> struct GTypeTraits<cv::GMat>
+ {
+ static constexpr const ArgKind kind = ArgKind::GMAT;
+ static constexpr const GShape shape = GShape::GMAT;
+ };
+ template<> struct GTypeTraits<cv::GScalar>
+ {
+ static constexpr const ArgKind kind = ArgKind::GSCALAR;
+ static constexpr const GShape shape = GShape::GSCALAR;
+ };
+ template<class T> struct GTypeTraits<cv::GArray<T> >
+ {
+ static constexpr const ArgKind kind = ArgKind::GARRAY;
+ static constexpr const GShape shape = GShape::GARRAY;
+ using host_type = std::vector<T>;
+ using strip_type = cv::detail::VectorRef;
+ static cv::detail::GArrayU wrap_value(const cv::GArray<T> &t) { return t.strip();}
+ static cv::detail::VectorRef wrap_in (const std::vector<T> &t) { return detail::VectorRef(t); }
+ static cv::detail::VectorRef wrap_out ( std::vector<T> &t) { return detail::VectorRef(t); }
+ };
+
+ // Tests if Trait for type T requires extra marshalling ("custom wrap") or not.
+ // If Traits<T> has wrap_value() defined, it does.
+ template<class T> struct has_custom_wrap
+ {
+ template<class,class> class check;
+ template<typename C> static std::true_type test(check<C, decltype(&GTypeTraits<C>::wrap_value)> *);
+ template<typename C> static std::false_type test(...);
+ using type = decltype(test<T>(nullptr));
+ static const constexpr bool value = std::is_same<std::true_type, decltype(test<T>(nullptr))>::value;
+ };
+
+ // Resolve a Host type back to its associated G-Type.
+ // FIXME: Probably it can be avoided
+ template<typename T> struct GTypeOf;
+#if !defined(GAPI_STANDALONE)
+ template<> struct GTypeOf<cv::Mat> { using type = cv::GMat; };
+ template<> struct GTypeOf<cv::Scalar> { using type = cv::GScalar; };
+#endif // !defined(GAPI_STANDALONE)
+ template<> struct GTypeOf<cv::gapi::own::Mat> { using type = cv::GMat; };
+ template<> struct GTypeOf<cv::gapi::own::Scalar> { using type = cv::GScalar; };
+ template<typename U> struct GTypeOf<std::vector<U> > { using type = cv::GArray<U>; };
+ template<class T> using g_type_of_t = typename GTypeOf<T>::type;
+
+ // Marshalling helper for G-types and its Host types. Helps G-API
+ // to store G types in internal generic containers for further
+ // processing. Implements the following callbacks:
+ //
+ // * wrap() - converts user-facing G-type into an internal one
+ // for internal storage.
+ // Used when G-API operation is instantiated (G<Kernel>::on(),
+ // etc) during expressing a pipeline. Mostly returns input
+ // value "as is" except the case when G-type is a template. For
+ // template G-classes, calls custom wrap() from Traits.
+ // The value returned by wrap() is then wrapped into GArg() and
+ // stored in G-API metadata.
+ //
+ // Example:
+ // - cv::GMat arguments are passed as-is.
+ // - integers, pointers, STL containers, user types are passed as-is.
+ // - cv::GArray<T> is converted to cv::GArrayU.
+ //
+ // * wrap_in() / wrap_out() - convert Host type associated with
+ // G-type to internal representation type.
+ //
+ // - For "simple" (non-template) G-types, returns value as-is.
+ // Example: cv::GMat has host type cv::Mat, when user passes a
+ // cv::Mat, system stores it internally as cv::Mat.
+ //
+ // - For "complex" (template) G-types, utilizes custom
+ // wrap_in()/wrap_out() as described in Traits.
+ // Example: cv::GArray<T> has host type std::vector<T>, when
+ // user passes a std::vector<T>, system stores it
+ // internally as VectorRef (with <T> stripped away).
+ template<typename T, class Custom = void> struct WrapValue
+ {
+ static auto wrap(const T& t) ->
+ typename std::remove_reference<T>::type
+ {
+ return static_cast<typename std::remove_reference<T>::type>(t);
+ }
+
+ template<typename U> static U wrap_in (const U &u) { return u; }
+ template<typename U> static U* wrap_out(U &u) { return &u; }
+ };
+ template<typename T> struct WrapValue<T, typename std::enable_if<has_custom_wrap<T>::value>::type>
+ {
+ static auto wrap(const T& t) -> decltype(GTypeTraits<T>::wrap_value(t))
+ {
+ return GTypeTraits<T>::wrap_value(t);
+ }
+ template<typename U> static auto wrap_in (const U &u) -> typename GTypeTraits<T>::strip_type
+ {
+ return GTypeTraits<T>::wrap_in(u);
+ }
+ template<typename U> static auto wrap_out(U &u) -> typename GTypeTraits<T>::strip_type
+ {
+ return GTypeTraits<T>::wrap_out(u);
+ }
+ };
+
+ template<typename T> using wrap_gapi_helper = WrapValue<typename std::decay<T>::type>;
+ template<typename T> using wrap_host_helper = WrapValue<typename std::decay<g_type_of_t<T> >::type>;
+
+} // namespace detail
+} // namespace cv
+
+#endif // OPENCV_GAPI_GTYPE_TRAITS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtyped.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtyped.hpp
new file mode 100644
index 000000000..a966f263f
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/gtyped.hpp
@@ -0,0 +1,187 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GTYPED_HPP
+#define OPENCV_GAPI_GTYPED_HPP
+#if !defined(GAPI_STANDALONE)
+
+#include <vector>
+
+#include "opencv2/gapi/gcomputation.hpp"
+#include "opencv2/gapi/gcompiled.hpp"
+#include "opencv2/gapi/gproto.hpp"
+#include "opencv2/gapi/gcommon.hpp"
+
+namespace cv {
+
+namespace detail
+{
+ // FIXME: How to prevent coolhackers from extending it by their own types?
+ // FIXME: ...Should we care?
+ template<typename T> struct ProtoToParam;
+ template<> struct ProtoToParam<cv::GMat> { using type = cv::Mat; };
+ template<> struct ProtoToParam<cv::GScalar> { using type = cv::Scalar; };
+ template<typename U> struct ProtoToParam<cv::GArray<U> > { using type = std::vector<U>; };
+ template<typename T> using ProtoToParamT = typename ProtoToParam<T>::type;
+
+ template<typename T> struct ProtoToMeta;
+ template<> struct ProtoToMeta<cv::GMat> { using type = cv::GMatDesc; };
+ template<> struct ProtoToMeta<cv::GScalar> { using type = cv::GScalarDesc; };
+ template<typename U> struct ProtoToMeta<cv::GArray<U> > { using type = cv::GArrayDesc; };
+ template<typename T> using ProtoToMetaT = typename ProtoToMeta<T>::type;
+
+ //workaround for MSVC 19.0 bug
+ template <typename T>
+ auto make_default()->decltype(T{}) {return {};}
+}; // detail
+
+template<typename> class GComputationT;
+
+// Single return value implementation
+template<typename R, typename... Args> class GComputationT<R(Args...)>
+{
+public:
+ typedef std::function<R(Args...)> Gen;
+
+ class GCompiledT
+ {
+ private:
+ friend class GComputationT<R(Args...)>;
+
+ cv::GCompiled m_comp;
+
+ explicit GCompiledT(const cv::GCompiled &comp) : m_comp(comp) {}
+
+ public:
+ GCompiledT() {}
+
+ void operator()(detail::ProtoToParamT<Args>... inArgs,
+ detail::ProtoToParamT<R> &outArg)
+ {
+ m_comp(cv::gin(inArgs...), cv::gout(outArg));
+ }
+
+ explicit operator bool() const
+ {
+ return static_cast<bool>(m_comp);
+ }
+ };
+
+private:
+ typedef std::pair<R, GProtoInputArgs > Captured;
+
+ Captured capture(const Gen& g, Args... args)
+ {
+ return Captured(g(args...), cv::GIn(args...));
+ }
+
+ Captured m_capture;
+ cv::GComputation m_comp;
+
+public:
+ GComputationT(const Gen &generator)
+ : m_capture(capture(generator, detail::make_default<Args>()...))
+ , m_comp(cv::GProtoInputArgs(std::move(m_capture.second)),
+ cv::GOut(m_capture.first))
+ {
+ }
+
+ void apply(detail::ProtoToParamT<Args>... inArgs,
+ detail::ProtoToParamT<R> &outArg)
+ {
+ m_comp.apply(cv::gin(inArgs...), cv::gout(outArg));
+ }
+
+ GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs)
+ {
+ GMetaArgs inMetas = { GMetaArg(inDescs)... };
+ return GCompiledT(m_comp.compile(std::move(inMetas), GCompileArgs()));
+ }
+
+ GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs, GCompileArgs &&args)
+ {
+ GMetaArgs inMetas = { GMetaArg(inDescs)... };
+ return GCompiledT(m_comp.compile(std::move(inMetas), std::move(args)));
+ }
+};
+
+// Multiple (fixed) return value implementation. FIXME: How to avoid copy-paste?
+template<typename... R, typename... Args> class GComputationT<std::tuple<R...>(Args...)>
+{
+public:
+ typedef std::function<std::tuple<R...>(Args...)> Gen;
+
+ class GCompiledT
+ {
+ private:
+ friend class GComputationT<std::tuple<R...>(Args...)>;
+
+ cv::GCompiled m_comp;
+ explicit GCompiledT(const cv::GCompiled &comp) : m_comp(comp) {}
+
+ public:
+ GCompiledT() {}
+
+ void operator()(detail::ProtoToParamT<Args>... inArgs,
+ detail::ProtoToParamT<R>&... outArgs)
+ {
+ m_comp(cv::gin(inArgs...), cv::gout(outArgs...));
+ }
+
+ explicit operator bool() const
+ {
+ return static_cast<bool>(m_comp);
+ }
+ };
+
+private:
+ typedef std::pair<GProtoArgs, GProtoArgs> Captured;
+
+ template<int... IIs>
+ Captured capture(GProtoArgs &&args, const std::tuple<R...> &rr, detail::Seq<IIs...>)
+ {
+ return Captured(cv::GOut(std::get<IIs>(rr)...).m_args, args);
+ }
+
+ Captured capture(const Gen& g, Args... args)
+ {
+ return capture(cv::GIn(args...).m_args, g(args...), typename detail::MkSeq<sizeof...(R)>::type());
+ }
+
+ Captured m_capture;
+ cv::GComputation m_comp;
+
+public:
+ GComputationT(const Gen &generator)
+ : m_capture(capture(generator, detail::make_default<Args>()...))
+ , m_comp(cv::GProtoInputArgs(std::move(m_capture.second)),
+ cv::GProtoOutputArgs(std::move(m_capture.first)))
+ {
+ }
+
+ void apply(detail::ProtoToParamT<Args>... inArgs,
+ detail::ProtoToParamT<R>&... outArgs)
+ {
+ m_comp.apply(cv::gin(inArgs...), cv::gout(outArgs...));
+ }
+
+ GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs)
+ {
+ GMetaArgs inMetas = { GMetaArg(inDescs)... };
+ return GCompiledT(m_comp.compile(std::move(inMetas), GCompileArgs()));
+ }
+
+ GCompiledT compile(detail::ProtoToMetaT<Args>... inDescs, GCompileArgs &&args)
+ {
+ GMetaArgs inMetas = { GMetaArg(inDescs)... };
+ return GCompiledT(m_comp.compile(std::move(inMetas), std::move(args)));
+ }
+};
+
+} // namespace cv
+#endif // !defined(GAPI_STANDALONE)
+#endif // OPENCV_GAPI_GTYPED_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/imgproc.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/imgproc.hpp
new file mode 100644
index 000000000..aeed9fa6c
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/imgproc.hpp
@@ -0,0 +1,677 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_IMGPROC_HPP
+#define OPENCV_GAPI_IMGPROC_HPP
+
+#include "opencv2/imgproc.hpp"
+
+#include <utility> // std::tuple
+
+#include "opencv2/gapi/gkernel.hpp"
+#include "opencv2/gapi/gmat.hpp"
+#include "opencv2/gapi/gscalar.hpp"
+
+
+/** \defgroup gapi_imgproc G-API image processing functionality
+@{
+ @defgroup gapi_filters Graph API: Image filters
+ @defgroup gapi_colorconvert Graph API: Converting image from one color space to another
+@}
+ */
+
+namespace cv { namespace gapi {
+
+namespace imgproc {
+ using GMat3 = std::tuple<GMat,GMat,GMat>; // FIXME: how to avoid this?
+
+ G_TYPED_KERNEL(GFilter2D, <GMat(GMat,int,Mat,Point,Scalar,int,Scalar)>,"org.opencv.imgproc.filters.filter2D") {
+ static GMatDesc outMeta(GMatDesc in, int ddepth, Mat, Point, Scalar, int, Scalar) {
+ return in.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GSepFilter, <GMat(GMat,int,Mat,Mat,Point,Scalar,int,Scalar)>, "org.opencv.imgproc.filters.sepfilter") {
+ static GMatDesc outMeta(GMatDesc in, int ddepth, Mat, Mat, Point, Scalar, int, Scalar) {
+ return in.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GBoxFilter, <GMat(GMat,int,Size,Point,bool,int,Scalar)>, "org.opencv.imgproc.filters.boxfilter") {
+ static GMatDesc outMeta(GMatDesc in, int ddepth, Size, Point, bool, int, Scalar) {
+ return in.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GBlur, <GMat(GMat,Size,Point,int,Scalar)>, "org.opencv.imgproc.filters.blur"){
+ static GMatDesc outMeta(GMatDesc in, Size, Point, int, Scalar) {
+ return in;
+ }
+ };
+
+ G_TYPED_KERNEL(GGaussBlur, <GMat(GMat,Size,double,double,int,Scalar)>, "org.opencv.imgproc.filters.gaussianBlur") {
+ static GMatDesc outMeta(GMatDesc in, Size, double, double, int, Scalar) {
+ return in;
+ }
+ };
+
+ G_TYPED_KERNEL(GMedianBlur, <GMat(GMat,int)>, "org.opencv.imgproc.filters.medianBlur") {
+ static GMatDesc outMeta(GMatDesc in, int) {
+ return in;
+ }
+ };
+
+ G_TYPED_KERNEL(GErode, <GMat(GMat,Mat,Point,int,int,Scalar)>, "org.opencv.imgproc.filters.erode") {
+ static GMatDesc outMeta(GMatDesc in, Mat, Point, int, int, Scalar) {
+ return in;
+ }
+ };
+
+ G_TYPED_KERNEL(GDilate, <GMat(GMat,Mat,Point,int,int,Scalar)>, "org.opencv.imgproc.filters.dilate") {
+ static GMatDesc outMeta(GMatDesc in, Mat, Point, int, int, Scalar) {
+ return in;
+ }
+ };
+
+ G_TYPED_KERNEL(GSobel, <GMat(GMat,int,int,int,int,double,double,int,Scalar)>, "org.opencv.imgproc.filters.sobel") {
+ static GMatDesc outMeta(GMatDesc in, int ddepth, int, int, int, double, double, int, Scalar) {
+ return in.withDepth(ddepth);
+ }
+ };
+
+ G_TYPED_KERNEL(GEqHist, <GMat(GMat)>, "org.opencv.imgproc.equalizeHist"){
+ static GMatDesc outMeta(GMatDesc in) {
+ return in.withType(CV_8U, 1);
+ }
+ };
+
+ G_TYPED_KERNEL(GCanny, <GMat(GMat,double,double,int,bool)>, "org.opencv.imgproc.canny"){
+ static GMatDesc outMeta(GMatDesc in, double, double, int, bool) {
+ return in.withType(CV_8U, 1);
+ }
+ };
+
+ G_TYPED_KERNEL(GRGB2YUV, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.rgb2yuv") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in; // type still remains CV_8UC3;
+ }
+ };
+
+ G_TYPED_KERNEL(GYUV2RGB, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.yuv2rgb") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in; // type still remains CV_8UC3;
+ }
+ };
+
+ G_TYPED_KERNEL(GRGB2Lab, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.rgb2lab") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in; // type still remains CV_8UC3;
+ }
+ };
+
+ G_TYPED_KERNEL(GBGR2LUV, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.bgr2luv") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in; // type still remains CV_8UC3;
+ }
+ };
+
+ G_TYPED_KERNEL(GLUV2BGR, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.luv2bgr") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in; // type still remains CV_8UC3;
+ }
+ };
+
+ G_TYPED_KERNEL(GYUV2BGR, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.yuv2bgr") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in; // type still remains CV_8UC3;
+ }
+ };
+
+ G_TYPED_KERNEL(GBGR2YUV, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.bgr2yuv") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in; // type still remains CV_8UC3;
+ }
+ };
+
+ G_TYPED_KERNEL(GRGB2Gray, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.rgb2gray") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in.withType(CV_8U, 1);
+ }
+ };
+
+ G_TYPED_KERNEL(GRGB2GrayCustom, <GMat(GMat,float,float,float)>, "org.opencv.imgproc.colorconvert.rgb2graycustom") {
+ static GMatDesc outMeta(GMatDesc in, float, float, float) {
+ return in.withType(CV_8U, 1);
+ }
+ };
+
+ G_TYPED_KERNEL(GBGR2Gray, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.bgr2gray") {
+ static GMatDesc outMeta(GMatDesc in) {
+ return in.withType(CV_8U, 1);
+ }
+ };
+}
+
+
+//! @addtogroup gapi_filters
+//! @{
+/** @brief Applies a separable linear filter to a matrix(image).
+
+The function applies a separable linear filter to the matrix. That is, first, every row of src is
+filtered with the 1D kernel kernelX. Then, every column of the result is filtered with the 1D
+kernel kernelY. The final result is returned.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+Output image must have the same type, size, and number of channels as the input image.
+@note In case of floating-point computation, rounding to nearest even is procedeed
+if hardware supports it (if not - to nearest value).
+
+@note Function textual ID is "org.opencv.imgproc.filters.sepfilter"
+@param src Source image.
+@param ddepth desired depth of the destination image (the following combinations of src.depth() and ddepth are supported:
+
+ src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F
+ src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F
+ src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F
+ src.depth() = CV_64F, ddepth = -1/CV_64F
+
+when ddepth=-1, the output image will have the same depth as the source)
+@param kernelX Coefficients for filtering each row.
+@param kernelY Coefficients for filtering each column.
+@param anchor Anchor position within the kernel. The default value \f$(-1,-1)\f$ means that the anchor
+is at the kernel center.
+@param delta Value added to the filtered results before storing them.
+@param borderType Pixel extrapolation method, see cv::BorderTypes
+@param borderValue border value in case of constant border type
+@sa boxFilter, gaussianBlur, medianBlur
+ */
+GAPI_EXPORTS GMat sepFilter(const GMat& src, int ddepth, const Mat& kernelX, const Mat& kernelY, const Point& anchor /*FIXME: = Point(-1,-1)*/,
+ const Scalar& delta /*FIXME = GScalar(0)*/, int borderType = BORDER_DEFAULT,
+ const Scalar& borderValue = Scalar(0));
+
+/** @brief Convolves an image with the kernel.
+
+The function applies an arbitrary linear filter to an image. When
+the aperture is partially outside the image, the function interpolates outlier pixel values
+according to the specified border mode.
+
+The function does actually compute correlation, not the convolution:
+
+\f[\texttt{dst} (x,y) = \sum _{ \stackrel{0\leq x' < \texttt{kernel.cols},}{0\leq y' < \texttt{kernel.rows}} } \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f]
+
+That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip
+the kernel using flip and set the new anchor to `(kernel.cols - anchor.x - 1, kernel.rows -
+anchor.y - 1)`.
+
+Supported matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+Output image must have the same size and number of channels an input image.
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+
+@note Function textual ID is "org.opencv.imgproc.filters.filter2D"
+
+@param src input image.
+@param ddepth desired depth of the destination image
+@param kernel convolution kernel (or rather a correlation kernel), a single-channel floating point
+matrix; if you want to apply different kernels to different channels, split the image into
+separate color planes using split and process them individually.
+@param anchor anchor of the kernel that indicates the relative position of a filtered point within
+the kernel; the anchor should lie within the kernel; default value (-1,-1) means that the anchor
+is at the kernel center.
+@param delta optional value added to the filtered pixels before storing them in dst.
+@param borderType pixel extrapolation method, see cv::BorderTypes
+@param borderValue border value in case of constant border type
+@sa sepFilter
+ */
+GAPI_EXPORTS GMat filter2D(const GMat& src, int ddepth, const Mat& kernel, const Point& anchor = Point(-1,-1), const Scalar& delta = Scalar(0),
+ int borderType = BORDER_DEFAULT, const Scalar& borderValue = Scalar(0));
+
+
+/** @brief Blurs an image using the box filter.
+
+The function smooths an image using the kernel:
+
+\f[\texttt{K} = \alpha \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \end{bmatrix}\f]
+
+where
+
+\f[\alpha = \fork{\frac{1}{\texttt{ksize.width*ksize.height}}}{when \texttt{normalize=true}}{1}{otherwise}\f]
+
+Unnormalized box filter is useful for computing various integral characteristics over each pixel
+neighborhood, such as covariance matrices of image derivatives (used in dense optical flow
+algorithms, and so on). If you need to compute pixel sums over variable-size windows, use cv::integral.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+Output image must have the same type, size, and number of channels as the input image.
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+
+@note Function textual ID is "org.opencv.imgproc.filters.boxfilter"
+
+@param src Source image.
+@param dtype the output image depth (-1 to set the input image data type).
+@param ksize blurring kernel size.
+@param anchor Anchor position within the kernel. The default value \f$(-1,-1)\f$ means that the anchor
+is at the kernel center.
+@param normalize flag, specifying whether the kernel is normalized by its area or not.
+@param borderType Pixel extrapolation method, see cv::BorderTypes
+@param borderValue border value in case of constant border type
+@sa sepFilter, gaussianBlur, medianBlur, integral
+ */
+GAPI_EXPORTS GMat boxFilter(const GMat& src, int dtype, const Size& ksize, const Point& anchor = Point(-1,-1),
+ bool normalize = true, int borderType = BORDER_DEFAULT,
+ const Scalar& borderValue = Scalar(0));
+
+/** @brief Blurs an image using the normalized box filter.
+
+The function smooths an image using the kernel:
+
+\f[\texttt{K} = \frac{1}{\texttt{ksize.width*ksize.height}} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \end{bmatrix}\f]
+
+The call `blur(src, dst, ksize, anchor, borderType)` is equivalent to `boxFilter(src, dst, src.type(),
+anchor, true, borderType)`.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+Output image must have the same type, size, and number of channels as the input image.
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+
+@note Function textual ID is "org.opencv.imgproc.filters.blur"
+
+@param src Source image.
+@param ksize blurring kernel size.
+@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel
+center.
+@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes
+@param borderValue border value in case of constant border type
+@sa boxFilter, bilateralFilter, GaussianBlur, medianBlur
+ */
+GAPI_EXPORTS GMat blur(const GMat& src, const Size& ksize, const Point& anchor = Point(-1,-1),
+ int borderType = BORDER_DEFAULT, const Scalar& borderValue = Scalar(0));
+
+
+//GAPI_EXPORTS_W void blur( InputArray src, OutputArray dst,
+ // Size ksize, Point anchor = Point(-1,-1),
+ // int borderType = BORDER_DEFAULT );
+
+
+/** @brief Blurs an image using a Gaussian filter.
+
+The function filter2Ds the source image with the specified Gaussian kernel.
+Output image must have the same type and number of channels an input image.
+
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, @ref CV_32FC1.
+Output image must have the same type, size, and number of channels as the input image.
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+
+@note Function textual ID is "org.opencv.imgproc.filters.gaussianBlur"
+
+@param src input image;
+@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be
+positive and odd. Or, they can be zero's and then they are computed from sigma.
+@param sigmaX Gaussian kernel standard deviation in X direction.
+@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be
+equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height,
+respectively (see cv::getGaussianKernel for details); to fully control the result regardless of
+possible future modifications of all this semantics, it is recommended to specify all of ksize,
+sigmaX, and sigmaY.
+@param borderType pixel extrapolation method, see cv::BorderTypes
+@param borderValue border value in case of constant border type
+@sa sepFilter, boxFilter, medianBlur
+ */
+GAPI_EXPORTS GMat gaussianBlur(const GMat& src, const Size& ksize, double sigmaX, double sigmaY = 0,
+ int borderType = BORDER_DEFAULT, const Scalar& borderValue = Scalar(0));
+
+/** @brief Blurs an image using the median filter.
+
+The function smoothes an image using the median filter with the \f$\texttt{ksize} \times
+\texttt{ksize}\f$ aperture. Each channel of a multi-channel image is processed independently.
+Output image must have the same type, size, and number of channels as the input image.
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+The median filter uses cv::BORDER_REPLICATE internally to cope with border pixels, see cv::BorderTypes
+
+@note Function textual ID is "org.opencv.imgproc.filters.medianBlur"
+
+@param src input matrix (image)
+@param ksize aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ...
+@sa boxFilter, gaussianBlur
+ */
+GAPI_EXPORTS GMat medianBlur(const GMat& src, int ksize);
+
+/** @brief Erodes an image by using a specific structuring element.
+
+The function erodes the source image using the specified structuring element that determines the
+shape of a pixel neighborhood over which the minimum is taken:
+
+\f[\texttt{dst} (x,y) = \min _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f]
+
+Erosion can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently.
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1.
+Output image must have the same type, size, and number of channels as the input image.
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+
+@note Function textual ID is "org.opencv.imgproc.filters.erode"
+
+@param src input image
+@param kernel structuring element used for erosion; if `element=Mat()`, a `3 x 3` rectangular
+structuring element is used. Kernel can be created using getStructuringElement.
+@param anchor position of the anchor within the element; default value (-1, -1) means that the
+anchor is at the element center.
+@param iterations number of times erosion is applied.
+@param borderType pixel extrapolation method, see cv::BorderTypes
+@param borderValue border value in case of a constant border
+@sa dilate
+ */
+GAPI_EXPORTS GMat erode(const GMat& src, const Mat& kernel, const Point& anchor = Point(-1,-1), int iterations = 1,
+ int borderType = BORDER_CONSTANT,
+ const Scalar& borderValue = morphologyDefaultBorderValue());
+
+/** @brief Erodes an image by using 3 by 3 rectangular structuring element.
+
+The function erodes the source image using the rectangular structuring element with rectangle center as an anchor.
+Erosion can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently.
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1.
+Output image must have the same type, size, and number of channels as the input image.
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+
+@param src input image
+@param iterations number of times erosion is applied.
+@param borderType pixel extrapolation method, see cv::BorderTypes
+@param borderValue border value in case of a constant border
+@sa erode, dilate3x3
+ */
+GAPI_EXPORTS GMat erode3x3(const GMat& src, int iterations = 1,
+ int borderType = BORDER_CONSTANT,
+ const Scalar& borderValue = morphologyDefaultBorderValue());
+
+/** @brief Dilates an image by using a specific structuring element.
+
+The function dilates the source image using the specified structuring element that determines the
+shape of a pixel neighborhood over which the maximum is taken:
+\f[\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f]
+
+Dilation can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently.
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1.
+Output image must have the same type, size, and number of channels as the input image.
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+
+@note Function textual ID is "org.opencv.imgproc.filters.dilate"
+
+@param src input image.
+@param kernel structuring element used for dilation; if elemenat=Mat(), a 3 x 3 rectangular
+structuring element is used. Kernel can be created using getStructuringElement
+@param anchor position of the anchor within the element; default value (-1, -1) means that the
+anchor is at the element center.
+@param iterations number of times dilation is applied.
+@param borderType pixel extrapolation method, see cv::BorderTypes
+@param borderValue border value in case of a constant border
+@sa erode, morphologyEx, getStructuringElement
+ */
+GAPI_EXPORTS GMat dilate(const GMat& src, const Mat& kernel, const Point& anchor = Point(-1,-1), int iterations = 1,
+ int borderType = BORDER_CONSTANT,
+ const Scalar& borderValue = morphologyDefaultBorderValue());
+
+/** @brief Dilates an image by using 3 by 3 rectangular structuring element.
+
+The function dilates the source image using the specified structuring element that determines the
+shape of a pixel neighborhood over which the maximum is taken:
+\f[\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f]
+
+Dilation can be applied several (iterations) times. In case of multi-channel images, each channel is processed independently.
+Supported input matrix data types are @ref CV_8UC1, @ref CV_8UC3, @ref CV_16UC1, @ref CV_16SC1, and @ref CV_32FC1.
+Output image must have the same type, size, and number of channels as the input image.
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+
+@note Function textual ID is "org.opencv.imgproc.filters.dilate"
+
+@param src input image.
+@param iterations number of times dilation is applied.
+@param borderType pixel extrapolation method, see cv::BorderTypes
+@param borderValue border value in case of a constant border
+@sa dilate, erode3x3
+ */
+
+GAPI_EXPORTS GMat dilate3x3(const GMat& src, int iterations = 1,
+ int borderType = BORDER_CONSTANT,
+ const Scalar& borderValue = morphologyDefaultBorderValue());
+
+/** @brief Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator.
+
+In all cases except one, the \f$\texttt{ksize} \times \texttt{ksize}\f$ separable kernel is used to
+calculate the derivative. When \f$\texttt{ksize = 1}\f$, the \f$3 \times 1\f$ or \f$1 \times 3\f$
+kernel is used (that is, no Gaussian smoothing is done). `ksize = 1` can only be used for the first
+or the second x- or y- derivatives.
+
+There is also the special value `ksize = FILTER_SCHARR (-1)` that corresponds to the \f$3\times3\f$ Scharr
+filter that may give more accurate results than the \f$3\times3\f$ Sobel. The Scharr aperture is
+
+\f[\vecthreethree{-3}{0}{3}{-10}{0}{10}{-3}{0}{3}\f]
+
+for the x-derivative, or transposed for the y-derivative.
+
+The function calculates an image derivative by convolving the image with the appropriate kernel:
+
+\f[\texttt{dst} = \frac{\partial^{xorder+yorder} \texttt{src}}{\partial x^{xorder} \partial y^{yorder}}\f]
+
+The Sobel operators combine Gaussian smoothing and differentiation, so the result is more or less
+resistant to the noise. Most often, the function is called with ( xorder = 1, yorder = 0, ksize = 3)
+or ( xorder = 0, yorder = 1, ksize = 3) to calculate the first x- or y- image derivative. The first
+case corresponds to a kernel of:
+
+\f[\vecthreethree{-1}{0}{1}{-2}{0}{2}{-1}{0}{1}\f]
+
+The second case corresponds to a kernel of:
+
+\f[\vecthreethree{-1}{-2}{-1}{0}{0}{0}{1}{2}{1}\f]
+
+@note Rounding to nearest even is procedeed if hardware supports it, if not - to nearest.
+
+@note Function textual ID is "org.opencv.imgproc.filters.sobel"
+
+@param src input image.
+@param ddepth output image depth, see @ref filter_depths "combinations"; in the case of
+ 8-bit input images it will result in truncated derivatives.
+@param dx order of the derivative x.
+@param dy order of the derivative y.
+@param ksize size of the extended Sobel kernel; it must be odd.
+@param scale optional scale factor for the computed derivative values; by default, no scaling is
+applied (see cv::getDerivKernels for details).
+@param delta optional delta value that is added to the results prior to storing them in dst.
+@param borderType pixel extrapolation method, see cv::BorderTypes
+@param borderValue border value in case of constant border type
+@sa filter2D, gaussianBlur, cartToPolar
+ */
+GAPI_EXPORTS GMat Sobel(const GMat& src, int ddepth, int dx, int dy, int ksize = 3,
+ double scale = 1, double delta = 0,
+ int borderType = BORDER_DEFAULT,
+ const Scalar& borderValue = Scalar(0));
+
+/** @brief Finds edges in an image using the Canny algorithm.
+
+The function finds edges in the input image and marks them in the output map edges using the
+Canny algorithm. The smallest value between threshold1 and threshold2 is used for edge linking. The
+largest value is used to find initial segments of strong edges. See
+<http://en.wikipedia.org/wiki/Canny_edge_detector>
+
+@note Function textual ID is "org.opencv.imgproc.filters.canny"
+
+@param image 8-bit input image.
+@param threshold1 first threshold for the hysteresis procedure.
+@param threshold2 second threshold for the hysteresis procedure.
+@param apertureSize aperture size for the Sobel operator.
+@param L2gradient a flag, indicating whether a more accurate \f$L_2\f$ norm
+\f$=\sqrt{(dI/dx)^2 + (dI/dy)^2}\f$ should be used to calculate the image gradient magnitude (
+L2gradient=true ), or whether the default \f$L_1\f$ norm \f$=|dI/dx|+|dI/dy|\f$ is enough (
+L2gradient=false ).
+ */
+GAPI_EXPORTS GMat Canny(const GMat& image, double threshold1, double threshold2,
+ int apertureSize = 3, bool L2gradient = false);
+
+/** @brief Equalizes the histogram of a grayscale image.
+
+The function equalizes the histogram of the input image using the following algorithm:
+
+- Calculate the histogram \f$H\f$ for src .
+- Normalize the histogram so that the sum of histogram bins is 255.
+- Compute the integral of the histogram:
+\f[H'_i = \sum _{0 \le j < i} H(j)\f]
+- Transform the image using \f$H'\f$ as a look-up table: \f$\texttt{dst}(x,y) = H'(\texttt{src}(x,y))\f$
+
+The algorithm normalizes the brightness and increases the contrast of the image.
+@note The returned image is of the same size and type as input.
+
+@note Function textual ID is "org.opencv.imgproc.equalizeHist"
+
+@param src Source 8-bit single channel image.
+ */
+GAPI_EXPORTS GMat equalizeHist(const GMat& src);
+
+//! @} gapi_filters
+
+//! @addtogroup gapi_colorconvert
+//! @{
+/** @brief Converts an image from RGB color space to gray-scaled.
+The conventional ranges for R, G, and B channel values are 0 to 255.
+Resulting gray color value computed as
+\f[\texttt{dst} (I)= \texttt{0.299} * \texttt{src}(I).R + \texttt{0.587} * \texttt{src}(I).G + \texttt{0.114} * \texttt{src}(I).B \f]
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2gray"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1.
+@sa RGB2YUV
+ */
+GAPI_EXPORTS GMat RGB2Gray(const GMat& src);
+
+/** @overload
+Resulting gray color value computed as
+\f[\texttt{dst} (I)= \texttt{rY} * \texttt{src}(I).R + \texttt{gY} * \texttt{src}(I).G + \texttt{bY} * \texttt{src}(I).B \f]
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2graycustom"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1.
+@param rY float multiplier for R channel.
+@param gY float multiplier for G channel.
+@param bY float multiplier for B channel.
+@sa RGB2YUV
+ */
+GAPI_EXPORTS GMat RGB2Gray(const GMat& src, float rY, float gY, float bY);
+
+/** @brief Converts an image from BGR color space to gray-scaled.
+The conventional ranges for B, G, and R channel values are 0 to 255.
+Resulting gray color value computed as
+\f[\texttt{dst} (I)= \texttt{0.114} * \texttt{src}(I).B + \texttt{0.587} * \texttt{src}(I).G + \texttt{0.299} * \texttt{src}(I).R \f]
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2gray"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1.
+@sa BGR2LUV
+ */
+GAPI_EXPORTS GMat BGR2Gray(const GMat& src);
+
+/** @brief Converts an image from RGB color space to YUV color space.
+
+The function converts an input image from RGB color space to YUV.
+The conventional ranges for R, G, and B channel values are 0 to 255.
+
+In case of linear transformations, the range does not matter. But in case of a non-linear
+transformation, an input RGB image should be normalized to the proper value range to get the correct
+results, like here, at RGB \f$\rightarrow\f$ Y\*u\*v\* transformation.
+Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2yuv"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
+@sa YUV2RGB, RGB2Lab
+*/
+GAPI_EXPORTS GMat RGB2YUV(const GMat& src);
+
+/** @brief Converts an image from BGR color space to LUV color space.
+
+The function converts an input image from BGR color space to LUV.
+The conventional ranges for B, G, and R channel values are 0 to 255.
+
+Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2luv"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
+@sa RGB2Lab, RGB2LUV
+*/
+GAPI_EXPORTS GMat BGR2LUV(const GMat& src);
+
+/** @brief Converts an image from LUV color space to BGR color space.
+
+The function converts an input image from LUV color space to BGR.
+The conventional ranges for B, G, and R channel values are 0 to 255.
+
+Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.luv2bgr"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
+@sa BGR2LUV
+*/
+GAPI_EXPORTS GMat LUV2BGR(const GMat& src);
+
+/** @brief Converts an image from YUV color space to BGR color space.
+
+The function converts an input image from YUV color space to BGR.
+The conventional ranges for B, G, and R channel values are 0 to 255.
+
+Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.yuv2bgr"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
+@sa BGR2YUV
+*/
+GAPI_EXPORTS GMat YUV2BGR(const GMat& src);
+
+/** @brief Converts an image from BGR color space to YUV color space.
+
+The function converts an input image from BGR color space to YUV.
+The conventional ranges for B, G, and R channel values are 0 to 255.
+
+Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.bgr2yuv"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
+@sa YUV2BGR
+*/
+GAPI_EXPORTS GMat BGR2YUV(const GMat& src);
+
+/** @brief Converts an image from RGB color space to Lab color space.
+
+The function converts an input image from BGR color space to Lab.
+The conventional ranges for R, G, and B channel values are 0 to 255.
+
+Output image must be 8-bit unsigned 3-channel image @ref CV_8UC1.
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.rgb2lab"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC1.
+@sa RGB2YUV, RGB2LUV
+*/
+GAPI_EXPORTS GMat RGB2Lab(const GMat& src);
+
+/** @brief Converts an image from YUV color space to RGB.
+The function converts an input image from YUV color space to RGB.
+The conventional ranges for Y, U, and V channel values are 0 to 255.
+
+Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.yuv2rgb"
+
+@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
+
+@sa RGB2Lab, RGB2YUV
+*/
+GAPI_EXPORTS GMat YUV2RGB(const GMat& src);
+
+//! @} gapi_colorconvert
+} //namespace gapi
+} //namespace cv
+
+#endif // OPENCV_GAPI_IMGPROC_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/opencv_includes.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/opencv_includes.hpp
new file mode 100644
index 000000000..5acf28023
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/opencv_includes.hpp
@@ -0,0 +1,21 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_OPENCV_INCLUDES_HPP
+#define OPENCV_GAPI_OPENCV_INCLUDES_HPP
+
+#if !defined(GAPI_STANDALONE)
+# include <opencv2/core/mat.hpp>
+# include <opencv2/core/cvdef.h>
+# include <opencv2/core/types.hpp>
+# include <opencv2/core/base.hpp>
+#else // Without OpenCV
+# include <opencv2/gapi/own/cvdefs.hpp>
+#endif // !defined(GAPI_STANDALONE)
+
+#endif // OPENCV_GAPI_OPENCV_INCLUDES_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/operators.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/operators.hpp
new file mode 100644
index 000000000..27a1d8012
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/operators.hpp
@@ -0,0 +1,69 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_OPERATORS_HPP
+#define OPENCV_GAPI_OPERATORS_HPP
+
+#include "opencv2/gapi/gmat.hpp"
+#include "opencv2/gapi/gscalar.hpp"
+
+GAPI_EXPORTS cv::GMat operator+(const cv::GMat& lhs, const cv::GMat& rhs);
+
+GAPI_EXPORTS cv::GMat operator+(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator+(const cv::GScalar& lhs, const cv::GMat& rhs);
+
+GAPI_EXPORTS cv::GMat operator-(const cv::GMat& lhs, const cv::GMat& rhs);
+
+GAPI_EXPORTS cv::GMat operator-(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator-(const cv::GScalar& lhs, const cv::GMat& rhs);
+
+GAPI_EXPORTS cv::GMat operator*(const cv::GMat& lhs, float rhs);
+GAPI_EXPORTS cv::GMat operator*(float lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator*(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator*(const cv::GScalar& lhs, const cv::GMat& rhs);
+
+GAPI_EXPORTS cv::GMat operator/(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator/(const cv::GScalar& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator/(const cv::GMat& lhs, const cv::GMat& rhs);
+
+GAPI_EXPORTS cv::GMat operator&(const cv::GMat& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator|(const cv::GMat& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator^(const cv::GMat& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator~(const cv::GMat& lhs);
+
+GAPI_EXPORTS cv::GMat operator&(const cv::GScalar& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator|(const cv::GScalar& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator^(const cv::GScalar& lhs, const cv::GMat& rhs);
+
+GAPI_EXPORTS cv::GMat operator&(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator|(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator^(const cv::GMat& lhs, const cv::GScalar& rhs);
+
+GAPI_EXPORTS cv::GMat operator>(const cv::GMat& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator>=(const cv::GMat& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator<(const cv::GMat& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator<=(const cv::GMat& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator==(const cv::GMat& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator!=(const cv::GMat& lhs, const cv::GMat& rhs);
+
+GAPI_EXPORTS cv::GMat operator>(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator>=(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator<(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator<=(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator==(const cv::GMat& lhs, const cv::GScalar& rhs);
+GAPI_EXPORTS cv::GMat operator!=(const cv::GMat& lhs, const cv::GScalar& rhs);
+
+GAPI_EXPORTS cv::GMat operator>(const cv::GScalar& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator>=(const cv::GScalar& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator<(const cv::GScalar& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator<=(const cv::GScalar& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator==(const cv::GScalar& lhs, const cv::GMat& rhs);
+GAPI_EXPORTS cv::GMat operator!=(const cv::GScalar& lhs, const cv::GMat& rhs);
+
+
+
+#endif // OPENCV_GAPI_OPERATORS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/assert.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/assert.hpp
new file mode 100644
index 000000000..8d3feff01
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/assert.hpp
@@ -0,0 +1,41 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_OWN_ASSERT_HPP
+#define OPENCV_GAPI_OWN_ASSERT_HPP
+
+#if !defined(GAPI_STANDALONE)
+#include <opencv2/core/base.hpp>
+#define GAPI_Assert(expr) CV_Assert(expr)
+
+#else
+#include <stdexcept>
+#include <sstream>
+#include "opencv2/gapi/util/throw.hpp"
+
+namespace detail
+{
+ inline void assert_abort(const char* str, int line, const char* file, const char* func)
+ {
+ std::stringstream ss;
+ ss << file << ":" << line << ": Assertion " << str << " in function " << func << " failed\n";
+ cv::util::throw_error(std::logic_error(ss.str()));
+ }
+}
+
+#define GAPI_Assert(expr) \
+{ if (!(expr)) ::detail::assert_abort(#expr, __LINE__, __FILE__, __func__); }
+
+#endif
+
+#ifdef NDEBUG
+# define GAPI_DbgAssert(expr)
+#else
+# define GAPI_DbgAssert(expr) GAPI_Assert(expr)
+#endif
+
+#endif // OPENCV_GAPI_OWN_ASSERT_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/convert.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/convert.hpp
new file mode 100644
index 000000000..8c1feb408
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/convert.hpp
@@ -0,0 +1,50 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_OWN_CONVERT_HPP
+#define OPENCV_GAPI_OWN_CONVERT_HPP
+
+#if !defined(GAPI_STANDALONE)
+
+#include <opencv2/gapi/opencv_includes.hpp>
+#include <opencv2/gapi/own/types.hpp>
+#include <opencv2/gapi/own/mat.hpp>
+#include "opencv2/gapi/own/scalar.hpp"
+
+namespace cv
+{
+ inline cv::gapi::own::Mat to_own(Mat const& m) { return {m.rows, m.cols, m.type(), m.data, m.step};};
+ cv::gapi::own::Mat to_own(Mat&&) = delete;
+
+ inline cv::gapi::own::Scalar to_own(const cv::Scalar& s) { return {s[0], s[1], s[2], s[3]}; };
+
+ inline cv::gapi::own::Size to_own (const Size& s) { return {s.width, s.height}; };
+
+ inline cv::gapi::own::Rect to_own (const Rect& r) { return {r.x, r.y, r.width, r.height}; };
+
+
+
+namespace gapi
+{
+namespace own
+{
+ inline cv::Mat to_ocv(Mat const& m) { return {m.rows, m.cols, m.type(), m.data, m.step};};
+ cv::Mat to_ocv(Mat&&) = delete;
+
+ inline cv::Scalar to_ocv(const Scalar& s) { return {s[0], s[1], s[2], s[3]}; };
+
+ inline cv::Size to_ocv (const Size& s) { return cv::Size(s.width, s.height); };
+
+ inline cv::Rect to_ocv (const Rect& r) { return cv::Rect(r.x, r.y, r.width, r.height); };
+
+} // namespace own
+} // namespace gapi
+} // namespace cv
+
+#endif // !defined(GAPI_STANDALONE)
+
+#endif // OPENCV_GAPI_OWN_CONVERT_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/cvdefs.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/cvdefs.hpp
new file mode 100644
index 000000000..e11053692
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/cvdefs.hpp
@@ -0,0 +1,146 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_CV_DEFS_HPP
+#define OPENCV_GAPI_CV_DEFS_HPP
+
+#if defined(GAPI_STANDALONE)
+
+// Simulate OpenCV definitions taken from various
+// OpenCV interface headers if G-API is built in a
+// standalone mode.
+
+// interface.h:
+
+typedef unsigned char uchar;
+typedef char schar;
+
+typedef unsigned short ushort;
+
+#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
+#define CV_16S 3
+#define CV_32S 4
+#define CV_32F 5
+#define CV_64F 6
+#define CV_USRTYPE1 7
+
+#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1)
+#define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK)
+
+#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
+#define CV_MAKE_TYPE CV_MAKETYPE
+
+#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
+#define CV_8UC2 CV_MAKETYPE(CV_8U,2)
+#define CV_8UC3 CV_MAKETYPE(CV_8U,3)
+#define CV_8UC4 CV_MAKETYPE(CV_8U,4)
+#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n))
+
+#define CV_8SC1 CV_MAKETYPE(CV_8S,1)
+#define CV_8SC2 CV_MAKETYPE(CV_8S,2)
+#define CV_8SC3 CV_MAKETYPE(CV_8S,3)
+#define CV_8SC4 CV_MAKETYPE(CV_8S,4)
+#define CV_8SC(n) CV_MAKETYPE(CV_8S,(n))
+
+#define CV_16UC1 CV_MAKETYPE(CV_16U,1)
+#define CV_16UC2 CV_MAKETYPE(CV_16U,2)
+#define CV_16UC3 CV_MAKETYPE(CV_16U,3)
+#define CV_16UC4 CV_MAKETYPE(CV_16U,4)
+#define CV_16UC(n) CV_MAKETYPE(CV_16U,(n))
+
+#define CV_16SC1 CV_MAKETYPE(CV_16S,1)
+#define CV_16SC2 CV_MAKETYPE(CV_16S,2)
+#define CV_16SC3 CV_MAKETYPE(CV_16S,3)
+#define CV_16SC4 CV_MAKETYPE(CV_16S,4)
+#define CV_16SC(n) CV_MAKETYPE(CV_16S,(n))
+
+#define CV_32SC1 CV_MAKETYPE(CV_32S,1)
+#define CV_32SC2 CV_MAKETYPE(CV_32S,2)
+#define CV_32SC3 CV_MAKETYPE(CV_32S,3)
+#define CV_32SC4 CV_MAKETYPE(CV_32S,4)
+#define CV_32SC(n) CV_MAKETYPE(CV_32S,(n))
+
+#define CV_32FC1 CV_MAKETYPE(CV_32F,1)
+#define CV_32FC2 CV_MAKETYPE(CV_32F,2)
+#define CV_32FC3 CV_MAKETYPE(CV_32F,3)
+#define CV_32FC4 CV_MAKETYPE(CV_32F,4)
+#define CV_32FC(n) CV_MAKETYPE(CV_32F,(n))
+
+#define CV_64FC1 CV_MAKETYPE(CV_64F,1)
+#define CV_64FC2 CV_MAKETYPE(CV_64F,2)
+#define CV_64FC3 CV_MAKETYPE(CV_64F,3)
+#define CV_64FC4 CV_MAKETYPE(CV_64F,4)
+#define CV_64FC(n) CV_MAKETYPE(CV_64F,(n))
+
+// cvdef.h:
+
+#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)
+#define CV_MAT_TYPE(flags) ((flags) & CV_MAT_TYPE_MASK)
+#define CV_MAT_CONT_FLAG_SHIFT 14
+#define CV_MAT_CONT_FLAG (1 << CV_MAT_CONT_FLAG_SHIFT)
+#define CV_IS_MAT_CONT(flags) ((flags) & CV_MAT_CONT_FLAG)
+#define CV_IS_CONT_MAT CV_IS_MAT_CONT
+#define CV_SUBMAT_FLAG_SHIFT 15
+#define CV_SUBMAT_FLAG (1 << CV_SUBMAT_FLAG_SHIFT)
+#define CV_IS_SUBMAT(flags) ((flags) & CV_MAT_SUBMAT_FLAG)
+
+///** Size of each channel item,
+// 0x8442211 = 1000 0100 0100 0010 0010 0001 0001 ~ array of sizeof(arr_type_elem) */
+//#define CV_ELEM_SIZE1(type) \
+// ((((sizeof(size_t)<<28)|0x8442211) >> CV_MAT_DEPTH(type)*4) & 15)
+
+#define CV_MAT_TYPE(flags) ((flags) & CV_MAT_TYPE_MASK)
+
+/** 0x3a50 = 11 10 10 01 01 00 00 ~ array of log2(sizeof(arr_type_elem)) */
+#define CV_ELEM_SIZE(type) \
+ (CV_MAT_CN(type) << ((((sizeof(size_t)/4+1)*16384|0x3a50) >> CV_MAT_DEPTH(type)*2) & 3))
+
+// base.h:
+namespace cv
+{
+enum BorderTypes {
+ BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i`
+ BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
+ BORDER_REFLECT = 2, //!< `fedcba|abcdefgh|hgfedcb`
+ BORDER_WRAP = 3, //!< `cdefgh|abcdefgh|abcdefg`
+ BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
+ BORDER_TRANSPARENT = 5, //!< `uvwxyz|abcdefgh|ijklmno`
+
+ BORDER_REFLECT101 = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
+ BORDER_DEFAULT = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
+ BORDER_ISOLATED = 16 //!< do not look outside of ROI
+};
+// imgproc.hpp:
+enum InterpolationFlags{
+ INTER_NEAREST = 0,
+ INTER_LINEAR = 1,
+ INTER_CUBIC = 2,
+ INTER_AREA = 3,
+ INTER_LANCZOS4 = 4,
+ INTER_LINEAR_EXACT = 5,
+ INTER_MAX = 7,
+};
+} // namespace cv
+
+static inline int cvFloor( double value )
+{
+ int i = (int)value;
+ return i - (i > value);
+}
+
+#endif // defined(GAPI_STANDALONE)
+
+#endif // OPENCV_GAPI_CV_DEFS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/exports.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/exports.hpp
new file mode 100644
index 000000000..0d955d0e4
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/exports.hpp
@@ -0,0 +1,28 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_OWN_TYPES_HPP
+#define OPENCV_GAPI_OWN_TYPES_HPP
+
+# if 0
+# include <opencv2/core/base.hpp>
+# define GAPI_EXPORTS CV_EXPORTS
+
+# else
+# if defined _WIN32
+# define GAPI_EXPORTS __declspec(dllexport)
+# elif defined __GNUC__ && __GNUC__ >= 4
+# define GAPI_EXPORTS __attribute__ ((visibility ("default")))
+# endif
+
+# ifndef GAPI_EXPORTS
+# define GAPI_EXPORTS
+# endif
+
+# endif
+
+#endif // OPENCV_GAPI_OWN_TYPES_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/mat.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/mat.hpp
new file mode 100644
index 000000000..73f3afcbc
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/mat.hpp
@@ -0,0 +1,291 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_OWN_MAT_HPP
+#define OPENCV_GAPI_OWN_MAT_HPP
+
+#include "opencv2/gapi/opencv_includes.hpp"
+#include "opencv2/gapi/own/types.hpp"
+#include "opencv2/gapi/own/scalar.hpp"
+#include "opencv2/gapi/own/saturate.hpp"
+#include "opencv2/gapi/own/assert.hpp"
+
+#include <memory> //std::shared_ptr
+#include <cstring> //std::memcpy
+#include "opencv2/gapi/util/throw.hpp"
+
+namespace cv { namespace gapi { namespace own {
+ namespace detail {
+ template <typename T, unsigned char channels>
+ void assign_row(void* ptr, int cols, Scalar const& s)
+ {
+ auto p = static_cast<T*>(ptr);
+ for (int c = 0; c < cols; c++)
+ {
+ for (int ch = 0; ch < channels; ch++)
+ {
+ p[c * channels + ch] = saturate<T>(s[ch], roundd);
+ }
+ }
+ }
+
+ inline size_t default_step(int type, int cols)
+ {
+ return CV_ELEM_SIZE(type) * cols;
+ }
+ //Matrix header, i.e. fields that are unique to each Mat object.
+ //Devoted class is needed to implement custom behavior on move (erasing state of moved from object)
+ struct MatHeader{
+ enum { AUTO_STEP = 0};
+ enum { TYPE_MASK = 0x00000FFF };
+
+ MatHeader() = default;
+
+ MatHeader(int _rows, int _cols, int type, void* _data, size_t _step)
+ : flags((type & TYPE_MASK)), rows(_rows), cols(_cols), data((uchar*)_data), step(_step == AUTO_STEP ? detail::default_step(type, _cols) : _step)
+ {}
+
+ MatHeader(const MatHeader& ) = default;
+ MatHeader(MatHeader&& src) : MatHeader(src) // reuse copy constructor here
+ {
+ MatHeader empty; //give it a name to call copy(not move) assignment below
+ src = empty;
+ }
+ MatHeader& operator=(const MatHeader& ) = default;
+ MatHeader& operator=(MatHeader&& src)
+ {
+ *this = src; //calling a copy assignment here, not move one
+ MatHeader empty; //give it a name to call copy(not move) assignment below
+ src = empty;
+ return *this;
+ }
+ /*! includes several bit-fields:
+ - depth
+ - number of channels
+ */
+ int flags = 0;
+
+ //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
+ int rows = 0, cols = 0;
+ //! pointer to the data
+ uchar* data = nullptr;
+ size_t step = 0;
+ };
+ }
+ //concise version of cv::Mat suitable for GAPI needs (used when no dependence on OpenCV is required)
+ class Mat : public detail::MatHeader{
+ public:
+
+ Mat() = default;
+
+ /** @overload
+ @param _rows Number of rows in a 2D array.
+ @param _cols Number of columns in a 2D array.
+ @param _type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or
+ CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices.
+ @param _data Pointer to the user data. Matrix constructors that take data and step parameters do not
+ allocate matrix data. Instead, they just initialize the matrix header that points to the specified
+ data, which means that no data is copied. This operation is very efficient and can be used to
+ process external data using OpenCV functions. The external data is not automatically deallocated, so
+ you should take care of it.
+ @param _step Number of bytes each matrix row occupies. The value should include the padding bytes at
+ the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed
+ and the actual step is calculated as cols*elemSize(). See Mat::elemSize.
+ */
+ Mat(int _rows, int _cols, int _type, void* _data, size_t _step = AUTO_STEP)
+ : MatHeader (_rows, _cols, _type, _data, _step)
+ {}
+
+ Mat(Mat const& src, const Rect& roi )
+ : Mat(src)
+ {
+ rows = roi.height;
+ cols = roi.width;
+ data = ptr(roi.y, roi.x);
+ }
+
+ Mat(Mat const& src) = default;
+ Mat(Mat&& src) = default;
+
+ Mat& operator=(Mat const& src) = default;
+ Mat& operator=(Mat&& src) = default;
+
+ /** @brief Sets all or some of the array elements to the specified value.
+ @param s Assigned scalar converted to the actual array type.
+ */
+ Mat& operator = (const Scalar& s)
+ {
+ constexpr unsigned max_channels = 4; //Scalar can't fit more than 4
+ const auto channels = static_cast<unsigned int>(this->channels());
+ GAPI_Assert(channels <= max_channels);
+
+ using func_p_t = void (*)(void*, int, Scalar const&);
+ using detail::assign_row;
+ #define TABLE_ENTRY(type) {assign_row<type, 1>, assign_row<type, 2>, assign_row<type, 3>, assign_row<type, 4>}
+ static constexpr func_p_t func_tbl[][max_channels] = {
+ TABLE_ENTRY(uchar),
+ TABLE_ENTRY(schar),
+ TABLE_ENTRY(ushort),
+ TABLE_ENTRY(short),
+ TABLE_ENTRY(int),
+ TABLE_ENTRY(float),
+ TABLE_ENTRY(double)
+ };
+ #undef TABLE_ENTRY
+
+ static_assert(CV_8U == 0 && CV_8S == 1 && CV_16U == 2 && CV_16S == 3
+ && CV_32S == 4 && CV_32F == 5 && CV_64F == 6,
+ "OCV type ids used as indexes to array, thus exact numbers are important!"
+ );
+
+ const auto depth = static_cast<unsigned int>(this->depth());
+ GAPI_Assert(depth < sizeof(func_tbl)/sizeof(func_tbl[0]));
+
+ for (int r = 0; r < rows; ++r)
+ {
+ auto* f = func_tbl[depth][channels -1];
+ (*f)(static_cast<void *>(ptr(r)), cols, s );
+ }
+ return *this;
+ }
+
+ /** @brief Returns the matrix element size in bytes.
+
+ The method returns the matrix element size in bytes. For example, if the matrix type is CV_16SC3 ,
+ the method returns 3\*sizeof(short) or 6.
+ */
+ size_t elemSize() const
+ {
+ return CV_ELEM_SIZE(type());
+ }
+ /** @brief Returns the type of a matrix element.
+
+ The method returns a matrix element type. This is an identifier compatible with the CvMat type
+ system, like CV_16SC3 or 16-bit signed 3-channel array, and so on.
+ */
+ int type() const {return CV_MAT_TYPE(flags);}
+
+ /** @brief Returns the depth of a matrix element.
+
+ The method returns the identifier of the matrix element depth (the type of each individual channel).
+ For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of
+ matrix types contains the following values:
+ - CV_8U - 8-bit unsigned integers ( 0..255 )
+ - CV_8S - 8-bit signed integers ( -128..127 )
+ - CV_16U - 16-bit unsigned integers ( 0..65535 )
+ - CV_16S - 16-bit signed integers ( -32768..32767 )
+ - CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
+ - CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
+ - CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
+ */
+ int depth() const {return CV_MAT_DEPTH(flags);}
+
+ /** @brief Returns the number of matrix channels.
+
+ The method returns the number of matrix channels.
+ */
+ int channels() const {return CV_MAT_CN(flags);}
+
+ /**
+ @param _rows New number of rows.
+ @param _cols New number of columns.
+ @param _type New matrix type.
+ */
+ void create(int _rows, int _cols, int _type)
+ {
+ create({_cols, _rows}, _type);
+ }
+ /** @overload
+ @param _size Alternative new matrix size specification: Size(cols, rows)
+ @param _type New matrix type.
+ */
+ void create(Size _size, int _type)
+ {
+ if (_size != Size{cols, rows} )
+ {
+ Mat tmp{_size.height, _size.width, _type, nullptr};
+ tmp.memory.reset(new uchar[ tmp.step * tmp.rows], [](uchar * p){delete[] p;});
+ tmp.data = tmp.memory.get();
+
+ *this = std::move(tmp);
+ }
+ }
+
+ /** @brief Copies the matrix to another one.
+
+ The method copies the matrix data to another matrix. Before copying the data, the method invokes :
+ @code
+ m.create(this->size(), this->type());
+ @endcode
+ so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the
+ function does not handle the case of a partial overlap between the source and the destination
+ matrices.
+ */
+ void copyTo(Mat& dst) const
+ {
+ dst.create(rows, cols, type());
+ for (int r = 0; r < rows; ++r)
+ {
+ std::copy_n(ptr(r), detail::default_step(type(),cols), dst.ptr(r));
+ }
+ }
+
+ /** @brief Returns true if the array has no elements.
+
+ The method returns true if Mat::total() is 0 or if Mat::data is NULL. Because of pop_back() and
+ resize() methods `M.total() == 0` does not imply that `M.data == NULL`.
+ */
+ bool empty() const;
+
+ /** @brief Returns the total number of array elements.
+
+ The method returns the number of array elements (a number of pixels if the array represents an
+ image).
+ */
+ size_t total() const
+ {
+ return static_cast<size_t>(rows * cols);
+ }
+
+
+ /** @overload
+ @param roi Extracted submatrix specified as a rectangle.
+ */
+ Mat operator()( const Rect& roi ) const
+ {
+ return Mat{*this, roi};
+ }
+
+
+ /** @brief Returns a pointer to the specified matrix row.
+
+ The methods return `uchar*` or typed pointer to the specified matrix row. See the sample in
+ Mat::isContinuous to know how to use these methods.
+ @param row Index along the dimension 0
+ @param col Index along the dimension 1
+ */
+ uchar* ptr(int row, int col = 0)
+ {
+ return const_cast<uchar*>(const_cast<const Mat*>(this)->ptr(row,col));
+ }
+ /** @overload */
+ const uchar* ptr(int row, int col = 0) const
+ {
+ return data + step * row + CV_ELEM_SIZE(type()) * col;
+ }
+
+
+ private:
+ //actual memory allocated for storage, or nullptr if object is non owning view to over memory
+ std::shared_ptr<uchar> memory;
+ };
+
+} //namespace own
+} //namespace gapi
+} //namespace cv
+
+#endif /* OPENCV_GAPI_OWN_MAT_HPP */
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/saturate.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/saturate.hpp
new file mode 100644
index 000000000..207dcde25
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/saturate.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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_OWN_SATURATE_HPP
+#define OPENCV_GAPI_OWN_SATURATE_HPP
+
+#include <cmath>
+
+#include <limits>
+#include <type_traits>
+
+#include <opencv2/gapi/own/assert.hpp>
+
+namespace cv { namespace gapi { namespace own {
+//-----------------------------
+//
+// Numeric cast with saturation
+//
+//-----------------------------
+
+template<typename DST, typename SRC>
+static inline DST saturate(SRC x)
+{
+ // only integral types please!
+ GAPI_DbgAssert(std::is_integral<DST>::value &&
+ std::is_integral<SRC>::value);
+
+ if (std::is_same<DST, SRC>::value)
+ return static_cast<DST>(x);
+
+ if (sizeof(DST) > sizeof(SRC))
+ return static_cast<DST>(x);
+
+ // compiler must recognize this saturation,
+ // so compile saturate<s16>(a + b) with adds
+ // instruction (e.g.: _mm_adds_epi16 if x86)
+ return x < std::numeric_limits<DST>::min()?
+ std::numeric_limits<DST>::min():
+ x > std::numeric_limits<DST>::max()?
+ std::numeric_limits<DST>::max():
+ static_cast<DST>(x);
+}
+
+// Note, that OpenCV rounds differently:
+// - like std::round() for add, subtract
+// - like std::rint() for multiply, divide
+template<typename DST, typename SRC, typename R>
+static inline DST saturate(SRC x, R round)
+{
+ if (std::is_floating_point<DST>::value)
+ {
+ return static_cast<DST>(x);
+ }
+ else if (std::is_integral<SRC>::value)
+ {
+ GAPI_DbgAssert(std::is_integral<DST>::value &&
+ std::is_integral<SRC>::value);
+ return saturate<DST>(x);
+ }
+ else
+ {
+ GAPI_DbgAssert(std::is_integral<DST>::value &&
+ std::is_floating_point<SRC>::value);
+#ifdef _WIN32
+// Suppress warning about convering x to floating-point
+// Note that x is already floating-point at this point
+#pragma warning(disable: 4244)
+#endif
+ int ix = static_cast<int>(round(x));
+#ifdef _WIN32
+#pragma warning(default: 4244)
+#endif
+ return saturate<DST>(ix);
+ }
+}
+
+// explicit suffix 'd' for double type
+inline double ceild(double x) { return std::ceil(x); }
+inline double floord(double x) { return std::floor(x); }
+inline double roundd(double x) { return std::round(x); }
+inline double rintd(double x) { return std::rint(x); }
+
+} //namespace own
+} //namespace gapi
+} //namespace cv
+#endif /* OPENCV_GAPI_OWN_SATURATE_HPP */
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/scalar.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/scalar.hpp
new file mode 100644
index 000000000..bda91c83b
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/scalar.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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GAPI_OWN_SCALAR_HPP
+#define OPENCV_GAPI_GAPI_OWN_SCALAR_HPP
+
+#include <opencv2/gapi/own/exports.hpp>
+
+namespace cv
+{
+namespace gapi
+{
+namespace own
+{
+
+class GAPI_EXPORTS Scalar
+{
+public:
+ Scalar() = default;
+ explicit Scalar(double v0) { val[0] = v0; };
+ Scalar(double v0, double v1, double v2 = 0, double v3 = 0)
+ : val{v0, v1, v2, v3}
+ {
+ }
+
+ const double& operator[](int i) const { return val[i]; }
+ double& operator[](int i) { return val[i]; }
+
+ static Scalar all(double v0) { return Scalar(v0, v0, v0, v0); }
+
+ double val[4] = {0};
+};
+
+inline bool operator==(const Scalar& lhs, const Scalar& rhs)
+{
+ return std::equal(std::begin(lhs.val), std::end(lhs.val), std::begin(rhs.val));
+}
+
+} // namespace own
+} // namespace gapi
+} // namespace cv
+
+#endif // OPENCV_GAPI_GAPI_OWN_SCALAR_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/types.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/types.hpp
new file mode 100644
index 000000000..20445ee0f
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/own/types.hpp
@@ -0,0 +1,135 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_TYPES_HPP
+#define OPENCV_GAPI_TYPES_HPP
+
+#include <algorithm> // std::max, std::min
+#include <ostream>
+
+namespace cv
+{
+namespace gapi
+{
+namespace own
+{
+
+class Point
+{
+public:
+ Point() = default;
+ Point(int _x, int _y) : x(_x), y(_y) {};
+
+ int x = 0;
+ int y = 0;
+};
+
+class Rect
+{
+public:
+ Rect() = default;
+ 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) {};
+ inline Rect& operator=(const cv::Rect& other)
+ {
+ x = other.x;
+ y = other.x;
+ width = other.width;
+ height = other.height;
+ return *this;
+ }
+#endif // !defined(GAPI_STANDALONE)
+
+ int x = 0; //!< x coordinate of the top-left corner
+ int y = 0; //!< y coordinate of the top-left corner
+ int width = 0; //!< width of the rectangle
+ int height = 0; //!< height of the rectangle
+};
+
+inline bool operator==(const Rect& lhs, const Rect& rhs)
+{
+ return lhs.x == rhs.x && lhs.y == rhs.y && lhs.width == rhs.width && lhs.height == rhs.height;
+}
+
+inline bool operator!=(const Rect& lhs, const Rect& rhs)
+{
+ return !(lhs == rhs);
+}
+
+inline Rect& operator&=(Rect& lhs, const Rect& rhs)
+{
+ int x1 = std::max(lhs.x, rhs.x);
+ int y1 = std::max(lhs.y, rhs.y);
+ lhs.width = std::min(lhs.x + lhs.width, rhs.x + rhs.width) - x1;
+ lhs.height = std::min(lhs.y + lhs.height, rhs.y + rhs.height) - y1;
+ lhs.x = x1;
+ lhs.y = y1;
+ if( lhs.width <= 0 || lhs.height <= 0 )
+ lhs = Rect();
+ return lhs;
+}
+
+inline const Rect operator&(const Rect& lhs, const Rect& rhs)
+{
+ Rect result = lhs;
+ return result &= rhs;
+}
+
+inline std::ostream& operator<<(std::ostream& o, const Rect& rect)
+{
+ return o << "[" << rect.width << " x " << rect.height << " from (" << rect.x << ", " << rect.y << ")]";
+}
+
+class Size
+{
+public:
+ Size() = default;
+ Size(int _width, int _height) : width(_width), height(_height) {};
+#if !defined(GAPI_STANDALONE)
+ Size(const cv::Size& other) : width(other.width), height(other.height) {};
+ inline Size& operator=(const cv::Size& rhs)
+ {
+ width = rhs.width;
+ height = rhs.height;
+ return *this;
+ }
+#endif // !defined(GAPI_STANDALONE)
+
+ int width = 0;
+ int height = 0;
+};
+
+inline Size& operator+=(Size& lhs, const Size& rhs)
+{
+ lhs.width += rhs.width;
+ lhs.height += rhs.height;
+ return lhs;
+}
+
+inline bool operator==(const Size& lhs, const Size& rhs)
+{
+ return lhs.width == rhs.width && lhs.height == rhs.height;
+}
+
+inline bool operator!=(const Size& lhs, const Size& rhs)
+{
+ return !(lhs == rhs);
+}
+
+
+inline std::ostream& operator<<(std::ostream& o, const Size& s)
+{
+ o << "[" << s.width << " x " << s.height << "]";
+ return o;
+}
+
+} // namespace own
+} // namespace gapi
+} // namespace cv
+
+#endif // OPENCV_GAPI_TYPES_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/any.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/any.hpp
new file mode 100644
index 000000000..3146cb6fd
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/any.hpp
@@ -0,0 +1,186 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_UTIL_ANY_HPP
+#define OPENCV_GAPI_UTIL_ANY_HPP
+
+#include <memory>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+#include "opencv2/gapi/util/throw.hpp"
+
+#if defined(_MSC_VER)
+ // disable MSVC warning on "multiple copy constructors specified"
+# pragma warning(disable: 4521)
+#endif
+
+namespace cv
+{
+
+namespace internal
+{
+ template <class T, class Source>
+ T down_cast(Source operand)
+ {
+#if defined(__GXX_RTTI) || defined(_CPPRTTI)
+ return dynamic_cast<T>(operand);
+#else
+ #warning used static cast instead of dynamic because RTTI is disabled
+ return static_cast<T>(operand);
+#endif
+ }
+}
+
+namespace util
+{
+ class bad_any_cast : public std::bad_cast
+ {
+ public:
+ virtual const char* what() const noexcept override
+ {
+ return "Bad any cast";
+ }
+ };
+
+ //modeled against C++17 std::any
+
+ class any
+ {
+ private:
+ struct holder;
+ using holder_ptr = std::unique_ptr<holder>;
+ struct holder
+ {
+ virtual holder_ptr clone() = 0;
+ virtual ~holder() = default;
+ };
+
+ template <typename value_t>
+ struct holder_impl : holder
+ {
+ value_t v;
+ template<typename arg_t>
+ holder_impl(arg_t&& a) : v(std::forward<arg_t>(a)) {}
+ holder_ptr clone() override { return holder_ptr(new holder_impl (v));}
+ };
+
+ holder_ptr hldr;
+ public:
+ template<class value_t>
+ any(value_t&& arg) : hldr(new holder_impl<typename std::decay<value_t>::type>( std::forward<value_t>(arg))) {}
+
+ any(any const& src) : hldr( src.hldr ? src.hldr->clone() : nullptr) {}
+ //simple hack in order not to write enable_if<not any> for the template constructor
+ any(any & src) : any (const_cast<any const&>(src)) {}
+
+ any() = default;
+ any(any&& ) = default;
+
+ any& operator=(any&&) = default;
+
+ any& operator=(any const& src)
+ {
+ any copy(src);
+ swap(*this, copy);
+ return *this;
+ }
+
+ template<class value_t>
+ friend value_t* any_cast(any* operand);
+
+ template<class value_t>
+ friend const value_t* any_cast(const any* operand);
+
+ template<class value_t>
+ friend value_t& unsafe_any_cast(any& operand);
+
+ template<class value_t>
+ friend const value_t& unsafe_any_cast(const any& operand);
+
+ friend void swap(any & lhs, any& rhs)
+ {
+ swap(lhs.hldr, rhs.hldr);
+ }
+
+ };
+
+ template<class value_t>
+ value_t* any_cast(any* operand)
+ {
+ auto casted = internal::down_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand->hldr.get());
+ if (casted){
+ return & (casted->v);
+ }
+ return nullptr;
+ }
+
+ template<class value_t>
+ const value_t* any_cast(const any* operand)
+ {
+ auto casted = internal::down_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand->hldr.get());
+ if (casted){
+ return & (casted->v);
+ }
+ return nullptr;
+ }
+
+ template<class value_t>
+ value_t& any_cast(any& operand)
+ {
+ auto ptr = any_cast<value_t>(&operand);
+ if (ptr)
+ {
+ return *ptr;
+ }
+
+ throw_error(bad_any_cast());
+ }
+
+
+ template<class value_t>
+ const value_t& any_cast(const any& operand)
+ {
+ auto ptr = any_cast<value_t>(&operand);
+ if (ptr)
+ {
+ return *ptr;
+ }
+
+ throw_error(bad_any_cast());
+ }
+
+ template<class value_t>
+ inline value_t& unsafe_any_cast(any& operand)
+ {
+#ifdef DEBUG
+ return any_cast<value_t>(operand);
+#else
+ return static_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand.hldr.get())->v;
+#endif
+ }
+
+ template<class value_t>
+ inline const value_t& unsafe_any_cast(const any& operand)
+ {
+#ifdef DEBUG
+ return any_cast<value_t>(operand);
+#else
+ return static_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand.hldr.get())->v;
+#endif
+ }
+
+} // namespace util
+} // namespace cv
+
+#if defined(_MSC_VER)
+ // Enable "multiple copy constructors specified" back
+# pragma warning(default: 4521)
+#endif
+
+#endif // OPENCV_GAPI_UTIL_ANY_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/compiler_hints.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/compiler_hints.hpp
new file mode 100644
index 000000000..575655e8f
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/compiler_hints.hpp
@@ -0,0 +1,21 @@
+// 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) 2018 Intel Corporation
+
+#ifndef OPENCV_GAPI_UTIL_COMPILER_HINTS_HPP
+#define OPENCV_GAPI_UTIL_COMPILER_HINTS_HPP
+
+namespace cv
+{
+namespace util
+{
+ //! Utility template function to prevent "unused" warnings by various compilers.
+ template<typename T> void suppress_unused_warning( const T& ) {}
+} // namespace util
+} // namespace cv
+
+#define UNUSED(x) cv::util::suppress_unused_warning(x)
+
+#endif /* OPENCV_GAPI_UTIL_COMPILER_HINTS_HPP */
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/optional.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/optional.hpp
new file mode 100644
index 000000000..54126d627
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/optional.hpp
@@ -0,0 +1,178 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_UTIL_OPTIONAL_HPP
+#define OPENCV_GAPI_UTIL_OPTIONAL_HPP
+
+#include "opencv2/gapi/util/variant.hpp"
+
+// A poor man's `optional` implementation, incompletely modeled against C++17 spec.
+namespace cv
+{
+namespace util
+{
+ class bad_optional_access: public std::exception
+ {
+ public:
+ virtual const char *what() const noexcept override
+ {
+ return "Bad optional access";
+ }
+ };
+
+ // TODO: nullopt_t
+
+ // Interface ///////////////////////////////////////////////////////////////
+ template<typename T> class optional
+ {
+ public:
+ // Constructors
+ // NB.: there were issues with Clang 3.8 when =default() was used
+ // instead {}
+ optional() {};
+ optional(const optional&) = default;
+ explicit optional(T &&value) noexcept;
+ explicit optional(const T &value) noexcept;
+ optional(optional &&) noexcept;
+ // TODO: optional(nullopt_t) noexcept;
+ // TODO: optional(const optional<U> &)
+ // TODO: optional(optional<U> &&)
+ // TODO: optional(Args&&...)
+ // TODO: optional(initializer_list<U>)
+ // TODO: optional(U&& value);
+
+ // Assignment
+ optional& operator=(const optional& rhs) = default;
+ optional& operator=(optional&& rhs);
+
+ // Observers
+ T* operator-> ();
+ const T* operator-> () const;
+ T& operator* ();
+ const T& operator* () const;
+ // TODO: && versions
+
+ operator bool() const noexcept;
+ bool has_value() const noexcept;
+
+ T& value();
+ const T& value() const;
+ // TODO: && versions
+
+ template<class U>
+ T value_or(U &&default_value) const;
+
+ void swap(optional &other) noexcept;
+ void reset() noexcept;
+ // TODO: emplace
+
+ // TODO: operator==, !=, <, <=, >, >=
+
+ private:
+ struct nothing {};
+ util::variant<nothing, T> m_holder;
+ };
+
+ template<class T>
+ optional<typename std::decay<T>::type> make_optional(T&& value);
+
+ // TODO: Args... and initializer_list versions
+
+ // Implementation //////////////////////////////////////////////////////////
+ template<class T> optional<T>::optional(T &&v) noexcept
+ : m_holder(v)
+ {
+ }
+
+ template<class T> optional<T>::optional(const T &v) noexcept
+ : m_holder(v)
+ {
+ }
+
+ template<class T> optional<T>::optional(optional&& rhs) noexcept
+ : m_holder(std::move(rhs.m_holder))
+ {
+ rhs.reset();
+ }
+
+ template<class T> optional<T>& optional<T>::operator=(optional&& rhs)
+ {
+ m_holder = std::move(rhs.m_holder);
+ rhs.reset();
+ return *this;
+ }
+
+ template<class T> T* optional<T>::operator-> ()
+ {
+ return & *(*this);
+ }
+
+ template<class T> const T* optional<T>::operator-> () const
+ {
+ return & *(*this);
+ }
+
+ template<class T> T& optional<T>::operator* ()
+ {
+ return this->value();
+ }
+
+ template<class T> const T& optional<T>::operator* () const
+ {
+ return this->value();
+ }
+
+ template<class T> optional<T>::operator bool() const noexcept
+ {
+ return this->has_value();
+ }
+
+ template<class T> bool optional<T>::has_value() const noexcept
+ {
+ return util::holds_alternative<T>(m_holder);
+ }
+
+ template<class T> T& optional<T>::value()
+ {
+ if (!this->has_value())
+ throw_error(bad_optional_access());
+ return util::get<T>(m_holder);
+ }
+
+ template<class T> const T& optional<T>::value() const
+ {
+ if (!this->has_value())
+ throw_error(bad_optional_access());
+ return util::get<T>(m_holder);
+ }
+
+ template<class T>
+ template<class U> T optional<T>::value_or(U &&default_value) const
+ {
+ return (this->has_value() ? this->value() : T(default_value));
+ }
+
+ template<class T> void optional<T>::swap(optional<T> &other) noexcept
+ {
+ m_holder.swap(other.m_holder);
+ }
+
+ template<class T> void optional<T>::reset() noexcept
+ {
+ if (this->has_value())
+ m_holder = nothing{};
+ }
+
+ template<class T>
+ optional<typename std::decay<T>::type> make_optional(T&& value)
+ {
+ return optional<typename std::decay<T>::type>(std::forward<T>(value));
+ }
+} // namespace util
+} // namespace cv
+
+#endif // OPENCV_GAPI_UTIL_OPTIONAL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/throw.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/throw.hpp
new file mode 100644
index 000000000..689bf583c
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/throw.hpp
@@ -0,0 +1,36 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_UTIL_THROW_HPP
+#define OPENCV_GAPI_UTIL_THROW_HPP
+
+#include <utility> // std::forward
+
+#if !defined(__EXCEPTIONS)
+#include <stdlib.h>
+#include <stdio.h>
+#endif
+
+namespace cv
+{
+namespace util
+{
+template <class ExceptionType>
+[[noreturn]] void throw_error(ExceptionType &&e)
+{
+#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
+ throw std::forward<ExceptionType>(e);
+#else
+ fprintf(stderr, "An exception thrown! %s\n" , e.what());
+ fflush(stderr);
+ abort();
+#endif
+}
+} // namespace util
+} // namespace cv
+
+#endif // OPENCV_GAPI_UTIL_THROW_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/util.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/util.hpp
new file mode 100644
index 000000000..d0378e0e5
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/util.hpp
@@ -0,0 +1,92 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_UTIL_HPP
+#define OPENCV_GAPI_UTIL_HPP
+
+#include <utility> // std::tuple
+
+// \cond HIDDEN_SYMBOLS
+// This header file contains some generic utility functions which are
+// used in other G-API Public API headers.
+//
+// PLEASE don't put any stuff here if it is NOT used in public API headers!
+
+namespace cv
+{
+namespace detail
+{
+ // Recursive integer sequence type, useful for enumerating elements of
+ // template parameter packs.
+ template<int... I> struct Seq { using next = Seq<I..., sizeof...(I)>; };
+ template<int Sz> struct MkSeq { using type = typename MkSeq<Sz-1>::type::next; };
+ template<> struct MkSeq<0>{ using type = Seq<>; };
+
+ // Checks if elements of variadic template satisfy the given Predicate.
+ // Implemented via tuple, with an interface to accept plain type lists
+ template<template<class> class, typename, typename...> struct all_satisfy;
+
+ template<template<class> class F, typename T, typename... Ts>
+ struct all_satisfy<F, std::tuple<T, Ts...> >
+ {
+ static const constexpr bool value = F<T>::value
+ && all_satisfy<F, std::tuple<Ts...> >::value;
+ };
+ template<template<class> class F, typename T>
+ struct all_satisfy<F, std::tuple<T> >
+ {
+ static const constexpr bool value = F<T>::value;
+ };
+
+ template<template<class> class F, typename T, typename... Ts>
+ struct all_satisfy: public all_satisfy<F, std::tuple<T, Ts...> > {};
+
+ // Permute given tuple type C with given integer sequence II
+ // Sequence may be less than tuple C size.
+ template<class, class> struct permute_tuple;
+
+ template<class C, int... IIs>
+ struct permute_tuple<C, Seq<IIs...> >
+ {
+ using type = std::tuple< typename std::tuple_element<IIs, C>::type... >;
+ };
+
+ // Given T..., generates a type sequence of sizeof...(T)-1 elements
+ // which is T... without its last element
+ // Implemented via tuple, with an interface to accept plain type lists
+ template<typename T, typename... Ts> struct all_but_last;
+
+ template<typename T, typename... Ts>
+ struct all_but_last<std::tuple<T, Ts...> >
+ {
+ using C = std::tuple<T, Ts...>;
+ using S = typename MkSeq<std::tuple_size<C>::value - 1>::type;
+ using type = typename permute_tuple<C, S>::type;
+ };
+
+ template<typename T, typename... Ts>
+ struct all_but_last: public all_but_last<std::tuple<T, Ts...> > {};
+
+ template<typename... Ts>
+ using all_but_last_t = typename all_but_last<Ts...>::type;
+
+ // NB.: This is here because there's no constexpr std::max in C++11
+ template<std::size_t S0, std::size_t... SS> struct max_of_t
+ {
+ static constexpr const std::size_t rest = max_of_t<SS...>::value;
+ static constexpr const std::size_t value = rest > S0 ? rest : S0;
+ };
+ template<std::size_t S> struct max_of_t<S>
+ {
+ static constexpr const std::size_t value = S;
+ };
+} // namespace detail
+} // namespace cv
+
+// \endcond
+
+#endif // OPENCV_GAPI_UTIL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/variant.hpp b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/variant.hpp
new file mode 100644
index 000000000..cb0270a73
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/include/opencv2/gapi/util/variant.hpp
@@ -0,0 +1,377 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_UTIL_VARIANT_HPP
+#define OPENCV_GAPI_UTIL_VARIANT_HPP
+
+#include <array>
+#include <type_traits>
+
+#include "opencv2/gapi/util/throw.hpp"
+#include "opencv2/gapi/util/util.hpp" // max_of_t
+
+// A poor man's `variant` implementation, incompletely modeled against C++17 spec.
+namespace cv
+{
+namespace util
+{
+ namespace detail
+ {
+ template<std::size_t I, typename Target, typename First, typename... Remaining>
+ struct type_list_index_helper
+ {
+ static const constexpr bool is_same = std::is_same<Target, First>::value;
+ static const constexpr std::size_t value =
+ std::conditional<is_same, std::integral_constant<std::size_t, I>, type_list_index_helper<I + 1, Target, Remaining...>>::type::value;
+ };
+
+ template<std::size_t I, typename Target, typename First>
+ struct type_list_index_helper<I, Target, First>
+ {
+ static_assert(std::is_same<Target, First>::value, "Type not found");
+ static const constexpr std::size_t value = I;
+ };
+
+
+ template<class T, class U, class V> using are_different =
+ std::enable_if<!std::is_same<typename std::decay<T>::type,
+ typename std::decay<U>::type>::value,
+ V>;
+ }
+
+ template<typename Target, typename... Types>
+ struct type_list_index
+ {
+ static const constexpr std::size_t value = detail::type_list_index_helper<0, Target, Types...>::value;
+ };
+
+ class bad_variant_access: public std::exception
+ {
+ public:
+ virtual const char *what() const noexcept override
+ {
+ return "Bad variant access";
+ }
+ };
+
+ // Interface ///////////////////////////////////////////////////////////////
+ struct monostate {};
+ inline bool operator==(const util::monostate&, const util::monostate&)
+ {
+ return true;
+ }
+
+ template<typename... Ts> // FIXME: no references, arrays, and void
+ class variant
+ {
+ // FIXME: Replace with std::aligned_union after gcc4.8 support is dropped
+ static constexpr const std::size_t S = cv::detail::max_of_t<sizeof(Ts)...>::value;
+ static constexpr const std::size_t A = cv::detail::max_of_t<alignof(Ts)...>::value;
+ using Memory = typename std::aligned_storage<S, A>::type[1];
+
+ template<typename T> struct cctr_h {
+ static void help(Memory memory, const Memory from) {
+ new (memory) T(*reinterpret_cast<const T*>(from));
+ }
+ };
+
+ template<typename T> struct vctr_h {
+ static void help(Memory memory, const void* pval) {
+ new (memory) T(*reinterpret_cast<const T*>(pval));
+ }
+ };
+
+ template<typename T> struct mctr_h {
+ static void help(Memory memory, void *pval) {
+ new (memory) T(std::move(*reinterpret_cast<T*>(pval)));
+ }
+ };
+
+ template<typename T> struct copy_h {
+ static void help(Memory to, const Memory from) {
+ *reinterpret_cast<T*>(to) = *reinterpret_cast<const T*>(from);
+ }
+ };
+
+ template<typename T> struct move_h {
+ static void help(Memory to, const Memory from) {
+ *reinterpret_cast<T*>(to) = std::move(*reinterpret_cast<const T*>(from));
+ }
+ };
+
+ template<typename T> struct swap_h {
+ static void help(Memory to, Memory from) {
+ std::swap(*reinterpret_cast<T*>(to), *reinterpret_cast<T*>(from));
+ }
+ };
+
+ template<typename T> struct dtor_h {
+ static void help(Memory memory) {
+ (void) memory; // MSCV warning
+ reinterpret_cast<T*>(memory)->~T();
+ }
+ };
+
+ template<typename T> struct equal_h {
+ static bool help(const Memory lhs, const Memory rhs) {
+ const T& t_lhs = *reinterpret_cast<const T*>(lhs);
+ const T& t_rhs = *reinterpret_cast<const T*>(rhs);
+ return t_lhs == t_rhs;
+ }
+ };
+
+ typedef void (*CCtr) (Memory, const Memory); // Copy c-tor (variant)
+ typedef void (*VCtr) (Memory, const void*); // Copy c-tor (value)
+ typedef void (*MCtr) (Memory, void*); // Generic move c-tor
+ typedef void (*Copy) (Memory, const Memory); // Copy assignment
+ typedef void (*Move) (Memory, const Memory); // Move assignment
+ typedef void (*Swap) (Memory, Memory); // Swap
+ typedef void (*Dtor) (Memory); // Destructor
+
+ typedef bool (*Equal)(const Memory, const Memory); // Equality test (external)
+
+ static constexpr std::array<CCtr, sizeof...(Ts)> cctrs(){ return {{(&cctr_h<Ts>::help)...}};}
+ static constexpr std::array<VCtr, sizeof...(Ts)> vctrs(){ return {{(&vctr_h<Ts>::help)...}};}
+ static constexpr std::array<MCtr, sizeof...(Ts)> mctrs(){ return {{(&mctr_h<Ts>::help)...}};}
+ static constexpr std::array<Copy, sizeof...(Ts)> cpyrs(){ return {{(&copy_h<Ts>::help)...}};}
+ static constexpr std::array<Move, sizeof...(Ts)> mvers(){ return {{(&move_h<Ts>::help)...}};}
+ static constexpr std::array<Swap, sizeof...(Ts)> swprs(){ return {{(&swap_h<Ts>::help)...}};}
+ static constexpr std::array<Dtor, sizeof...(Ts)> dtors(){ return {{(&dtor_h<Ts>::help)...}};}
+
+ std::size_t m_index = 0;
+
+ protected:
+ template<typename T, typename... Us> friend T& get(variant<Us...> &v);
+ template<typename T, typename... Us> friend const T& get(const variant<Us...> &v);
+ template<typename... Us> friend bool operator==(const variant<Us...> &lhs,
+ const variant<Us...> &rhs);
+ Memory memory;
+
+ public:
+ // Constructors
+ variant() noexcept;
+ variant(const variant& other);
+ variant(variant&& other) noexcept;
+ template<typename T> explicit variant(const T& t);
+ // are_different is a SFINAE trick to avoid variant(T &&t) with T=variant
+ // for some reason, this version is called instead of variant(variant&& o) when
+ // variant is used in STL containers (examples: vector assignment)
+ template<typename T> explicit variant(T&& t, typename detail::are_different<variant, T, int>::type = 0);
+ // template<class T, class... Args> explicit variant(Args&&... args);
+ // FIXME: other constructors
+
+ // Destructor
+ ~variant();
+
+ // Assignment
+ variant& operator=(const variant& rhs);
+ variant& operator=(variant &&rhs) noexcept;
+
+ // SFINAE trick to avoid operator=(T&&) with T=variant<>, see comment above
+ template<class T>
+ typename detail::are_different<variant, T, variant&>
+ ::type operator=(T&& t) noexcept;
+
+ // Observers
+ std::size_t index() const noexcept;
+ // FIXME: valueless_by_exception()
+
+ // Modifiers
+ // FIXME: emplace()
+ void swap(variant &rhs) noexcept;
+
+ // Non-C++17x!
+ template<typename T> static constexpr std::size_t index_of();
+ };
+
+ // FIMXE: visit
+
+ template<typename T, typename... Types>
+ T& get(util::variant<Types...> &v);
+
+ template<typename T, typename... Types>
+ const T& get(const util::variant<Types...> &v);
+
+ template<typename T, typename... Types>
+ bool holds_alternative(const util::variant<Types...> &v) noexcept;
+
+ // FIXME: T&&, const TT&& versions.
+
+ // Implementation //////////////////////////////////////////////////////////
+ template<typename... Ts>
+ variant<Ts...>::variant() noexcept
+ {
+ typedef typename std::tuple_element<0, std::tuple<Ts...> >::type TFirst;
+ new (memory) TFirst();
+ }
+
+ template<typename... Ts>
+ variant<Ts...>::variant(const variant &other)
+ : m_index(other.m_index)
+ {
+ (cctrs()[m_index])(memory, other.memory);
+ }
+
+ template<typename... Ts>
+ variant<Ts...>::variant(variant &&other) noexcept
+ : m_index(other.m_index)
+ {
+ (mctrs()[m_index])(memory, other.memory);
+ }
+
+ template<typename... Ts>
+ template<class T>
+ variant<Ts...>::variant(const T& t)
+ : m_index(util::type_list_index<T, Ts...>::value)
+ {
+ (vctrs()[m_index])(memory, &t);
+ }
+
+ template<typename... Ts>
+ template<class T>
+ variant<Ts...>::variant(T&& t, typename detail::are_different<variant, T, int>::type)
+ : m_index(util::type_list_index<typename std::remove_reference<T>::type, Ts...>::value)
+ {
+ (mctrs()[m_index])(memory, &t);
+ }
+
+ template<typename... Ts>
+ variant<Ts...>::~variant()
+ {
+ (dtors()[m_index])(memory);
+ }
+
+ template<typename... Ts>
+ variant<Ts...>& variant<Ts...>::operator=(const variant<Ts...> &rhs)
+ {
+ if (m_index != rhs.m_index)
+ {
+ (dtors()[ m_index])(memory);
+ (cctrs()[rhs.m_index])(memory, rhs.memory);
+ m_index = rhs.m_index;
+ }
+ else
+ {
+ (cpyrs()[rhs.m_index])(memory, rhs.memory);
+ }
+ return *this;
+ }
+
+ template<typename... Ts>
+ variant<Ts...>& variant<Ts...>::operator=(variant<Ts...> &&rhs) noexcept
+ {
+ if (m_index != rhs.m_index)
+ {
+ (dtors()[ m_index])(memory);
+ (mctrs()[rhs.m_index])(memory, rhs.memory);
+ m_index = rhs.m_index;
+ }
+ else
+ {
+ (mvers()[rhs.m_index])(memory, rhs.memory);
+ }
+ return *this;
+ }
+
+ template<typename... Ts>
+ template<class T> typename detail::are_different<variant<Ts...>, T, variant<Ts...>&>
+ ::type variant<Ts...>::operator=(T&& t) noexcept
+ {
+ // FIXME: No version with implicit type conversion available!
+ static const constexpr std::size_t t_index =
+ util::type_list_index<T, Ts...>::value;
+
+ if (t_index == m_index)
+ {
+ util::get<T>(*this) = std::move(t);
+ return *this;
+ }
+ else return (*this = variant(std::move(t)));
+ }
+
+ template<typename... Ts>
+ std::size_t util::variant<Ts...>::index() const noexcept
+ {
+ return m_index;
+ }
+
+ template<typename... Ts>
+ void variant<Ts...>::swap(variant<Ts...> &rhs) noexcept
+ {
+ if (m_index == rhs.index())
+ {
+ (swprs()[m_index](memory, rhs.memory));
+ }
+ else
+ {
+ variant<Ts...> tmp(std::move(*this));
+ *this = std::move(rhs);
+ rhs = std::move(tmp);
+ }
+ }
+
+ template<typename... Ts>
+ template<typename T>
+ constexpr std::size_t variant<Ts...>::index_of()
+ {
+ return util::type_list_index<T, Ts...>::value; // FIXME: tests!
+ }
+
+ template<typename T, typename... Types>
+ T& get(util::variant<Types...> &v)
+ {
+ const constexpr std::size_t t_index =
+ util::type_list_index<T, Types...>::value;
+
+ if (v.index() == t_index)
+ return reinterpret_cast<T&>(v.memory);
+ else
+ throw_error(bad_variant_access());
+ }
+
+ template<typename T, typename... Types>
+ const T& get(const util::variant<Types...> &v)
+ {
+ const constexpr std::size_t t_index =
+ util::type_list_index<T, Types...>::value;
+
+ if (v.index() == t_index)
+ return reinterpret_cast<const T&>(v.memory);
+ else
+ throw_error(bad_variant_access());
+ }
+
+ template<typename T, typename... Types>
+ bool holds_alternative(const util::variant<Types...> &v) noexcept
+ {
+ return v.index() == util::variant<Types...>::template index_of<T>();
+ }
+
+ template<typename... Us> bool operator==(const variant<Us...> &lhs,
+ const variant<Us...> &rhs)
+ {
+ using V = variant<Us...>;
+
+ // Instantiate table only here since it requires operator== for <Us...>
+ // <Us...> should have operator== only if this one is used, not in general
+ static const std::array<typename V::Equal, sizeof...(Us)> eqs = {
+ {(&V::template equal_h<Us>::help)...}
+ };
+ if (lhs.index() != rhs.index())
+ return false;
+ return (eqs[lhs.index()])(lhs.memory, rhs.memory);
+ }
+
+ template<typename... Us> bool operator!=(const variant<Us...> &lhs,
+ const variant<Us...> &rhs)
+ {
+ return !(lhs == rhs);
+ }
+} // namespace cv
+} // namespace util
+
+#endif // OPENCV_GAPI_UTIL_VARIANT_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests.cpp
new file mode 100644
index 000000000..2df4d8890
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests.cpp
@@ -0,0 +1,9 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "perf_precomp.hpp"
+#include "gapi_core_perf_tests_inl.hpp"
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests.hpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests.hpp
new file mode 100644
index 000000000..8af7b1abf
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests.hpp
@@ -0,0 +1,76 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_CORE_PERF_TESTS_HPP
+#define OPENCV_GAPI_CORE_PERF_TESTS_HPP
+
+
+#include "../../test/common/gapi_tests_common.hpp"
+#include "opencv2/gapi/core.hpp"
+
+namespace opencv_test
+{
+ using namespace perf;
+
+ enum bitwiseOp
+ {
+ AND = 0,
+ OR = 1,
+ XOR = 2,
+ NOT = 3
+ };
+
+//------------------------------------------------------------------------------
+
+ class AddPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class AddCPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class SubPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class SubCPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class SubRCPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class MulPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class MulDoublePerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class MulCPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class DivPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class DivCPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class DivRCPerfTest : public TestPerfParams<tuple<compare_f,cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class MaskPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class MeanPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class Polar2CartPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+ class Cart2PolarPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+ class CmpPerfTest : public TestPerfParams<tuple<CmpTypes, cv::Size, MatType, cv::GCompileArgs>> {};
+ class CmpWithScalarPerfTest : public TestPerfParams<tuple<CmpTypes, cv::Size, MatType, cv::GCompileArgs>> {};
+ class BitwisePerfTest : public TestPerfParams<tuple<bitwiseOp, cv::Size, MatType, cv::GCompileArgs>> {};
+ class BitwiseNotPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class SelectPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class MinPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class MaxPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class AbsDiffPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class AbsDiffCPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class SumPerfTest : public TestPerfParams<tuple<cv::Size, MatType, double, cv::GCompileArgs>> {};
+ class AddWeightedPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, double, cv::GCompileArgs>> {};
+ class NormPerfTest : public TestPerfParams<tuple<NormTypes, cv::Size, MatType, double, cv::GCompileArgs>> {};
+ class IntegralPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class ThresholdPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class ThresholdOTPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class InRangePerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class Split3PerfTest : public TestPerfParams<tuple<cv::Size, cv::GCompileArgs>> {};
+ class Split4PerfTest : public TestPerfParams<tuple<cv::Size, cv::GCompileArgs>> {};
+ class Merge3PerfTest : public TestPerfParams<tuple<cv::Size, cv::GCompileArgs>> {};
+ class Merge4PerfTest : public TestPerfParams<tuple<cv::Size, cv::GCompileArgs>> {};
+ class RemapPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class FlipPerfTest : public TestPerfParams<tuple<cv::Size, MatType, int, cv::GCompileArgs>> {};
+ class CropPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::Rect, cv::GCompileArgs>> {};
+ class ConcatHorPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class ConcatHorVecPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class ConcatVertPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class ConcatVertVecPerfTest : public TestPerfParams<tuple<cv::Size, MatType, cv::GCompileArgs>> {};
+ class LUTPerfTest : public TestPerfParams<tuple<MatType, MatType, cv::Size, cv::GCompileArgs>> {};
+ class ConvertToPerfTest : public TestPerfParams<tuple<MatType, int, cv::Size, cv::GCompileArgs>> {};
+ class ResizePerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, cv::Size, cv::GCompileArgs>> {};
+ class ResizeFxFyPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, double, double, cv::GCompileArgs>> {};
+}
+#endif // OPENCV_GAPI_CORE_PERF_TESTS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests_inl.hpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests_inl.hpp
new file mode 100644
index 000000000..f49e06161
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_core_perf_tests_inl.hpp
@@ -0,0 +1,1841 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_CORE_PERF_TESTS_INL_HPP
+#define OPENCV_GAPI_CORE_PERF_TESTS_INL_HPP
+
+#include <iostream>
+
+#include "gapi_core_perf_tests.hpp"
+
+namespace opencv_test
+{
+using namespace perf;
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(AddPerfTest, TestPerformance)
+{
+ Size sz = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::add(in_mat1, in_mat2, out_mat_ocv, cv::noArray(), dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out;
+ out = cv::gapi::add(in1, in2, dtype);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(AddCPerfTest, TestPerformance)
+{
+ Size sz = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::add(in_mat1, sc, out_mat_ocv, cv::noArray(), dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar sc1;
+ out = cv::gapi::addC(in1, sc1, dtype);
+ cv::GComputation c(GIn(in1, sc1), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(SubPerfTest, TestPerformance)
+{
+ Size sz = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::subtract(in_mat1, in_mat2, out_mat_ocv, cv::noArray(), dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out;
+ out = cv::gapi::sub(in1, in2, dtype);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(SubCPerfTest, TestPerformance)
+{
+ Size sz = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::subtract(in_mat1, sc, out_mat_ocv, cv::noArray(), dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar sc1;
+ out = cv::gapi::subC(in1, sc1, dtype);
+ cv::GComputation c(GIn(in1, sc1), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(SubRCPerfTest, TestPerformance)
+{
+ Size sz = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::subtract(sc, in_mat1, out_mat_ocv, cv::noArray(), dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar sc1;
+ out = cv::gapi::subRC(sc1, in1, dtype);
+ cv::GComputation c(GIn(in1, sc1), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(MulPerfTest, TestPerformance)
+{
+ Size sz = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::multiply(in_mat1, in_mat2, out_mat_ocv, 1.0, dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out;
+ out = cv::gapi::mul(in1, in2, 1.0, dtype);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(MulDoublePerfTest, TestPerformance)
+{
+ Size sz = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ auto& rng = cv::theRNG();
+ double d = rng.uniform(0.0, 10.0);
+ initMatrixRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::multiply(in_mat1, d, out_mat_ocv, 1, dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ out = cv::gapi::mulC(in1, d, dtype);
+ cv::GComputation c(in1, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(MulCPerfTest, TestPerformance)
+{
+ Size sz = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::multiply(in_mat1, sc, out_mat_ocv, 1, dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar sc1;
+ out = cv::gapi::mulC(in1, sc1, dtype);
+ cv::GComputation c(GIn(in1, sc1), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(DivPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ MatType type = get<2>(GetParam());
+ int dtype = get<3>(GetParam());
+ cv::GCompileArgs compile_args = get<4>(GetParam());
+
+ // FIXIT Unstable input data for divide
+ initMatsRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::divide(in_mat1, in_mat2, out_mat_ocv, dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out;
+ out = cv::gapi::div(in1, in2, dtype);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(DivCPerfTest, TestPerformance)
+{
+ Size sz = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ // FIXIT Unstable input data for divide
+ initMatsRandU(type, sz, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::divide(in_mat1, sc, out_mat_ocv, 1.0, dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar sc1;
+ out = cv::gapi::divC(in1, sc1, 1.0, dtype);
+ cv::GComputation c(GIn(in1, sc1), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(DivRCPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ MatType type = get<2>(GetParam());
+ int dtype = get<3>(GetParam());
+ cv::GCompileArgs compile_args = get<4>(GetParam());
+
+ // FIXIT Unstable input data for divide
+ initMatsRandU(type, sz, dtype, false);
+
+ // FIXIT Unstable input data for divide, don't process zeros
+ sc += Scalar::all(1);
+ in_mat1 += 1;
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::divide(sc, in_mat1, out_mat_ocv, 1.0, dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar sc1;
+ out = cv::gapi::divRC(sc1, in1, 1.0, dtype);
+ cv::GComputation c(GIn(in1, sc1), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(MaskPerfTest, TestPerformance)
+{
+ Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatrixRandU(type, sz_in, type, false);
+ in_mat2 = cv::Mat(sz_in, CV_8UC1);
+ cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+ in_mat2 = in_mat2 > 128;
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ out_mat_ocv = cv::Mat::zeros(in_mat1.size(), in_mat1.type());
+ in_mat1.copyTo(out_mat_ocv, in_mat2);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in, m;
+ auto out = cv::gapi::mask(in, m);
+ cv::GComputation c(cv::GIn(in, m), cv::GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(MeanPerfTest, TestPerformance)
+{
+ Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatrixRandU(type, sz_in, false);
+ cv::Scalar out_norm;
+ cv::Scalar out_norm_ocv;
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ out_norm_ocv = cv::mean(in_mat1);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::mean(in);
+ cv::GComputation c(cv::GIn(in), cv::GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(cv::gin(in_mat1), cv::gout(out_norm), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1), cv::gout(out_norm), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(out_norm[0], out_norm_ocv[0]);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(Polar2CartPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz_in = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandU(CV_32FC1, sz_in, CV_32FC1, false);
+ cv::Mat out_mat2;
+ cv::Mat out_mat_ocv2;
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::polarToCart(in_mat1, in_mat2, out_mat_ocv, out_mat_ocv2);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out1, out2;
+ std::tie(out1, out2) = cv::gapi::polarToCart(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out1, out2));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi, out_mat2), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi, out_mat2), std::move(compile_args));
+ }
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_TRUE(cmpF(out_mat_ocv2, out_mat2));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(Cart2PolarPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz_in = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandU(CV_32FC1, sz_in, CV_32FC1, false);
+ cv::Mat out_mat2(sz_in, CV_32FC1);
+ cv::Mat out_mat_ocv2(sz_in, CV_32FC1);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::cartToPolar(in_mat1, in_mat2, out_mat_ocv, out_mat_ocv2);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out1, out2;
+ std::tie(out1, out2) = cv::gapi::cartToPolar(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out1, out2));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi, out_mat2), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi, out_mat2), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_TRUE(cmpF(out_mat_ocv2, out_mat2));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(CmpPerfTest, TestPerformance)
+{
+ CmpTypes opType = get<0>(GetParam());
+ cv::Size sz = get<1>(GetParam());
+ MatType type = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, CV_8U, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::compare(in_mat1, in_mat2, out_mat_ocv, opType);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out;
+ switch (opType)
+ {
+ case CMP_EQ: out = cv::gapi::cmpEQ(in1, in2); break;
+ case CMP_GT: out = cv::gapi::cmpGT(in1, in2); break;
+ case CMP_GE: out = cv::gapi::cmpGE(in1, in2); break;
+ case CMP_LT: out = cv::gapi::cmpLT(in1, in2); break;
+ case CMP_LE: out = cv::gapi::cmpLE(in1, in2); break;
+ case CMP_NE: out = cv::gapi::cmpNE(in1, in2); break;
+ default: FAIL() << "no such compare operation type for two matrices!";
+ }
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(CmpWithScalarPerfTest, TestPerformance)
+{
+ CmpTypes opType = get<0>(GetParam());
+ cv::Size sz = get<1>(GetParam());
+ MatType type = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, CV_8U, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::compare(in_mat1, sc, out_mat_ocv, opType);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar in2;
+ switch (opType)
+ {
+ case CMP_EQ: out = cv::gapi::cmpEQ(in1, in2); break;
+ case CMP_GT: out = cv::gapi::cmpGT(in1, in2); break;
+ case CMP_GE: out = cv::gapi::cmpGE(in1, in2); break;
+ case CMP_LT: out = cv::gapi::cmpLT(in1, in2); break;
+ case CMP_LE: out = cv::gapi::cmpLE(in1, in2); break;
+ case CMP_NE: out = cv::gapi::cmpNE(in1, in2); break;
+ default: FAIL() << "no such compare operation type for matrix and scalar!";
+ }
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(BitwisePerfTest, TestPerformance)
+{
+ bitwiseOp opType = get<0>(GetParam());
+ cv::Size sz = get<1>(GetParam());
+ MatType type = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatsRandU(type, sz, type, false);
+
+ // G-API code & corresponding OpenCV code ////////////////////////////////
+ cv::GMat in1, in2, out;
+ switch (opType)
+ {
+ case AND:
+ {
+ out = cv::gapi::bitwise_and(in1, in2);
+ cv::bitwise_and(in_mat1, in_mat2, out_mat_ocv);
+ break;
+ }
+ case OR:
+ {
+ out = cv::gapi::bitwise_or(in1, in2);
+ cv::bitwise_or(in_mat1, in_mat2, out_mat_ocv);
+ break;
+ }
+ case XOR:
+ {
+ out = cv::gapi::bitwise_xor(in1, in2);
+ cv::bitwise_xor(in_mat1, in_mat2, out_mat_ocv);
+ break;
+ }
+ default:
+ {
+ FAIL() << "no such bitwise operation type!";
+ }
+ }
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(BitwiseNotPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatrixRandU(type, sz_in, type, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::bitwise_not(in_mat1, out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in, out;
+ out = cv::gapi::bitwise_not(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(SelectPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandU(type, sz_in, type, false);
+ cv::Mat in_mask(sz_in, CV_8UC1);
+ cv::randu(in_mask, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ in_mat2.copyTo(out_mat_ocv);
+ in_mat1.copyTo(out_mat_ocv, in_mask);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, in3, out;
+ out = cv::gapi::select(in1, in2, in3);
+ cv::GComputation c(GIn(in1, in2, in3), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2, in_mask), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2, in_mask), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(MinPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+
+ initMatsRandU(type, sz_in, type, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::min(in_mat1, in_mat2, out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out;
+ out = cv::gapi::min(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(MaxPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+
+ initMatsRandU(type, sz_in, type, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::max(in_mat1, in_mat2, out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out;
+ out = cv::gapi::max(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(AbsDiffPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+
+ initMatsRandU(type, sz_in, type, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::absdiff(in_mat1, in_mat2, out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out;
+ out = cv::gapi::absDiff(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(AbsDiffCPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+
+ initMatsRandU(type, sz_in, type, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::absdiff(in_mat1, sc, out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar sc1;
+ out = cv::gapi::absDiffC(in1, sc1);
+ cv::GComputation c(cv::GIn(in1, sc1), cv::GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(SumPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ double tolerance = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+
+ initMatrixRandU(type, sz_in, false);
+ cv::Scalar out_sum;
+ cv::Scalar out_sum_ocv;
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ out_sum_ocv = cv::sum(in_mat1);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::sum(in);
+ cv::GComputation c(cv::GIn(in), cv::GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(cv::gin(in_mat1), cv::gout(out_sum), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1), cv::gout(out_sum), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ {
+ EXPECT_LE(std::abs(out_sum[0] - out_sum_ocv[0]) / std::max(1.0, std::abs(out_sum_ocv[0])), tolerance)
+ << "OCV=" << out_sum_ocv[0] << " GAPI=" << out_sum[0];
+ }
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(AddWeightedPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int dtype = get<2>(GetParam());
+ double tolerance = get<3>(GetParam());
+ cv::GCompileArgs compile_args = get<4>(GetParam());
+
+ auto& rng = cv::theRNG();
+ double alpha = rng.uniform(0.0, 1.0);
+ double beta = rng.uniform(0.0, 1.0);
+ double gamma = rng.uniform(0.0, 1.0);
+ initMatsRandU(type, sz_in, dtype, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::addWeighted(in_mat1, alpha, in_mat2, beta, gamma, out_mat_ocv, dtype);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::addWeighted(in1, alpha, in2, beta, gamma, dtype);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check
+ if (0)
+ {
+ // Note, that we cannot expect bitwise results for add-weighted:
+ //
+ // tmp = src1*alpha + src2*beta + gamma;
+ // dst = saturate<DST>( round(tmp) );
+ //
+ // Because tmp is floating-point, dst depends on compiler optimizations
+ //
+ // However, we must expect good accuracy of tmp, and rounding correctly
+
+ cv::Mat failures;
+
+ if (out_mat_ocv.type() == CV_32FC1)
+ {
+ // result: float - may vary in 7th decimal digit
+ failures = abs(out_mat_gapi - out_mat_ocv) > abs(out_mat_ocv) * 1e-6;
+ }
+ else
+ {
+ // result: integral - rounding may vary if fractional part of tmp
+ // is nearly 0.5
+
+ cv::Mat inexact, incorrect, diff, tmp;
+
+ inexact = out_mat_gapi != out_mat_ocv;
+
+ // even if rounded differently, check if still rounded correctly
+ cv::addWeighted(in_mat1, alpha, in_mat2, beta, gamma, tmp, CV_32F);
+ cv::subtract(out_mat_gapi, tmp, diff, cv::noArray(), CV_32F);
+ incorrect = abs(diff) >= tolerance;// 0.5000005f; // relative to 6 digits
+
+ failures = inexact & incorrect;
+ }
+
+ EXPECT_EQ(0, cv::countNonZero(failures));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(NormPerfTest, TestPerformance)
+{
+ NormTypes opType = get<0>(GetParam());
+ cv::Size sz = get<1>(GetParam());
+ MatType type = get<2>(GetParam());
+ double tolerance = get<3>(GetParam());
+ cv::GCompileArgs compile_args = get<4>(GetParam());
+
+
+ initMatrixRandU(type, sz, type, false);
+ cv::Scalar out_norm;
+ cv::Scalar out_norm_ocv;
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ out_norm_ocv = cv::norm(in_mat1, opType);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1;
+ cv::GScalar out;
+ switch (opType)
+ {
+ case NORM_L1: out = cv::gapi::normL1(in1); break;
+ case NORM_L2: out = cv::gapi::normL2(in1); break;
+ case NORM_INF: out = cv::gapi::normInf(in1); break;
+ default: FAIL() << "no such norm operation type!";
+ }
+ cv::GComputation c(GIn(in1), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1), gout(out_norm), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1), gout(out_norm), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ {
+ EXPECT_LE(std::abs(out_norm[0] - out_norm_ocv[0]) / std::max(1.0, std::abs(out_norm_ocv[0])), tolerance)
+ << "OCV=" << out_norm_ocv[0] << " GAPI=" << out_norm[0];
+ }
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(IntegralPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+
+ MatType type_out = (type == CV_8U) ? CV_32SC1 : CV_64FC1;
+
+
+ in_mat1 = cv::Mat(sz_in, type);
+ cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ cv::Size sz_out = cv::Size(sz_in.width + 1, sz_in.height + 1);
+ cv::Mat out_mat1(sz_out, type_out);
+ cv::Mat out_mat_ocv1(sz_out, type_out);
+
+ cv::Mat out_mat2(sz_out, CV_64FC1);
+ cv::Mat out_mat_ocv2(sz_out, CV_64FC1);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::integral(in_mat1, out_mat_ocv1, out_mat_ocv2);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out1, out2;
+ std::tie(out1, out2) = cv::gapi::integral(in1, type_out, CV_64FC1);
+ cv::GComputation c(cv::GIn(in1), cv::GOut(out1, out2));
+
+ // Warm-up graph engine:
+ c.apply(cv::gin(in_mat1), cv::gout(out_mat1, out_mat2), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1), cv::gout(out_mat1, out_mat2), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_ocv1 != out_mat1));
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_ocv2 != out_mat2));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ThresholdPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int tt = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ cv::Scalar thr = initScalarRandU(50);
+ cv::Scalar maxval = initScalarRandU(50) + cv::Scalar(50, 50, 50, 50);
+ initMatrixRandU(type, sz_in, type, false);
+ cv::Scalar out_scalar;
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::threshold(in_mat1, out_mat_ocv, thr.val[0], maxval.val[0], tt);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar th1, mv1;
+ out = cv::gapi::threshold(in1, th1, mv1, tt);
+ cv::GComputation c(GIn(in1, th1, mv1), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, thr, maxval), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, thr, maxval), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ThresholdOTPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int tt = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ cv::Scalar maxval = initScalarRandU(50) + cv::Scalar(50, 50, 50, 50);
+ initMatrixRandU(type, sz_in, type, false);
+ cv::Scalar out_gapi_scalar;
+ double ocv_res;
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ ocv_res = cv::threshold(in_mat1, out_mat_ocv, maxval.val[0], maxval.val[0], tt);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar mv1, scout;
+ std::tie<cv::GMat, cv::GScalar>(out, scout) = cv::gapi::threshold(in1, mv1, tt);
+ cv::GComputation c(cv::GIn(in1, mv1), cv::GOut(out, scout));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, maxval), gout(out_mat_gapi, out_gapi_scalar), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, maxval), gout(out_mat_gapi, out_gapi_scalar), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ EXPECT_EQ(ocv_res, out_gapi_scalar.val[0]);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(InRangePerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ cv::Scalar thrLow = initScalarRandU(100);
+ cv::Scalar thrUp = initScalarRandU(100) + cv::Scalar(100, 100, 100, 100);
+ initMatrixRandU(type, sz_in, type, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::inRange(in_mat1, thrLow, thrUp, out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1;
+ cv::GScalar th1, mv1;
+ auto out = cv::gapi::inRange(in1, th1, mv1);
+ cv::GComputation c(GIn(in1, th1, mv1), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, thrLow, thrUp), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, thrLow, thrUp), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(Split3PerfTest, TestPerformance)
+{
+ Size sz_in = get<0>(GetParam());
+ cv::GCompileArgs compile_args = get<1>(GetParam());
+
+
+ initMatrixRandU(CV_8UC3, sz_in, CV_8UC1);
+ cv::Mat out_mat2 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat3 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv2 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv3 = cv::Mat(sz_in, CV_8UC1);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ std::vector<cv::Mat> out_mats_ocv = { out_mat_ocv, out_mat_ocv2, out_mat_ocv3 };
+ cv::split(in_mat1, out_mats_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out1, out2, out3;
+ std::tie(out1, out2, out3) = cv::gapi::split3(in1);
+ cv::GComputation c(cv::GIn(in1), cv::GOut(out1, out2, out3));
+
+ // Warm-up graph engine:
+ c.apply(cv::gin(in_mat1), cv::gout(out_mat_gapi, out_mat2, out_mat3), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1), cv::gout(out_mat_gapi, out_mat2, out_mat3), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(0, cv::norm(out_mat_ocv2, out_mat2, NORM_INF));
+ EXPECT_EQ(0, cv::norm(out_mat_ocv3, out_mat3, NORM_INF));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(Split4PerfTest, TestPerformance)
+{
+ Size sz_in = get<0>(GetParam());
+ cv::GCompileArgs compile_args = get<1>(GetParam());
+
+ initMatrixRandU(CV_8UC4, sz_in, CV_8UC1);
+ cv::Mat out_mat2 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat3 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat4 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv2 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv3 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv4 = cv::Mat(sz_in, CV_8UC1);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ std::vector<cv::Mat> out_mats_ocv = { out_mat_ocv, out_mat_ocv2, out_mat_ocv3, out_mat_ocv4 };
+ cv::split(in_mat1, out_mats_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out1, out2, out3, out4;
+ std::tie(out1, out2, out3, out4) = cv::gapi::split4(in1);
+ cv::GComputation c(cv::GIn(in1), cv::GOut(out1, out2, out3, out4));
+
+ // Warm-up graph engine:
+ c.apply(cv::gin(in_mat1), cv::gout(out_mat_gapi, out_mat2, out_mat3, out_mat4), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1), cv::gout(out_mat_gapi, out_mat2, out_mat3, out_mat4), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(0, cv::norm(out_mat_ocv2, out_mat2, NORM_INF));
+ EXPECT_EQ(0, cv::norm(out_mat_ocv3, out_mat3, NORM_INF));
+ EXPECT_EQ(0, cv::norm(out_mat_ocv4, out_mat4, NORM_INF));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(Merge3PerfTest, TestPerformance)
+{
+ Size sz_in = get<0>(GetParam());
+ cv::GCompileArgs compile_args = get<1>(GetParam());
+
+ initMatsRandU(CV_8UC1, sz_in, CV_8UC3);
+ cv::Mat in_mat3(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+ cv::randn(in_mat3, mean, stddev);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ std::vector<cv::Mat> in_mats_ocv = { in_mat1, in_mat2, in_mat3 };
+ cv::merge(in_mats_ocv, out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, in3;
+ auto out = cv::gapi::merge3(in1, in2, in3);
+ cv::GComputation c(cv::GIn(in1, in2, in3), cv::GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(cv::gin(in_mat1, in_mat2, in_mat3), cv::gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1, in_mat2, in_mat3), cv::gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(Merge4PerfTest, TestPerformance)
+{
+ Size sz_in = get<0>(GetParam());
+ cv::GCompileArgs compile_args = get<1>(GetParam());
+
+ initMatsRandU(CV_8UC1, sz_in, CV_8UC3);
+ cv::Mat in_mat3(sz_in, CV_8UC1);
+ cv::Mat in_mat4(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+ cv::randn(in_mat3, mean, stddev);
+ cv::randn(in_mat4, mean, stddev);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ std::vector<cv::Mat> in_mats_ocv = { in_mat1, in_mat2, in_mat3, in_mat4 };
+ cv::merge(in_mats_ocv, out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, in3, in4;
+ auto out = cv::gapi::merge4(in1, in2, in3, in4);
+ cv::GComputation c(cv::GIn(in1, in2, in3, in4), cv::GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(cv::gin(in_mat1, in_mat2, in_mat3, in_mat4), cv::gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1, in_mat2, in_mat3, in_mat4), cv::gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(RemapPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatrixRandU(type, sz_in, type, false);
+ cv::Mat in_map1(sz_in, CV_16SC2);
+ cv::Mat in_map2 = cv::Mat();
+ cv::randu(in_map1, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::Scalar bv = cv::Scalar();
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::remap(in_mat1, out_mat_ocv, in_map1, in_map2, cv::INTER_NEAREST, cv::BORDER_REPLICATE, bv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1;
+ auto out = cv::gapi::remap(in1, in_map1, in_map2, cv::INTER_NEAREST, cv::BORDER_REPLICATE, bv);
+ cv::GComputation c(in1, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(FlipPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int flipCode = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatrixRandU(type, sz_in, type, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::flip(in_mat1, out_mat_ocv, flipCode);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::flip(in, flipCode);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(CropPerfTest, TestPerformance)
+{
+ cv::Size sz_in = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::Rect rect_to = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatrixRandU(type, sz_in, type, false);
+ cv::Size sz_out = cv::Size(rect_to.width, rect_to.height);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::Mat(in_mat1, rect_to).copyTo(out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::crop(in, rect_to);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz_out);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ConcatHorPerfTest, TestPerformance)
+{
+ cv::Size sz_out = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ int wpart = sz_out.width / 4;
+
+ cv::Size sz_in1 = cv::Size(wpart, sz_out.height);
+ cv::Size sz_in2 = cv::Size(sz_out.width - wpart, sz_out.height);
+
+ in_mat1 = cv::Mat(sz_in1, type);
+ in_mat2 = cv::Mat(sz_in2, type);
+
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+ cv::randn(in_mat2, mean, stddev);
+
+ out_mat_gapi = cv::Mat(sz_out, type);
+ out_mat_ocv = cv::Mat(sz_out, type);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::hconcat(in_mat1, in_mat2, out_mat_ocv);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::concatHor(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ConcatHorVecPerfTest, TestPerformance)
+{
+ cv::Size sz_out = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ int wpart1 = sz_out.width / 3;
+ int wpart2 = sz_out.width / 2;
+
+ cv::Size sz_in1 = cv::Size(wpart1, sz_out.height);
+ cv::Size sz_in2 = cv::Size(wpart2, sz_out.height);
+ cv::Size sz_in3 = cv::Size(sz_out.width - wpart1 - wpart2, sz_out.height);
+
+ in_mat1 = cv::Mat(sz_in1, type);
+ in_mat2 = cv::Mat(sz_in2, type);
+ cv::Mat in_mat3(sz_in3, type);
+
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+ cv::randn(in_mat2, mean, stddev);
+ cv::randn(in_mat3, mean, stddev);
+
+ out_mat_gapi = cv::Mat(sz_out, type);
+ out_mat_ocv = cv::Mat(sz_out, type);
+
+ std::vector <cv::Mat> cvmats = { in_mat1, in_mat2, in_mat3 };
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::hconcat(cvmats, out_mat_ocv);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ std::vector <cv::GMat> mats(3);
+ auto out = cv::gapi::concatHor(mats);
+ cv::GComputation c({ mats[0], mats[1], mats[2] }, { out });
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2, in_mat3), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2, in_mat3), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ConcatVertPerfTest, TestPerformance)
+{
+ cv::Size sz_out = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ int hpart = sz_out.height * 2 / 3;
+
+ cv::Size sz_in1 = cv::Size(sz_out.width, hpart);
+ cv::Size sz_in2 = cv::Size(sz_out.width, sz_out.height - hpart);
+
+ in_mat1 = cv::Mat(sz_in1, type);
+ in_mat2 = cv::Mat(sz_in2, type);
+
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+ cv::randn(in_mat2, mean, stddev);
+
+ out_mat_gapi = cv::Mat(sz_out, type);
+ out_mat_ocv = cv::Mat(sz_out, type);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::vconcat(in_mat1, in_mat2, out_mat_ocv);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::concatVert(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ConcatVertVecPerfTest, TestPerformance)
+{
+ cv::Size sz_out = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ int hpart1 = sz_out.height * 2 / 5;
+ int hpart2 = sz_out.height / 5;
+
+ cv::Size sz_in1 = cv::Size(sz_out.width, hpart1);
+ cv::Size sz_in2 = cv::Size(sz_out.width, hpart2);
+ cv::Size sz_in3 = cv::Size(sz_out.width, sz_out.height - hpart1 - hpart2);
+
+ in_mat1 = cv::Mat(sz_in1, type);
+ in_mat2 = cv::Mat(sz_in2, type);
+ cv::Mat in_mat3(sz_in3, type);
+
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+ cv::randn(in_mat2, mean, stddev);
+ cv::randn(in_mat3, mean, stddev);
+
+ out_mat_gapi = cv::Mat(sz_out, type);
+ out_mat_ocv = cv::Mat(sz_out, type);
+
+ std::vector <cv::Mat> cvmats = { in_mat1, in_mat2, in_mat3 };
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::vconcat(cvmats, out_mat_ocv);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ std::vector <cv::GMat> mats(3);
+ auto out = cv::gapi::concatVert(mats);
+ cv::GComputation c({ mats[0], mats[1], mats[2] }, { out });
+
+ // Warm-up graph engine:
+ c.apply(gin(in_mat1, in_mat2, in_mat3), gout(out_mat_gapi), std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(gin(in_mat1, in_mat2, in_mat3), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(LUTPerfTest, TestPerformance)
+{
+ MatType type_mat = get<0>(GetParam());
+ MatType type_lut = get<1>(GetParam());
+ MatType type_out = CV_MAKETYPE(CV_MAT_DEPTH(type_lut), CV_MAT_CN(type_mat));
+ cv::Size sz_in = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+
+ initMatrixRandU(type_mat, sz_in, type_out);
+ cv::Size sz_lut = cv::Size(1, 256);
+ cv::Mat in_lut(sz_lut, type_lut);
+ cv::randu(in_lut, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::LUT(in_mat1, in_lut, out_mat_ocv);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::LUT(in, in_lut);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ConvertToPerfTest, TestPerformance)
+{
+ MatType type_mat = get<0>(GetParam());
+ int depth_to = get<1>(GetParam());
+ cv::Size sz_in = get<2>(GetParam());
+ cv::GCompileArgs compile_args = get<3>(GetParam());
+ MatType type_out = CV_MAKETYPE(depth_to, CV_MAT_CN(type_mat));
+
+ initMatrixRandU(type_mat, sz_in, type_out);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ in_mat1.convertTo(out_mat_ocv, depth_to);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::convertTo(in, depth_to);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ // FIXIT unrealiable check: EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ResizePerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int interp = get<2>(GetParam());
+ cv::Size sz_in = get<3>(GetParam());
+ cv::Size sz_out = get<4>(GetParam());
+ cv::GCompileArgs compile_args = get<5>(GetParam());
+
+ in_mat1 = cv::Mat(sz_in, type);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+ cv::randn(in_mat1, mean, stddev);
+ out_mat_gapi = cv::Mat(sz_out, type);
+ out_mat_ocv = cv::Mat(sz_out, type);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::resize(in_mat1, out_mat_ocv, sz_out, 0.0, 0.0, interp);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::resize(in, sz_out, 0.0, 0.0, interp);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ }
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ResizeFxFyPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ MatType type = get<1>(GetParam());
+ int interp = get<2>(GetParam());
+ cv::Size sz_in = get<3>(GetParam());
+ double fx = get<4>(GetParam());
+ double fy = get<5>(GetParam());
+ cv::GCompileArgs compile_args = get<6>(GetParam());
+
+ in_mat1 = cv::Mat(sz_in, type);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+ cv::randn(in_mat1, mean, stddev);
+ cv::Size sz_out = cv::Size(saturate_cast<int>(sz_in.width *fx), saturate_cast<int>(sz_in.height*fy));
+ out_mat_gapi = cv::Mat(sz_out, type);
+ out_mat_ocv = cv::Mat(sz_out, type);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::resize(in_mat1, out_mat_ocv, sz_out, fx, fy, interp);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::resize(in, sz_out, fx, fy, interp);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison ////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ }
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+}
+#endif // OPENCV_GAPI_CORE_PERF_TESTS_INL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests.cpp
new file mode 100644
index 000000000..5a2ffb88a
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests.cpp
@@ -0,0 +1,9 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "perf_precomp.hpp"
+#include "gapi_imgproc_perf_tests_inl.hpp"
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp
new file mode 100644
index 000000000..750c0692c
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp
@@ -0,0 +1,46 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_IMGPROC_PERF_TESTS_HPP
+#define OPENCV_GAPI_IMGPROC_PERF_TESTS_HPP
+
+
+
+#include "../../test/common/gapi_tests_common.hpp"
+#include "opencv2/gapi/imgproc.hpp"
+
+namespace opencv_test
+{
+
+ using namespace perf;
+
+ //------------------------------------------------------------------------------
+
+class SepFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, int, cv::GCompileArgs>> {};
+class Filter2DPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
+class BoxFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
+class BlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
+class GaussianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, cv::GCompileArgs>> {};
+class MedianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size, cv::GCompileArgs>> {};
+class ErodePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
+class Erode3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType, cv::Size, int, cv::GCompileArgs>> {};
+class DilatePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
+class Dilate3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
+class SobelPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int,int, cv::GCompileArgs>> {};
+class CannyPerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,double,double,int,bool, cv::GCompileArgs>> {};
+class EqHistPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
+class RGB2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
+class BGR2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
+class RGB2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
+class YUV2RGBPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
+class RGB2LabPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class BGR2LUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class LUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class BGR2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+class YUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
+}
+#endif //OPENCV_GAPI_IMGPROC_PERF_TESTS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp
new file mode 100644
index 000000000..5a13cfeeb
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp
@@ -0,0 +1,909 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_IMGPROC_PERF_TESTS_INL_HPP
+#define OPENCV_GAPI_IMGPROC_PERF_TESTS_INL_HPP
+
+
+#include <iostream>
+
+#include "gapi_imgproc_perf_tests.hpp"
+
+namespace opencv_test
+{
+
+ using namespace perf;
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(SepFilterPerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, dtype = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, dtype, compile_args) = GetParam();
+
+ cv::Mat kernelX(kernSize, 1, CV_32F);
+ cv::Mat kernelY(kernSize, 1, CV_32F);
+ randu(kernelX, -1, 1);
+ randu(kernelY, -1, 1);
+ initMatsRandN(type, sz, dtype, false);
+
+ cv::Point anchor = cv::Point(-1, -1);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::sepFilter2D(in_mat1, out_mat_ocv, dtype, kernelX, kernelY );
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::sepFilter(in, dtype, kernelX, kernelY, anchor, cv::Scalar() );
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(Filter2DPerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, borderType = 0, dtype = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, borderType, dtype, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, dtype, false);
+
+ cv::Point anchor = {-1, -1};
+ double delta = 0;
+
+ cv::Mat kernel = cv::Mat(kernSize, kernSize, CV_32FC1 );
+ cv::Scalar kernMean = cv::Scalar::all(1.0);
+ cv::Scalar kernStddev = cv::Scalar::all(2.0/3);
+ randn(kernel, kernMean, kernStddev);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::filter2D(in_mat1, out_mat_ocv, dtype, kernel, anchor, delta, borderType);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::filter2D(in, dtype, kernel, anchor, delta, borderType);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(BoxFilterPerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int filterSize = 0, borderType = 0, dtype = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, filterSize, sz, borderType, dtype, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, dtype, false);
+
+ cv::Point anchor = {-1, -1};
+ bool normalize = true;
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::boxFilter(in_mat1, out_mat_ocv, dtype, cv::Size(filterSize, filterSize), anchor, normalize, borderType);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::boxFilter(in, dtype, cv::Size(filterSize, filterSize), anchor, normalize, borderType);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(BlurPerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int filterSize = 0, borderType = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, filterSize, sz, borderType, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, type, false);
+
+ cv::Point anchor = {-1, -1};
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::blur(in_mat1, out_mat_ocv, cv::Size(filterSize, filterSize), anchor, borderType);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::blur(in, cv::Size(filterSize, filterSize), anchor, borderType);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(GaussianBlurPerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, compile_args) = GetParam();
+
+ cv::Size kSize = cv::Size(kernSize, kernSize);
+ auto& rng = cv::theRNG();
+ double sigmaX = rng();
+ initMatsRandN(type, sz, type, false);
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::GaussianBlur(in_mat1, out_mat_ocv, kSize, sigmaX);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::gaussianBlur(in, kSize, sigmaX);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(MedianBlurPerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, type, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::medianBlur(in_mat1, out_mat_ocv, kernSize);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::medianBlur(in, kernSize);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(ErodePerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, kernType = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, kernType, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, type, false);
+
+ cv::Mat kernel = cv::getStructuringElement(kernType, cv::Size(kernSize, kernSize));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::erode(in_mat1, out_mat_ocv, kernel);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::erode(in, kernel);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(Erode3x3PerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int numIters = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, sz, numIters, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, type, false);
+
+ cv::Mat kernel = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(3, 3));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::erode(in_mat1, out_mat_ocv, kernel, cv::Point(-1, -1), numIters);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::erode3x3(in, numIters);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(DilatePerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, kernType = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, kernType, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, type, false);
+
+ cv::Mat kernel = cv::getStructuringElement(kernType, cv::Size(kernSize, kernSize));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::dilate(in_mat1, out_mat_ocv, kernel);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::dilate(in, kernel);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(Dilate3x3PerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int numIters = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, sz, numIters, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, type, false);
+
+ cv::Mat kernel = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(3, 3));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::dilate(in_mat1, out_mat_ocv, kernel, cv::Point(-1,-1), numIters);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::dilate3x3(in, numIters);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(SobelPerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, dtype = 0, dx = 0, dy = 0;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, dtype, dx, dy, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, dtype, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::Sobel(in_mat1, out_mat_ocv, dtype, dx, dy, kernSize);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::Sobel(in, dtype, dx, dy, kernSize);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(CannyPerfTest, TestPerformance)
+{
+ compare_f cmpF;
+ MatType type;
+ int apSize = 0;
+ double thrLow = 0.0, thrUp = 0.0;
+ cv::Size sz;
+ bool l2gr = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, sz, thrLow, thrUp, apSize, l2gr, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, CV_8UC1, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::Canny(in_mat1, out_mat_ocv, thrLow, thrUp, apSize, l2gr);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::Canny(in, thrLow, thrUp, apSize, l2gr);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(EqHistPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC1, sz, CV_8UC1, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::equalizeHist(in_mat1, out_mat_ocv);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::equalizeHist(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(RGB2GrayPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC3, sz, CV_8UC1, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_RGB2GRAY);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::RGB2Gray(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(BGR2GrayPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC3, sz, CV_8UC1, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_BGR2GRAY);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::BGR2Gray(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(RGB2YUVPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC3, sz, CV_8UC3, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_RGB2YUV);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::RGB2YUV(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(YUV2RGBPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC3, sz, CV_8UC3, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_YUV2RGB);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::YUV2RGB(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(RGB2LabPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC3, sz, CV_8UC3, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_RGB2Lab);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::RGB2Lab(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(BGR2LUVPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC3, sz, CV_8UC3, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_BGR2Luv);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::BGR2LUV(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(LUV2BGRPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC3, sz, CV_8UC3, false);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_Luv2BGR);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::LUV2BGR(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+
+ SANITY_CHECK_NOTHING();
+
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(BGR2YUVPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC3, sz, CV_8UC3, false);
+
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_BGR2YUV);
+
+ cv::GMat in;
+ auto out = cv::gapi::BGR2YUV(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi);
+ }
+
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+PERF_TEST_P_(YUV2BGRPerfTest, TestPerformance)
+{
+ compare_f cmpF = get<0>(GetParam());
+ Size sz = get<1>(GetParam());
+ cv::GCompileArgs compile_args = get<2>(GetParam());
+
+ initMatsRandN(CV_8UC3, sz, CV_8UC3, false);
+
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_YUV2BGR);
+
+ cv::GMat in;
+ auto out = cv::gapi::YUV2BGR(in);
+ cv::GComputation c(in, out);
+
+ // Warm-up graph engine:
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ TEST_CYCLE()
+ {
+ c.apply(in_mat1, out_mat_gapi);
+ }
+
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+
+ SANITY_CHECK_NOTHING();
+}
+
+//------------------------------------------------------------------------------
+
+}
+#endif //OPENCV_GAPI_IMGPROC_PERF_TESTS_INL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_core_perf_tests_cpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_core_perf_tests_cpu.cpp
new file mode 100644
index 000000000..6957401ad
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_core_perf_tests_cpu.cpp
@@ -0,0 +1,286 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+#include "../common/gapi_core_perf_tests.hpp"
+#include "opencv2/gapi/cpu/core.hpp"
+
+#define CORE_CPU cv::gapi::core::cpu::kernels()
+
+namespace opencv_test
+{
+
+
+INSTANTIATE_TEST_CASE_P(AddPerfTestCPU, AddPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(AddCPerfTestCPU, AddCPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SubPerfTestCPU, SubPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SubCPerfTestCPU, SubCPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SubRCPerfTestCPU, SubRCPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MulPerfTestCPU, MulPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MulDoublePerfTestCPU, MulDoublePerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MulCPerfTestCPU, MulCPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(DivPerfTestCPU, DivPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(DivCPerfTestCPU, DivCPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(DivRCPerfTestCPU, DivRCPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MaskPerfTestCPU, MaskPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MeanPerfTestCPU, MeanPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Polar2CartPerfTestCPU, Polar2CartPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Cart2PolarPerfTestCPU, Cart2PolarPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(CmpPerfTestCPU, CmpPerfTest,
+ Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(CmpWithScalarPerfTestCPU, CmpWithScalarPerfTest,
+ Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwisePerfTestCPU, BitwisePerfTest,
+ Combine(Values(AND, OR, XOR),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotPerfTestCPU, BitwiseNotPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SelectPerfTestCPU, SelectPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MinPerfTestCPU, MinPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MaxPerfTestCPU, MaxPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffPerfTestCPU, AbsDiffPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffCPerfTestCPU, AbsDiffCPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SumPerfTestCPU, SumPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(0.0),
+ Values(cv::compile_args(CORE_CPU))));
+
+// FIXME: Comparison introduced by YL doesn't work with C3
+INSTANTIATE_TEST_CASE_P(AddWeightedPerfTestCPU, AddWeightedPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, /*CV_8UC3,*/ CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(-1, CV_8U, CV_16U, CV_32F),
+ Values(0.5000005),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(NormPerfTestCPU, NormPerfTest,
+ Combine(Values(NORM_INF, NORM_L1, NORM_L2),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(0.0),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(IntegralPerfTestCPU, IntegralPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdPerfTestCPU, ThresholdPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::THRESH_BINARY, cv::THRESH_BINARY_INV, cv::THRESH_TRUNC, cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdPerfTestCPU, ThresholdOTPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1),
+ Values(cv::THRESH_OTSU, cv::THRESH_TRIANGLE),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(InRangePerfTestCPU, InRangePerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Split3PerfTestCPU, Split3PerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Split4PerfTestCPU, Split4PerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Merge3PerfTestCPU, Merge3PerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Merge4PerfTestCPU, Merge4PerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(RemapPerfTestCPU, RemapPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(FlipPerfTestCPU, FlipPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(0, 1, -1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(CropPerfTestCPU, CropPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatHorPerfTestCPU, ConcatHorPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatHorVecPerfTestCPU, ConcatHorVecPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatVertPerfTestCPU, ConcatVertPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatVertVecPerfTestCPU, ConcatVertVecPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(LUTPerfTestCPU, LUTPerfTest,
+ Combine(Values(CV_8UC1, CV_8UC3),
+ Values(CV_8UC1),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(LUTPerfTestCustomCPU, LUTPerfTest,
+ Combine(Values(CV_8UC3),
+ Values(CV_8UC3),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(CORE_CPU))));
+
+
+INSTANTIATE_TEST_CASE_P(ConvertToPerfTestCPU, ConvertToPerfTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
+ Values(CV_8U, CV_16U, CV_16S, CV_32F),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ResizePerfTestCPU, ResizePerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(cv::Size(64, 64),
+ cv::Size(30, 30)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ResizeFxFyPerfTestCPU, ResizeFxFyPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(0.5, 0.1),
+ Values(0.5, 0.1),
+ Values(cv::compile_args(CORE_CPU))));
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp
new file mode 100644
index 000000000..ea3d753f2
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp
@@ -0,0 +1,188 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+#include "../common/gapi_imgproc_perf_tests.hpp"
+#include "opencv2/gapi/cpu/imgproc.hpp"
+
+
+#define IMGPROC_CPU cv::gapi::imgproc::cpu::kernels()
+
+namespace opencv_test
+{
+
+INSTANTIATE_TEST_CASE_P(SepFilterPerfTestCPU_8U, SepFilterPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3),
+ Values(3),
+ Values(szVGA, sz720p, sz1080p),
+ Values(-1, CV_16S, CV_32F),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SepFilterPerfTestCPU_other, SepFilterPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3),
+ Values(szVGA, sz720p, sz1080p),
+ Values(-1, CV_32F),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Filter2DPerfTestCPU, Filter2DPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 4, 5, 7),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BoxFilterPerfTestCPU, BoxFilterPerfTest,
+ Combine(Values(AbsTolerance(0).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BlurPerfTestCPU, BlurPerfTest,
+ Combine(Values(AbsTolerance(0).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::BORDER_DEFAULT),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(GaussianBlurPerfTestCPU, GaussianBlurPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MedianBlurPerfTestCPU, MedianBlurPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ErodePerfTestCPU, ErodePerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Erode3x3PerfTestCPU, Erode3x3PerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(szVGA, sz720p, sz1080p),
+ Values(1, 2, 4),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(DilatePerfTestCPU, DilatePerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Dilate3x3PerfTestCPU, Dilate3x3PerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(szVGA, sz720p, sz1080p),
+ Values(1, 2, 4),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SobelPerfTestCPU, SobelPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(-1, CV_16S, CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SobelPerfTestCPU32F, SobelPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(CannyPerfTestCPU, CannyPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3),
+ Values(szVGA, sz720p, sz1080p),
+ Values(3.0, 120.0),
+ Values(125.0, 240.0),
+ Values(3, 5),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(EqHistPerfTestCPU, EqHistPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2GrayPerfTestCPU, RGB2GrayPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2GrayPerfTestCPU, BGR2GrayPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2YUVPerfTestCPU, RGB2YUVPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(YUV2RGBPerfTestCPU, YUV2RGBPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2LabPerfTestCPU, RGB2LabPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2LUVPerfTestCPU, BGR2LUVPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(LUV2BGRPerfTestCPU, LUV2BGRPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2YUVPerfTestCPU, BGR2YUVPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(YUV2BGRPerfTestCPU, YUV2BGRPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_fluid.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_fluid.cpp
new file mode 100644
index 000000000..a5d13e661
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_fluid.cpp
@@ -0,0 +1,76 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+#include "../common/gapi_imgproc_perf_tests.hpp"
+
+#define IMGPROC_FLUID cv::gapi::imgproc::fluid::kernels()
+
+namespace opencv_test
+{
+
+ INSTANTIATE_TEST_CASE_P(SobelPerfTestFluid, SobelPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1), // add CV_32FC1 when ready
+ Values(3), // add 5x5 once supported
+ Values(szVGA, sz720p, sz1080p),
+ Values(-1, CV_16S, CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+ INSTANTIATE_TEST_CASE_P(SobelPerfTestFluid32F, SobelPerfTest,
+ Combine(Values(ToleranceFilter(1e-3f, 0.0).to_compare_f()),
+ Values(CV_32FC1),
+ Values(3), // add 5x5 once supported
+ Values(szVGA, sz720p, sz1080p),
+ Values(CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+ INSTANTIATE_TEST_CASE_P(RGB2GrayPerfTestFluid, RGB2GrayPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+ INSTANTIATE_TEST_CASE_P(BGR2GrayPerfTestFluid, BGR2GrayPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+ INSTANTIATE_TEST_CASE_P(RGB2YUVPerfTestFluid, RGB2YUVPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+ INSTANTIATE_TEST_CASE_P(YUV2RGBPerfTestFluid, YUV2RGBPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+ INSTANTIATE_TEST_CASE_P(BGR2YUVPerfTestFluid, BGR2YUVPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+ INSTANTIATE_TEST_CASE_P(YUV2BGRPerfTestFluid, YUV2BGRPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+ INSTANTIATE_TEST_CASE_P(BGR2LUVPerfTestFluid, BGR2LUVPerfTest,
+ Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+ INSTANTIATE_TEST_CASE_P(RGB2LabPerfTestFluid, RGB2LabPerfTest,
+ Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_core_perf_tests_gpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_core_perf_tests_gpu.cpp
new file mode 100644
index 000000000..652cbae6b
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_core_perf_tests_gpu.cpp
@@ -0,0 +1,291 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+#include "../common/gapi_core_perf_tests.hpp"
+#include "opencv2/gapi/gpu/core.hpp"
+
+#define CORE_GPU cv::gapi::core::gpu::kernels()
+
+namespace opencv_test
+{
+
+INSTANTIATE_TEST_CASE_P(AddPerfTestGPU, AddPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(AddCPerfTestGPU, AddCPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SubPerfTestGPU, SubPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SubCPerfTestGPU, SubCPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SubRCPerfTestGPU, SubRCPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MulPerfTestGPU, MulPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MulDoublePerfTestGPU, MulDoublePerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MulCPerfTestGPU, MulCPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(DivPerfTestGPU, DivPerfTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_f()),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(DivCPerfTestGPU, DivCPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(DivRCPerfTestGPU, DivRCPerfTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_f()),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(cv::compile_args(CORE_GPU))));
+//TODO: mask test doesn't work
+#if 0
+INSTANTIATE_TEST_CASE_P(MaskPerfTestGPU, MaskPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::compile_args(CORE_GPU))));
+#endif
+
+INSTANTIATE_TEST_CASE_P(MeanPerfTestGPU, MeanPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Polar2CartPerfTestGPU, Polar2CartPerfTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_f()),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Cart2PolarPerfTestGPU, Cart2PolarPerfTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-2, 2).to_compare_f()),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(CmpPerfTestGPU, CmpPerfTest,
+ Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(CmpWithScalarPerfTestGPU, CmpWithScalarPerfTest,
+ Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwisePerfTestGPU, BitwisePerfTest,
+ Combine(Values(AND, OR, XOR),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotPerfTestGPU, BitwiseNotPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SelectPerfTestGPU, SelectPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MinPerfTestGPU, MinPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MaxPerfTestGPU, MaxPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffPerfTestGPU, AbsDiffPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffCPerfTestGPU, AbsDiffCPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SumPerfTestGPU, SumPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(4.0), //TODO: too relaxed?
+ Values(cv::compile_args(CORE_GPU))));
+
+// FIXME: Comparison introduced by YL doesn't work with C3
+INSTANTIATE_TEST_CASE_P(AddWeightedPerfTestGPU, AddWeightedPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, /*CV_8UC3,*/ CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ Values(0.50005),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(NormPerfTestGPU, NormPerfTest,
+ Combine(Values(NORM_INF, NORM_L1, NORM_L2),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(4.0), //TODO: too relaxed?
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(IntegralPerfTestGPU, IntegralPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdPerfTestGPU, ThresholdPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::THRESH_BINARY, cv::THRESH_BINARY_INV, cv::THRESH_TRUNC, cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdPerfTestGPU, ThresholdOTPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1 ),
+ Values(cv::THRESH_OTSU, cv::THRESH_TRIANGLE),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(InRangePerfTestGPU, InRangePerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Split3PerfTestGPU, Split3PerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Split4PerfTestGPU, Split4PerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Merge3PerfTestGPU, Merge3PerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Merge4PerfTestGPU, Merge4PerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(RemapPerfTestGPU, RemapPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(FlipPerfTestGPU, FlipPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(0,1,-1),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(CropPerfTestGPU, CropPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatHorPerfTestGPU, ConcatHorPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatVertPerfTestGPU, ConcatVertPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+
+//TODO: fix this backend to allow ConcatVertVec ConcatHorVec
+#if 0
+INSTANTIATE_TEST_CASE_P(ConcatHorVecPerfTestGPU, ConcatHorVecPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::compile_args(CORE_GPU))));
+
+
+INSTANTIATE_TEST_CASE_P(ConcatVertVecPerfTestGPU, ConcatVertVecPerfTest,
+ Combine(Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::compile_args(CORE_GPU))));
+#endif
+
+INSTANTIATE_TEST_CASE_P(LUTPerfTestGPU, LUTPerfTest,
+ Combine(Values(CV_8UC1, CV_8UC3),
+ Values(CV_8UC1),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(LUTPerfTestCustomGPU, LUTPerfTest,
+ Combine(Values(CV_8UC3),
+ Values(CV_8UC3),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::compile_args(CORE_GPU))));
+
+
+INSTANTIATE_TEST_CASE_P(ConvertToPerfTestGPU, ConvertToPerfTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
+ Values(CV_8U, CV_16U, CV_16S, CV_32F),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ResizePerfTestGPU, ResizePerfTest,
+ Combine(Values(AbsSimilarPoints(2, 0.05).to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(cv::Size(64,64),
+ cv::Size(30,30)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ResizeFxFyPerfTestGPU, ResizeFxFyPerfTest,
+ Combine(Values(AbsSimilarPoints(2, 0.05).to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values( szSmall128, szVGA, sz720p, sz1080p ),
+ Values(0.5, 0.1),
+ Values(0.5, 0.1),
+ Values(cv::compile_args(CORE_GPU))));
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_imgproc_perf_tests_gpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_imgproc_perf_tests_gpu.cpp
new file mode 100644
index 000000000..14ef60606
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/gpu/gapi_imgproc_perf_tests_gpu.cpp
@@ -0,0 +1,180 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../perf_precomp.hpp"
+#include "../common/gapi_imgproc_perf_tests.hpp"
+#include "opencv2/gapi/gpu/imgproc.hpp"
+
+#define IMGPROC_GPU cv::gapi::imgproc::gpu::kernels()
+
+namespace opencv_test
+{
+
+
+INSTANTIATE_TEST_CASE_P(SepFilterPerfTestGPU_8U, SepFilterPerfTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3),
+ Values(3),
+ Values(szVGA, sz720p, sz1080p),
+ Values(-1, CV_16S, CV_32F),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SepFilterPerfTestGPU_other, SepFilterPerfTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3),
+ Values(szVGA, sz720p, sz1080p),
+ Values(-1, CV_32F),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+
+
+INSTANTIATE_TEST_CASE_P(Filter2DPerfTestGPU, Filter2DPerfTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 4, 5, 7),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BoxFilterPerfTestGPU, BoxFilterPerfTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(/*CV_8UC1,*/ CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3,5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+ Values(cv::compile_args(IMGPROC_GPU)))); //TODO: 8UC1 doesn't work
+
+INSTANTIATE_TEST_CASE_P(BlurPerfTestGPU, BlurPerfTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::BORDER_DEFAULT),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(GaussianBlurPerfTestGPU, GaussianBlurPerfTest,
+ Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()), //TODO: too relaxed?
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MedianBlurPerfTestGPU, MedianBlurPerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ErodePerfTestGPU, ErodePerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Erode3x3PerfTestGPU, Erode3x3PerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(szVGA, sz720p, sz1080p),
+ Values(1,2,4),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(DilatePerfTestGPU, DilatePerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Dilate3x3PerfTestGPU, Dilate3x3PerfTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(szVGA, sz720p, sz1080p),
+ Values(1,2,4),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SobelPerfTestGPU, SobelPerfTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1/*, CV_32FC1*/), //TODO: CV_32FC1 fails accuracy
+ Values(3, 5),
+ Values(szVGA, sz720p, sz1080p),
+ Values(-1, CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(CannyPerfTestGPU, CannyPerfTest,
+ Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3),
+ Values(szVGA, sz720p, sz1080p),
+ Values(3.0, 120.0),
+ Values(125.0, 240.0),
+ Values(3, 5),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(EqHistPerfTestGPU, EqHistPerfTest,
+ Combine(Values(AbsExact().to_compare_f()), // FIXIT unrealiable check
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2GrayPerfTestGPU, RGB2GrayPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2GrayPerfTestGPU, BGR2GrayPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2YUVPerfTestGPU, RGB2YUVPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(YUV2RGBPerfTestGPU, YUV2RGBPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2LabPerfTestGPU, RGB2LabPerfTest,
+ Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2LUVPerfTestGPU, BGR2LUVPerfTest,
+ Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(LUV2BGRPerfTestGPU, LUV2BGRPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2YUVPerfTestGPU, BGR2YUVPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(YUV2BGRPerfTestGPU, YUV2BGRPerfTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(szVGA, sz720p, sz1080p),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/internal/gapi_compiler_perf_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/internal/gapi_compiler_perf_tests.cpp
new file mode 100644
index 000000000..48786b6a9
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/internal/gapi_compiler_perf_tests.cpp
@@ -0,0 +1,45 @@
+// 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) 2018 Intel Corporation
+
+
+#include "perf_precomp.hpp"
+#include "../../test/common/gapi_tests_common.hpp"
+
+namespace opencv_test
+{
+using namespace perf;
+
+class CompilerPerfTest : public TestPerfParams<tuple<cv::Size, MatType>> {};
+PERF_TEST_P_(CompilerPerfTest, TestPerformance)
+{
+ const auto params = GetParam();
+ Size sz = get<0>(params);
+ MatType type = get<1>(params);
+
+ initMatsRandU(type, sz, type, false);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto splitted = cv::gapi::split3(in);
+ auto add1 = cv::gapi::addC({1}, std::get<0>(splitted));
+ auto add2 = cv::gapi::addC({2}, std::get<1>(splitted));
+ auto add3 = cv::gapi::addC({3}, std::get<2>(splitted));
+ auto out = cv::gapi::merge3(add1, add2, add3);
+
+ TEST_CYCLE()
+ {
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, cv::compile_args(cv::gapi::core::fluid::kernels()));
+ }
+
+ SANITY_CHECK_NOTHING();
+}
+
+INSTANTIATE_TEST_CASE_P(CompilerPerfTest, CompilerPerfTest,
+ Combine(Values(szSmall128, szVGA, sz720p, sz1080p),
+ Values(CV_8UC3)));
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/perf_main.cpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/perf_main.cpp
new file mode 100644
index 000000000..8d6d77edc
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/perf_main.cpp
@@ -0,0 +1,11 @@
+// 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) 2018 Intel Corporation
+
+
+#include "perf_precomp.hpp"
+//#include "../test/test_precomp.hpp"
+
+CV_PERF_TEST_MAIN(gapi)
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/perf/perf_precomp.hpp b/inference-engine/thirdparty/fluid/modules/gapi/perf/perf_precomp.hpp
new file mode 100644
index 000000000..abd7cbe66
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/perf/perf_precomp.hpp
@@ -0,0 +1,25 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef __OPENCV_GAPI_PERF_PRECOMP_HPP__
+#define __OPENCV_GAPI_PERF_PRECOMP_HPP__
+
+#include <cstdint>
+#include <vector>
+
+#include "opencv2/ts.hpp"
+#include "opencv2/gapi.hpp"
+#include "opencv2/gapi/imgproc.hpp"
+#include "opencv2/gapi/core.hpp"
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+#include "opencv2/gapi/gpu/ggpukernel.hpp"
+#include "opencv2/gapi/operators.hpp"
+
+#include "opencv2/gapi/fluid/core.hpp"
+#include "opencv2/gapi/fluid/imgproc.hpp"
+
+#endif // __OPENCV_GAPI_PERF_PRECOMP_HPP__
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/samples/api_example.cpp b/inference-engine/thirdparty/fluid/modules/gapi/samples/api_example.cpp
new file mode 100644
index 000000000..a731000f4
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/samples/api_example.cpp
@@ -0,0 +1,34 @@
+#include <opencv2/videoio.hpp>
+#include <opencv2/highgui.hpp>
+#include <opencv2/gapi.hpp>
+#include <opencv2/gapi/core.hpp>
+#include <opencv2/gapi/imgproc.hpp>
+
+int main(int argc, char *argv[])
+{
+ cv::VideoCapture cap;
+ if (argc > 1) cap.open(argv[1]);
+ else cap.open(0);
+ CV_Assert(cap.isOpened());
+
+ cv::GMat in;
+ cv::GMat vga = cv::gapi::resize(in, cv::Size(), 0.5, 0.5);
+ cv::GMat gray = cv::gapi::BGR2Gray(vga);
+ cv::GMat blurred = cv::gapi::blur(gray, cv::Size(5,5));
+ cv::GMat edges = cv::gapi::Canny(blurred, 32, 128, 3);
+ cv::GMat b,g,r;
+ std::tie(b,g,r) = cv::gapi::split3(vga);
+ cv::GMat out = cv::gapi::merge3(b, g | edges, r);
+ cv::GComputation ac(in, out);
+
+ cv::Mat input_frame;
+ cv::Mat output_frame;
+ CV_Assert(cap.read(input_frame));
+ do
+ {
+ ac.apply(input_frame, output_frame);
+ cv::imshow("output", output_frame);
+ } while (cap.read(input_frame) && cv::waitKey(30) < 0);
+
+ return 0;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/samples/api_ref_snippets.cpp b/inference-engine/thirdparty/fluid/modules/gapi/samples/api_ref_snippets.cpp
new file mode 100644
index 000000000..5e8859da1
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/samples/api_ref_snippets.cpp
@@ -0,0 +1,82 @@
+#include <opencv2/videoio.hpp>
+#include <opencv2/highgui.hpp>
+#include <opencv2/gapi.hpp>
+#include <opencv2/gapi/core.hpp>
+#include <opencv2/gapi/imgproc.hpp>
+
+#include <opencv2/gapi/cpu/gcpukernel.hpp>
+
+#include <opencv2/gapi/fluid/core.hpp>
+#include <opencv2/gapi/fluid/imgproc.hpp>
+
+G_TYPED_KERNEL(IAdd, <cv::GMat(cv::GMat)>, "test.custom.add") {
+ static cv::GMatDesc outMeta(const cv::GMatDesc &in) { return in; }
+};
+G_TYPED_KERNEL(IFilter2D, <cv::GMat(cv::GMat)>, "test.custom.filter2d") {
+ static cv::GMatDesc outMeta(const cv::GMatDesc &in) { return in; }
+};
+G_TYPED_KERNEL(IRGB2YUV, <cv::GMat(cv::GMat)>, "test.custom.add") {
+ static cv::GMatDesc outMeta(const cv::GMatDesc &in) { return in; }
+};
+GAPI_OCV_KERNEL(CustomAdd, IAdd) { static void run(cv::Mat, cv::Mat &) {} };
+GAPI_OCV_KERNEL(CustomFilter2D, IFilter2D) { static void run(cv::Mat, cv::Mat &) {} };
+GAPI_OCV_KERNEL(CustomRGB2YUV, IRGB2YUV) { static void run(cv::Mat, cv::Mat &) {} };
+
+int main(int argc, char *argv[])
+{
+ if (argc < 3)
+ return -1;
+
+ cv::Mat input = cv::imread(argv[1]);
+ cv::Mat output;
+
+ {
+ //! [graph_def]
+ cv::GMat in;
+ cv::GMat gx = cv::gapi::Sobel(in, CV_32F, 1, 0);
+ cv::GMat gy = cv::gapi::Sobel(in, CV_32F, 0, 1);
+ cv::GMat g = cv::gapi::sqrt(cv::gapi::mul(gx, gx) + cv::gapi::mul(gy, gy));
+ cv::GMat out = cv::gapi::convertTo(g, CV_8U);
+ //! [graph_def]
+
+ //! [graph_decl_apply]
+ //! [graph_cap_full]
+ cv::GComputation sobelEdge(cv::GIn(in), cv::GOut(out));
+ //! [graph_cap_full]
+ sobelEdge.apply(input, output);
+ //! [graph_decl_apply]
+
+ //! [apply_with_param]
+ cv::gapi::GKernelPackage kernels = cv::gapi::combine
+ (cv::gapi::core::fluid::kernels(),
+ cv::gapi::imgproc::fluid::kernels(),
+ cv::unite_policy::KEEP);
+ sobelEdge.apply(input, output, cv::compile_args(kernels));
+ //! [apply_with_param]
+
+ //! [graph_cap_sub]
+ cv::GComputation sobelEdgeSub(cv::GIn(gx, gy), cv::GOut(out));
+ //! [graph_cap_sub]
+ }
+ //! [graph_gen]
+ cv::GComputation sobelEdgeGen([](){
+ cv::GMat in;
+ cv::GMat gx = cv::gapi::Sobel(in, CV_32F, 1, 0);
+ cv::GMat gy = cv::gapi::Sobel(in, CV_32F, 0, 1);
+ cv::GMat g = cv::gapi::sqrt(cv::gapi::mul(gx, gx) + cv::gapi::mul(gy, gy));
+ cv::GMat out = cv::gapi::convertTo(g, CV_8U);
+ return cv::GComputation(in, out);
+ });
+ //! [graph_gen]
+
+ cv::imwrite(argv[2], output);
+
+ //! [kernels_snippet]
+ cv::gapi::GKernelPackage pkg = cv::gapi::kernels
+ < CustomAdd
+ , CustomFilter2D
+ , CustomRGB2YUV
+ >();
+ //! [kernels_snippet]
+ return 0;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/samples/kernel_api_snippets.cpp b/inference-engine/thirdparty/fluid/modules/gapi/samples/kernel_api_snippets.cpp
new file mode 100644
index 000000000..a30161d27
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/samples/kernel_api_snippets.cpp
@@ -0,0 +1,157 @@
+// [filter2d_api]
+#include <opencv2/gapi.hpp>
+
+G_TYPED_KERNEL(GFilter2D,
+ <cv::GMat(cv::GMat,int,cv::Mat,cv::Point,double,int,cv::Scalar)>,
+ "org.opencv.imgproc.filters.filter2D")
+{
+ static cv::GMatDesc // outMeta's return value type
+ outMeta(cv::GMatDesc in , // descriptor of input GMat
+ int ddepth , // depth parameter
+ cv::Mat /* coeffs */, // (unused)
+ cv::Point /* anchor */, // (unused)
+ double /* scale */, // (unused)
+ int /* border */, // (unused)
+ cv::Scalar /* bvalue */ ) // (unused)
+ {
+ return in.withDepth(ddepth);
+ }
+};
+// [filter2d_api]
+
+cv::GMat filter2D(cv::GMat ,
+ int ,
+ cv::Mat ,
+ cv::Point ,
+ double ,
+ int ,
+ cv::Scalar);
+
+// [filter2d_wrap]
+cv::GMat filter2D(cv::GMat in,
+ int ddepth,
+ cv::Mat k,
+ cv::Point anchor = cv::Point(-1,-1),
+ double scale = 0.,
+ int border = cv::BORDER_DEFAULT,
+ cv::Scalar bval = cv::Scalar(0))
+{
+ return GFilter2D::on(in, ddepth, k, anchor, scale, border, bval);
+}
+// [filter2d_wrap]
+
+// [compound]
+#include <opencv2/gapi/gcompoundkernel.hpp> // GAPI_COMPOUND_KERNEL()
+
+using PointArray2f = cv::GArray<cv::Point2f>;
+
+G_TYPED_KERNEL(HarrisCorners,
+ <PointArray2f(cv::GMat,int,double,double,int,double)>,
+ "org.opencv.imgproc.harris_corner")
+{
+ static cv::GArrayDesc outMeta(const cv::GMatDesc &,
+ int,
+ double,
+ double,
+ int,
+ double)
+ {
+ // No special metadata for arrays in G-API (yet)
+ return cv::empty_array_desc();
+ }
+};
+
+// Define Fluid-backend-local kernels which form GoodFeatures
+G_TYPED_KERNEL(HarrisResponse,
+ <cv::GMat(cv::GMat,double,int,double)>,
+ "org.opencv.fluid.harris_response")
+{
+ static cv::GMatDesc outMeta(const cv::GMatDesc &in,
+ double,
+ int,
+ double)
+ {
+ return in.withType(CV_32F, 1);
+ }
+};
+
+G_TYPED_KERNEL(ArrayNMS,
+ <PointArray2f(cv::GMat,int,double)>,
+ "org.opencv.cpu.nms_array")
+{
+ static cv::GArrayDesc outMeta(const cv::GMatDesc &,
+ int,
+ double)
+ {
+ return cv::empty_array_desc();
+ }
+};
+
+GAPI_COMPOUND_KERNEL(GFluidHarrisCorners, HarrisCorners)
+{
+ static PointArray2f
+ expand(cv::GMat in,
+ int maxCorners,
+ double quality,
+ double minDist,
+ int blockSize,
+ double k)
+ {
+ cv::GMat response = HarrisResponse::on(in, quality, blockSize, k);
+ return ArrayNMS::on(response, maxCorners, minDist);
+ }
+};
+
+// Then implement HarrisResponse as Fluid kernel and NMSresponse
+// as a generic (OpenCV) kernel
+// [compound]
+
+// [filter2d_ocv]
+#include <opencv2/gapi/cpu/gcpukernel.hpp> // GAPI_OCV_KERNEL()
+#include <opencv2/imgproc.hpp> // cv::filter2D()
+
+GAPI_OCV_KERNEL(GCPUFilter2D, GFilter2D)
+{
+ static void
+ run(const cv::Mat &in, // in - derived from GMat
+ const int ddepth, // opaque (passed as-is)
+ const cv::Mat &k, // opaque (passed as-is)
+ const cv::Point &anchor, // opaque (passed as-is)
+ const double delta, // opaque (passed as-is)
+ const int border, // opaque (passed as-is)
+ const cv::Scalar &, // opaque (passed as-is)
+ cv::Mat &out) // out - derived from GMat (retval)
+ {
+ cv::filter2D(in, out, ddepth, k, anchor, delta, border);
+ }
+};
+// [filter2d_ocv]
+
+int main(int, char *[])
+{
+ std::cout << "This sample is non-complete. It is used as code snippents in documentation." << std::endl;
+
+cv::Mat conv_kernel_mat;
+
+{
+// [filter2d_on]
+cv::GMat in;
+cv::GMat out = GFilter2D::on(/* GMat */ in,
+ /* int */ -1,
+ /* Mat */ conv_kernel_mat,
+ /* Point */ cv::Point(-1,-1),
+ /* double */ 0.,
+ /* int */ cv::BORDER_DEFAULT,
+ /* Scalar */ cv::Scalar(0));
+// [filter2d_on]
+}
+
+{
+// [filter2d_wrap_call]
+cv::GMat in;
+cv::GMat out = filter2D(in, -1, conv_kernel_mat);
+// [filter2d_wrap_call]
+}
+
+return 0;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/README.md b/inference-engine/thirdparty/fluid/modules/gapi/src/api/README.md
new file mode 100644
index 000000000..970f730ec
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/README.md
@@ -0,0 +1 @@
+This directory contains implementation of G-API frontend (public API classes). \ No newline at end of file
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gapi_priv.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gapi_priv.cpp
new file mode 100644
index 000000000..744db1671
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gapi_priv.cpp
@@ -0,0 +1,44 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+#include <ade/util/assert.hpp>
+
+#include "api/gapi_priv.hpp"
+#include "api/gnode_priv.hpp"
+
+cv::GOrigin::GOrigin(GShape s,
+ const cv::GNode& n,
+ std::size_t p,
+ const cv::gimpl::HostCtor c)
+ : shape(s), node(n), port(p), ctor(c)
+{
+}
+
+cv::GOrigin::GOrigin(GShape s, cv::gimpl::ConstVal v)
+ : shape(s), node(cv::GNode::Const()), value(v), port(INVALID_PORT)
+{
+}
+
+bool cv::detail::GOriginCmp::operator() (const cv::GOrigin &lhs,
+ const cv::GOrigin &rhs) const
+{
+ const GNode::Priv* lhs_p = &lhs.node.priv();
+ const GNode::Priv* rhs_p = &rhs.node.priv();
+ if (lhs_p == rhs_p)
+ {
+ if (lhs.port == rhs.port)
+ {
+ // A data Origin is uniquely identified by {node/port} pair.
+ // The situation when there're two Origins with same {node/port}s
+ // but with different shapes (data formats) is illegal!
+ GAPI_Assert(lhs.shape == rhs.shape);
+ }
+ return lhs.port < rhs.port;
+ }
+ else return lhs_p < rhs_p;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gapi_priv.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gapi_priv.hpp
new file mode 100644
index 000000000..edab0a08b
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gapi_priv.hpp
@@ -0,0 +1,77 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_PRIV_HPP
+#define OPENCV_GAPI_PRIV_HPP
+
+#include <set> // set
+#include <map> // map
+#include <limits>
+
+#include "opencv2/gapi/util/variant.hpp" // variant
+#include "opencv2/gapi/garray.hpp" // ConstructVec
+#include "opencv2/gapi/gscalar.hpp"
+#include "opencv2/gapi/gcommon.hpp"
+
+#include "opencv2/gapi/opencv_includes.hpp"
+
+#include "api/gnode.hpp"
+
+namespace cv
+{
+
+namespace gimpl
+{
+ // Union type for various user-defined type constructors (GArray<T>, etc)
+ // FIXME: Replace construct-only API with a more generic one
+ // (probably with bits of introspection)
+ // Not required for non-user-defined types (GMat, GScalar, etc)
+ using HostCtor = util::variant
+ < util::monostate
+ , detail::ConstructVec
+ >;
+
+ using ConstVal = util::variant
+ < util::monostate
+ , cv::gapi::own::Scalar
+ >;
+}
+
+// TODO namespace gimpl?
+
+struct GOrigin
+{
+ static constexpr const std::size_t INVALID_PORT = std::numeric_limits<std::size_t>::max();
+
+ GOrigin(GShape s,
+ const GNode& n,
+ std::size_t p = INVALID_PORT,
+ const gimpl::HostCtor h = {});
+ GOrigin(GShape s, gimpl::ConstVal value);
+
+ const GShape shape; // Shape of a produced object
+ const GNode node; // a GNode which produces an object
+ const gimpl::ConstVal value; // Node can have initial constant value, now only scalar is supported
+ const std::size_t port; // GNode's output number; FIXME: "= max_size" in C++14
+ gimpl::HostCtor ctor; // FIXME: replace with an interface?
+};
+
+namespace detail
+{
+ struct GOriginCmp
+ {
+ bool operator() (const GOrigin &lhs, const GOrigin &rhs) const;
+ };
+} // namespace cv::details
+
+// TODO introduce a hash on GOrigin and define this via unordered_ ?
+using GOriginSet = std::set<GOrigin, detail::GOriginCmp>;
+template<typename T> using GOriginMap = std::map<GOrigin, T, detail::GOriginCmp>;
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_PRIV_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/garray.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/garray.cpp
new file mode 100644
index 000000000..0fd19a7e6
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/garray.cpp
@@ -0,0 +1,45 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+#include "opencv2/gapi/garray.hpp"
+#include "api/gapi_priv.hpp" // GOrigin
+
+// cv::detail::GArrayU public implementation ///////////////////////////////////
+cv::detail::GArrayU::GArrayU()
+ : m_priv(new GOrigin(GShape::GARRAY, cv::GNode::Param()))
+{
+}
+
+cv::detail::GArrayU::GArrayU(const GNode &n, std::size_t out)
+ : m_priv(new GOrigin(GShape::GARRAY, n, out))
+{
+}
+
+cv::GOrigin& cv::detail::GArrayU::priv()
+{
+ return *m_priv;
+}
+
+const cv::GOrigin& cv::detail::GArrayU::priv() const
+{
+ return *m_priv;
+}
+
+void cv::detail::GArrayU::setConstructFcn(ConstructVec &&cv)
+{
+ m_priv->ctor = std::move(cv);
+}
+
+namespace cv {
+std::ostream& operator<<(std::ostream& os, const cv::GArrayDesc &)
+{
+ // FIXME: add type information here
+ os << "(array)";
+ return os;
+}
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gbackend.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gbackend.cpp
new file mode 100644
index 000000000..8144d21d4
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gbackend.cpp
@@ -0,0 +1,353 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+#include <memory> // unique_ptr
+
+#include "opencv2/gapi/gkernel.hpp"
+#include "opencv2/gapi/own/convert.hpp"
+
+#include "api/gbackend_priv.hpp"
+#include "backends/common/gbackend.hpp"
+#include "compiler/gobjref.hpp"
+#include "compiler/gislandmodel.hpp"
+
+// GBackend private implementation /////////////////////////////////////////////
+void cv::gapi::GBackend::Priv::unpackKernel(ade::Graph & /*graph */ ,
+ const ade::NodeHandle & /*op_node*/ ,
+ const GKernelImpl & /*impl */ )
+{
+ // Default implementation is still there as Priv
+ // is instantiated by some tests.
+ // Priv is even instantiated as a mock object in a number of tests
+ // as a backend and this method is called for mock objects (doing nothing).
+ // FIXME: add a warning message here
+ // FIXME: Do something with this! Ideally this function should be "=0";
+}
+
+std::unique_ptr<cv::gimpl::GIslandExecutable>
+cv::gapi::GBackend::Priv::compile(const ade::Graph&,
+ const GCompileArgs&,
+ const std::vector<ade::NodeHandle> &) const
+{
+ // ...and this method is here for the same reason!
+ GAPI_Assert(false);
+ return {};
+}
+
+void cv::gapi::GBackend::Priv::addBackendPasses(ade::ExecutionEngineSetupContext &)
+{
+ // Do nothing by default, plugins may override this to
+ // add custom (backend-specific) graph transformations
+}
+
+// GBackend public implementation //////////////////////////////////////////////
+cv::gapi::GBackend::GBackend()
+{
+}
+
+cv::gapi::GBackend::GBackend(std::shared_ptr<cv::gapi::GBackend::Priv> &&p)
+ : m_priv(std::move(p))
+{
+}
+
+cv::gapi::GBackend::Priv& cv::gapi::GBackend::priv()
+{
+ return *m_priv;
+}
+
+const cv::gapi::GBackend::Priv& cv::gapi::GBackend::priv() const
+{
+ return *m_priv;
+}
+
+std::size_t cv::gapi::GBackend::hash() const
+{
+ return std::hash<const cv::gapi::GBackend::Priv*>{}(m_priv.get());
+}
+
+bool cv::gapi::GBackend::operator== (const cv::gapi::GBackend &rhs) const
+{
+ return m_priv == rhs.m_priv;
+}
+
+// Abstract Host-side data manipulation ////////////////////////////////////////
+// Reused between CPU backend and more generic GExecutor
+namespace cv {
+namespace gimpl {
+namespace magazine {
+
+// FIXME implement the below functions with visit()?
+
+void bindInArg(Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat)
+{
+ switch (rc.shape)
+ {
+ case GShape::GMAT:
+ {
+ switch (arg.index())
+ {
+ case GRunArg::index_of<cv::gapi::own::Mat>() :
+ if (is_umat)
+ {
+#if !defined(GAPI_STANDALONE)
+ auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
+ mag_umat = to_ocv(util::get<cv::gapi::own::Mat>(arg)).getUMat(ACCESS_READ);
+#else
+ util::throw_error(std::logic_error("UMat is not supported in stadnalone build"));
+#endif // !defined(GAPI_STANDALONE)
+ }
+ else
+ {
+ auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
+ mag_mat = util::get<cv::gapi::own::Mat>(arg);
+ }
+ break;
+#if !defined(GAPI_STANDALONE)
+ case GRunArg::index_of<cv::Mat>() :
+ if (is_umat)
+ {
+ auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
+ mag_umat = (util::get<cv::UMat>(arg));
+ }
+ else
+ {
+ auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
+ mag_mat = to_own(util::get<cv::Mat>(arg));
+ }
+ break;
+#endif // !defined(GAPI_STANDALONE)
+ default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
+ }
+ break;
+ }
+
+
+ case GShape::GSCALAR:
+ {
+ auto& mag_scalar = mag.template slot<cv::gapi::own::Scalar>()[rc.id];
+ switch (arg.index())
+ {
+ case GRunArg::index_of<cv::gapi::own::Scalar>() : mag_scalar = util::get<cv::gapi::own::Scalar>(arg); break;
+#if !defined(GAPI_STANDALONE)
+ case GRunArg::index_of<cv::Scalar>() : mag_scalar = to_own(util::get<cv::Scalar>(arg)); break;
+#endif // !defined(GAPI_STANDALONE)
+ default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
+ }
+ break;
+ }
+
+ case GShape::GARRAY:
+ mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
+ break;
+
+ default:
+ util::throw_error(std::logic_error("Unsupported GShape type"));
+ }
+}
+
+void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat)
+{
+ switch (rc.shape)
+ {
+ case GShape::GMAT:
+ {
+ switch (arg.index())
+ {
+ case GRunArgP::index_of<cv::gapi::own::Mat*>() :
+ if (is_umat)
+ {
+#if !defined(GAPI_STANDALONE)
+ auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
+ mag_umat = to_ocv(*(util::get<cv::gapi::own::Mat*>(arg))).getUMat(ACCESS_RW);
+#else
+ util::throw_error(std::logic_error("UMat is not supported in standalone build"));
+#endif // !defined(GAPI_STANDALONE)
+ }
+ else
+ {
+ auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
+ mag_mat = *util::get<cv::gapi::own::Mat*>(arg);
+ }
+ break;
+#if !defined(GAPI_STANDALONE)
+ case GRunArgP::index_of<cv::Mat*>() :
+ if (is_umat)
+ {
+ auto& mag_umat = mag.template slot<cv::UMat>()[rc.id];
+ mag_umat = (*util::get<cv::UMat*>(arg));
+ }
+ else
+ {
+ auto& mag_mat = mag.template slot<cv::gapi::own::Mat>()[rc.id];
+ mag_mat = to_own(*util::get<cv::Mat*>(arg));
+ }
+ break;
+#endif // !defined(GAPI_STANDALONE)
+ default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
+ }
+ break;
+ }
+
+ case GShape::GSCALAR:
+ {
+ auto& mag_scalar = mag.template slot<cv::gapi::own::Scalar>()[rc.id];
+ switch (arg.index())
+ {
+ case GRunArgP::index_of<cv::gapi::own::Scalar*>() : mag_scalar = *util::get<cv::gapi::own::Scalar*>(arg); break;
+#if !defined(GAPI_STANDALONE)
+ case GRunArgP::index_of<cv::Scalar*>() : mag_scalar = to_own(*util::get<cv::Scalar*>(arg)); break;
+#endif // !defined(GAPI_STANDALONE)
+ default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
+ }
+ break;
+ }
+ case GShape::GARRAY:
+ mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
+ break;
+
+ default:
+ util::throw_error(std::logic_error("Unsupported GShape type"));
+ break;
+ }
+}
+
+void resetInternalData(Mag& mag, const Data &d)
+{
+ if (d.storage != Data::Storage::INTERNAL)
+ return;
+
+ switch (d.shape)
+ {
+ case GShape::GARRAY:
+ util::get<cv::detail::ConstructVec>(d.ctor)
+ (mag.template slot<cv::detail::VectorRef>()[d.rc]);
+ break;
+
+ case GShape::GSCALAR:
+ mag.template slot<cv::gapi::own::Scalar>()[d.rc] = cv::gapi::own::Scalar();
+ break;
+
+ case GShape::GMAT:
+ // Do nothign here - FIXME unify with initInternalData?
+ break;
+
+ default:
+ util::throw_error(std::logic_error("Unsupported GShape type"));
+ break;
+ }
+}
+
+cv::GRunArg getArg(const Mag& mag, const RcDesc &ref)
+{
+ // Wrap associated CPU object (either host or an internal one)
+ switch (ref.shape)
+ {
+ case GShape::GMAT: return GRunArg(mag.template slot<cv::gapi::own::Mat>().at(ref.id));
+ case GShape::GSCALAR: return GRunArg(mag.template slot<cv::gapi::own::Scalar>().at(ref.id));
+ // Note: .at() is intentional for GArray as object MUST be already there
+ // (and constructed by either bindIn/Out or resetInternal)
+ case GShape::GARRAY: return GRunArg(mag.template slot<cv::detail::VectorRef>().at(ref.id));
+ default:
+ util::throw_error(std::logic_error("Unsupported GShape type"));
+ break;
+ }
+}
+
+cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat)
+{
+ switch (rc.shape)
+ {
+ case GShape::GMAT:
+ if (is_umat)
+ {
+#if !defined(GAPI_STANDALONE)
+ return GRunArgP(&mag.template slot<cv::UMat>()[rc.id]);
+#else
+ util::throw_error(std::logic_error("UMat is not supported in standalone build"));
+#endif // !defined(GAPI_STANDALONE)
+ }
+ else
+ return GRunArgP(&mag.template slot<cv::gapi::own::Mat>()[rc.id]);
+ case GShape::GSCALAR: return GRunArgP(&mag.template slot<cv::gapi::own::Scalar>()[rc.id]);
+ // Note: .at() is intentional for GArray as object MUST be already there
+ // (and constructer by either bindIn/Out or resetInternal)
+ case GShape::GARRAY:
+ // FIXME(DM): For some absolutely unknown to me reason, move
+ // semantics is involved here without const_cast to const (and
+ // value from map is moved into return value GRunArgP, leaving
+ // map with broken value I've spent few late Friday hours
+ // debugging this!!!1
+ return GRunArgP(const_cast<const Mag&>(mag)
+ .template slot<cv::detail::VectorRef>().at(rc.id));
+ default:
+ util::throw_error(std::logic_error("Unsupported GShape type"));
+ break;
+ }
+}
+
+void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
+{
+ switch (rc.shape)
+ {
+ case GShape::GARRAY:
+ // Do nothing - should we really do anything here?
+ break;
+
+ case GShape::GMAT:
+ {
+ //simply check that memory was not reallocated, i.e.
+ //both instances of Mat pointing to the same memory
+ uchar* out_arg_data = nullptr;
+ switch (g_arg.index())
+ {
+ case GRunArgP::index_of<cv::gapi::own::Mat*>() : out_arg_data = util::get<cv::gapi::own::Mat*>(g_arg)->data; break;
+#if !defined(GAPI_STANDALONE)
+ case GRunArgP::index_of<cv::Mat*>() : out_arg_data = util::get<cv::Mat*>(g_arg)->data; break;
+ case GRunArgP::index_of<cv::UMat*>() : out_arg_data = (util::get<cv::UMat*>(g_arg))->getMat(ACCESS_RW).data; break;
+#endif // !defined(GAPI_STANDALONE)
+ default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
+ }
+ if (is_umat)
+ {
+#if !defined(GAPI_STANDALONE)
+ auto& in_mag = mag.template slot<cv::UMat>().at(rc.id);
+ GAPI_Assert((out_arg_data == (in_mag.getMat(ACCESS_RW).data)) && " data for output parameters was reallocated ?");
+#else
+ util::throw_error(std::logic_error("UMat is not supported in standalone build"));
+#endif // !defined(GAPI_STANDALONE)
+ }
+ else
+ {
+ auto& in_mag = mag.template slot<cv::gapi::own::Mat>().at(rc.id);
+ GAPI_Assert((out_arg_data == in_mag.data) && " data for output parameters was reallocated ?");
+ }
+ break;
+ }
+
+ case GShape::GSCALAR:
+ {
+ switch (g_arg.index())
+ {
+ case GRunArgP::index_of<cv::gapi::own::Scalar*>() : *util::get<cv::gapi::own::Scalar*>(g_arg) = mag.template slot<cv::gapi::own::Scalar>().at(rc.id); break;
+#if !defined(GAPI_STANDALONE)
+ case GRunArgP::index_of<cv::Scalar*>() : *util::get<cv::Scalar*>(g_arg) = cv::gapi::own::to_ocv(mag.template slot<cv::gapi::own::Scalar>().at(rc.id)); break;
+#endif // !defined(GAPI_STANDALONE)
+ default: util::throw_error(std::logic_error("content type of the runtime argument does not match to resource description ?"));
+ }
+ break;
+ }
+
+ default:
+ util::throw_error(std::logic_error("Unsupported GShape type"));
+ break;
+ }
+}
+
+} // namespace magazine
+} // namespace gimpl
+} // namespace cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gbackend_priv.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gbackend_priv.hpp
new file mode 100644
index 000000000..1c6e29715
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gbackend_priv.hpp
@@ -0,0 +1,53 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef GAPI_API_GBACKEND_PRIV_HPP
+#define GAPI_API_GBACKEND_PRIV_HPP
+
+#include <memory>
+#include <unordered_set>
+
+#include <ade/graph.hpp>
+#include <ade/passes/pass_base.hpp> // passes::PassContext
+#include <ade/execution_engine/execution_engine.hpp> // ..SetupContext
+
+#include "opencv2/gapi/gcommon.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+
+namespace cv
+{
+namespace gimpl
+{
+ class GBackend;
+ class GIslandExecutable;
+} // namespace gimpl
+} // namespace cv
+
+// GAPI_EXPORTS is here to make tests build on Windows
+class GAPI_EXPORTS cv::gapi::GBackend::Priv
+{
+public:
+ using EPtr = std::unique_ptr<cv::gimpl::GIslandExecutable>;
+
+ virtual void unpackKernel(ade::Graph &graph,
+ const ade::NodeHandle &op_node,
+ const GKernelImpl &impl);
+
+ // FIXME: since backends are not passed to ADE anymore,
+ // there's no need in having both cv::gimpl::GBackend
+ // and cv::gapi::GBackend - these two things can be unified
+ // NOTE - nodes are guaranteed to be topologically sorted.
+ virtual EPtr compile(const ade::Graph &graph,
+ const GCompileArgs &args,
+ const std::vector<ade::NodeHandle> &nodes) const;
+
+ virtual void addBackendPasses(ade::ExecutionEngineSetupContext &);
+
+ virtual ~Priv() = default;
+};
+
+#endif // GAPI_API_GBACKEND_PRIV_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcall.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcall.cpp
new file mode 100644
index 000000000..2dd823daa
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcall.cpp
@@ -0,0 +1,65 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+#include <cassert>
+#include "opencv2/gapi/gcall.hpp"
+#include "api/gcall_priv.hpp"
+
+// GCall private implementation ////////////////////////////////////////////////
+cv::GCall::Priv::Priv(const cv::GKernel &k)
+ : m_k(k)
+{
+}
+
+// GCall public implementation /////////////////////////////////////////////////
+
+cv::GCall::GCall(const cv::GKernel &k)
+ : m_priv(new Priv(k))
+{
+ // Here we have a reference to GNode,
+ // and GNode has a reference to us. Cycle! Now see destructor.
+ m_priv->m_node = GNode::Call(*this);
+}
+
+cv::GCall::~GCall()
+{
+ // When a GCall object is destroyed (and GCall::Priv is likely still alive,
+ // as there might be other references), reset m_node to break cycle.
+ m_priv->m_node = GNode();
+}
+
+void cv::GCall::setArgs(std::vector<GArg> &&args)
+{
+ // FIXME: Check if argument number is matching kernel prototype
+ m_priv->m_args = std::move(args);
+}
+
+cv::GMat cv::GCall::yield(int output)
+{
+ return cv::GMat(m_priv->m_node, output);
+}
+
+cv::GScalar cv::GCall::yieldScalar(int output)
+{
+ return cv::GScalar(m_priv->m_node, output);
+}
+
+cv::detail::GArrayU cv::GCall::yieldArray(int output)
+{
+ return cv::detail::GArrayU(m_priv->m_node, output);
+}
+
+cv::GCall::Priv& cv::GCall::priv()
+{
+ return *m_priv;
+}
+
+const cv::GCall::Priv& cv::GCall::priv() const
+{
+ return *m_priv;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcall_priv.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcall_priv.hpp
new file mode 100644
index 000000000..ffb122ec8
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcall_priv.hpp
@@ -0,0 +1,37 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GCALL_PRIV_HPP
+#define OPENCV_GCALL_PRIV_HPP
+
+#include <vector>
+#include <unordered_map>
+
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gcall.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+
+#include "api/gnode.hpp"
+
+namespace cv {
+
+class GCall::Priv
+{
+public:
+ std::vector<GArg> m_args;
+ const GKernel m_k;
+
+ // FIXME: Document that there's no recursion here.
+ // TODO: Rename to "constructionNode" or smt to reflect its lifetime
+ GNode m_node;
+
+ explicit Priv(const GKernel &k);
+};
+
+}
+
+#endif // OPENCV_GCALL_PRIV_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation.cpp
new file mode 100644
index 000000000..ab761edf9
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation.cpp
@@ -0,0 +1,238 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+#include <algorithm> // remove_if
+#include <cctype> // isspace (non-locale version)
+#include <ade/util/algorithm.hpp>
+
+#include "logger.hpp" // GAPI_LOG
+
+#include "opencv2/gapi/gcomputation.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+
+#include "api/gcomputation_priv.hpp"
+#include "api/gcall_priv.hpp"
+#include "api/gnode_priv.hpp"
+
+#include "compiler/gmodelbuilder.hpp"
+#include "compiler/gcompiler.hpp"
+
+// cv::GComputation private implementation /////////////////////////////////////
+// <none>
+
+// cv::GComputation public implementation //////////////////////////////////////
+cv::GComputation::GComputation(const Generator& gen)
+ : m_priv(gen().m_priv)
+{
+}
+
+cv::GComputation::GComputation(GMat in, GMat out)
+ : cv::GComputation(cv::GIn(in), cv::GOut(out))
+{
+}
+
+
+cv::GComputation::GComputation(GMat in, GScalar out)
+ : cv::GComputation(cv::GIn(in), cv::GOut(out))
+{
+}
+
+cv::GComputation::GComputation(GMat in1, GMat in2, GMat out)
+ : cv::GComputation(cv::GIn(in1, in2), cv::GOut(out))
+{
+}
+
+cv::GComputation::GComputation(GMat in1, GMat in2, GScalar out)
+ : cv::GComputation(cv::GIn(in1, in2), cv::GOut(out))
+{
+}
+
+cv::GComputation::GComputation(const std::vector<GMat> &ins,
+ const std::vector<GMat> &outs)
+ : m_priv(new Priv())
+{
+ const auto wrap = [](cv::GMat m) { return GProtoArg(m); };
+ ade::util::transform(ins, std::back_inserter(m_priv->m_ins), wrap);
+ ade::util::transform(outs, std::back_inserter(m_priv->m_outs), wrap);
+}
+
+cv::GComputation::GComputation(cv::GProtoInputArgs &&ins,
+ cv::GProtoOutputArgs &&outs)
+ : m_priv(new Priv())
+{
+ m_priv->m_ins = std::move(ins.m_args);
+ m_priv->m_outs = std::move(outs.m_args);
+}
+
+cv::GCompiled cv::GComputation::compile(GMetaArgs &&metas, GCompileArgs &&args)
+{
+ // FIXME: Cache gcompiled per parameters here?
+ cv::gimpl::GCompiler comp(*this, std::move(metas), std::move(args));
+ return comp.compile();
+}
+
+// FIXME: Introduce similar query/test method for GMetaArgs as a building block
+// for functions like this?
+static bool formats_are_same(const cv::GMetaArgs& metas1, const cv::GMetaArgs& metas2)
+{
+ return std::equal(metas1.cbegin(), metas1.cend(), metas2.cbegin(),
+ [](const cv::GMetaArg& meta1, const cv::GMetaArg& meta2) {
+ if (meta1.index() == meta2.index() && meta1.index() == cv::GMetaArg::index_of<cv::GMatDesc>())
+ {
+ const auto& desc1 = cv::util::get<cv::GMatDesc>(meta1);
+ const auto& desc2 = cv::util::get<cv::GMatDesc>(meta2);
+
+ // comparison by size is omitted
+ return (desc1.chan == desc2.chan &&
+ desc1.depth == desc2.depth);
+ }
+ else
+ {
+ return meta1 == meta2;
+ }
+ });
+}
+
+void cv::GComputation::apply(GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args)
+{
+ const auto in_metas = descr_of(ins);
+ // FIXME Graph should be recompiled when GCompileArgs have changed
+ if (m_priv->m_lastMetas != in_metas)
+ {
+ if (m_priv->m_lastCompiled &&
+ m_priv->m_lastCompiled.canReshape() &&
+ formats_are_same(m_priv->m_lastMetas, in_metas))
+ {
+ m_priv->m_lastCompiled.reshape(in_metas, args);
+ }
+ else
+ {
+ // FIXME: Had to construct temporary object as compile() takes && (r-value)
+ m_priv->m_lastCompiled = compile(GMetaArgs(in_metas), std::move(args));
+ }
+ m_priv->m_lastMetas = in_metas;
+ }
+ m_priv->m_lastCompiled(std::move(ins), std::move(outs));
+}
+
+void cv::GComputation::apply(const std::vector<cv::gapi::own::Mat> &ins,
+ const std::vector<cv::gapi::own::Mat> &outs,
+ GCompileArgs &&args)
+{
+ GRunArgs call_ins;
+ GRunArgsP call_outs;
+
+ auto tmp = outs;
+ for (const cv::gapi::own::Mat &m : ins) { call_ins.emplace_back(m); }
+ for ( cv::gapi::own::Mat &m : tmp) { call_outs.emplace_back(&m); }
+
+ apply(std::move(call_ins), std::move(call_outs), std::move(args));
+}
+
+#if !defined(GAPI_STANDALONE)
+void cv::GComputation::apply(cv::Mat in, cv::Mat &out, GCompileArgs &&args)
+{
+ apply(cv::gin(in), cv::gout(out), std::move(args));
+ // FIXME: The following doesn't work!
+ // Operation result is not replicated into user's object
+ // apply({GRunArg(in)}, {GRunArg(out)});
+}
+
+void cv::GComputation::apply(cv::Mat in, cv::Scalar &out, GCompileArgs &&args)
+{
+ apply(cv::gin(in), cv::gout(out), std::move(args));
+}
+
+void cv::GComputation::apply(cv::Mat in1, cv::Mat in2, cv::Mat &out, GCompileArgs &&args)
+{
+ apply(cv::gin(in1, in2), cv::gout(out), std::move(args));
+}
+
+void cv::GComputation::apply(cv::Mat in1, cv::Mat in2, cv::Scalar &out, GCompileArgs &&args)
+{
+ apply(cv::gin(in1, in2), cv::gout(out), std::move(args));
+}
+
+void cv::GComputation::apply(const std::vector<cv::Mat> &ins,
+ const std::vector<cv::Mat> &outs,
+ GCompileArgs &&args)
+{
+ GRunArgs call_ins;
+ GRunArgsP call_outs;
+
+ // Make a temporary copy of vector outs - cv::Mats are copies anyway
+ auto tmp = outs;
+ for (const cv::Mat &m : ins) { call_ins.emplace_back(m); }
+ for ( cv::Mat &m : tmp) { call_outs.emplace_back(&m); }
+
+ apply(std::move(call_ins), std::move(call_outs), std::move(args));
+}
+#endif // !defined(GAPI_STANDALONE)
+
+cv::GComputation::Priv& cv::GComputation::priv()
+{
+ return *m_priv;
+}
+
+const cv::GComputation::Priv& cv::GComputation::priv() const
+{
+ return *m_priv;
+}
+
+// Islands /////////////////////////////////////////////////////////////////////
+
+void cv::gapi::island(const std::string &name,
+ GProtoInputArgs &&ins,
+ GProtoOutputArgs &&outs)
+{
+ {
+ // Island must have a printable name.
+ // Forbid names which contain only spaces.
+ GAPI_Assert(!name.empty());
+ const auto first_printable_it = std::find_if_not(name.begin(), name.end(), isspace);
+ const bool likely_printable = first_printable_it != name.end();
+ GAPI_Assert(likely_printable);
+ }
+ // Even if the name contains spaces, keep it unmodified as user will
+ // then use this string to assign affinity, etc.
+
+ // First, set island tags on all operations from `ins` to `outs`
+ auto island = cv::gimpl::unrollExpr(ins.m_args, outs.m_args);
+ if (island.all_ops.empty())
+ {
+ util::throw_error(std::logic_error("Operation range is empty"));
+ }
+ for (auto &op_expr_node : island.all_ops)
+ {
+ auto &op_expr_node_p = op_expr_node.priv();
+
+ GAPI_Assert(op_expr_node.shape() == GNode::NodeShape::CALL);
+ const GCall& call = op_expr_node.call();
+ const GCall::Priv& call_p = call.priv();
+
+ if (!op_expr_node_p.m_island.empty())
+ {
+ util::throw_error(std::logic_error
+ ( "Operation " + call_p.m_k.name
+ + " is already assigned to island \""
+ + op_expr_node_p.m_island + "\""));
+ }
+ else
+ {
+ op_expr_node_p.m_island = name;
+ GAPI_LOG_INFO(NULL,
+ "Assigned " << call_p.m_k.name << "_" << &call_p <<
+ " to island \"" << name << "\"");
+ }
+ }
+
+ // Note - this function only sets islands to all operations in
+ // expression tree, it is just a first step.
+ // The second step is assigning intermediate data objects to Islands,
+ // see passes::initIslands for details.
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation_priv.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation_priv.hpp
new file mode 100644
index 000000000..13d1b9afa
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gcomputation_priv.hpp
@@ -0,0 +1,29 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCOMPUTATION_PRIV_HPP
+#define OPENCV_GAPI_GCOMPUTATION_PRIV_HPP
+
+#include "opencv2/gapi.hpp"
+#include "opencv2/gapi/gcall.hpp"
+
+#include "opencv2/gapi/util/variant.hpp"
+
+namespace cv {
+
+class GComputation::Priv
+{
+public:
+ GCompiled m_lastCompiled;
+ GMetaArgs m_lastMetas; // TODO: make GCompiled remember its metas?
+ GProtoArgs m_ins;
+ GProtoArgs m_outs;
+};
+
+}
+
+#endif // OPENCV_GAPI_GCOMPUTATION_PRIV_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gkernel.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gkernel.cpp
new file mode 100644
index 000000000..f8c851abf
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gkernel.cpp
@@ -0,0 +1,147 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+#include <iostream> // cerr
+#include <functional> // hash
+#include <numeric> // accumulate
+
+#include <ade/util/algorithm.hpp>
+
+#include "logger.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+
+#include "api/gbackend_priv.hpp"
+
+// GKernelPackage public implementation ////////////////////////////////////////
+void cv::gapi::GKernelPackage::remove(const cv::gapi::GBackend& backend)
+{
+ m_backend_kernels.erase(backend);
+}
+
+bool cv::gapi::GKernelPackage::includesAPI(const std::string &id) const
+{
+ // In current form not very efficient (n * log n)
+ auto it = std::find_if(m_backend_kernels.begin(),
+ m_backend_kernels.end(),
+ [&id](const M::value_type &p) {
+ return ade::util::contains(p.second, id);
+ });
+ return (it != m_backend_kernels.end());
+}
+
+void cv::gapi::GKernelPackage::removeAPI(const std::string &id)
+{
+ for (auto &bk : m_backend_kernels)
+ bk.second.erase(id);
+}
+
+std::size_t cv::gapi::GKernelPackage::size() const
+{
+ return std::accumulate(m_backend_kernels.begin(),
+ m_backend_kernels.end(),
+ static_cast<std::size_t>(0u),
+ [](std::size_t acc, const M::value_type& v) {
+ return acc + v.second.size();
+ });
+}
+
+cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage &lhs,
+ const GKernelPackage &rhs,
+ const cv::unite_policy policy)
+{
+
+ if (policy == cv::unite_policy::REPLACE)
+ {
+ // REPLACE policy: if there is a collision, prefer RHS
+ // to LHS
+ // since RHS package has a precedense, start with its copy
+ GKernelPackage result(rhs);
+ // now iterate over LHS package and put kernel if and only
+ // if there's no such one
+ for (const auto &backend : lhs.m_backend_kernels)
+ {
+ for (const auto &kimpl : backend.second)
+ {
+ if (!result.includesAPI(kimpl.first))
+ result.m_backend_kernels[backend.first].insert(kimpl);
+ }
+ }
+ return result;
+ }
+ else if (policy == cv::unite_policy::KEEP)
+ {
+ // KEEP policy: if there is a collision, just keep two versions
+ // of a kernel
+ GKernelPackage result(lhs);
+ for (const auto &p : rhs.m_backend_kernels)
+ {
+ result.m_backend_kernels[p.first].insert(p.second.begin(),
+ p.second.end());
+ }
+ return result;
+ }
+ else GAPI_Assert(false);
+ return GKernelPackage();
+}
+
+std::pair<cv::gapi::GBackend, cv::GKernelImpl>
+cv::gapi::GKernelPackage::lookup(const std::string &id,
+ const GLookupOrder &order) const
+{
+ if (order.empty())
+ {
+ // If order is empty, return what comes first
+ auto it = std::find_if(m_backend_kernels.begin(),
+ m_backend_kernels.end(),
+ [&id](const M::value_type &p) {
+ return ade::util::contains(p.second, id);
+ });
+ if (it != m_backend_kernels.end())
+ {
+ // FIXME: Two lookups!
+ return std::make_pair(it->first, it->second.find(id)->second);
+ }
+ }
+ else
+ {
+ // There is order, so:
+ // 1. Limit search scope only to specified backends
+ // FIXME: Currently it is not configurable if search can fall-back
+ // to other backends (not listed in order) if kernel hasn't been found
+ // in the look-up list
+ // 2. Query backends in the specified order
+ for (const auto &selected_backend : order)
+ {
+ const auto kernels_it = m_backend_kernels.find(selected_backend);
+ if (kernels_it == m_backend_kernels.end())
+ {
+ GAPI_LOG_WARNING(NULL,
+ "Backend "
+ << &selected_backend.priv() // FIXME: name instead
+ << " was listed in lookup list but was not found "
+ "in the package");
+ continue;
+ }
+ if (ade::util::contains(kernels_it->second, id))
+ {
+ // FIXME: two lookups!
+ return std::make_pair(selected_backend, kernels_it->second.find(id)->second);
+ }
+ }
+ }
+
+ // If reached here, kernel was not found among selected backends.
+ util::throw_error(std::logic_error("Kernel " + id + " was not found"));
+}
+
+std::vector<cv::gapi::GBackend> cv::gapi::GKernelPackage::backends() const
+{
+ std::vector<cv::gapi::GBackend> result;
+ for (const auto &p : m_backend_kernels) result.emplace_back(p.first);
+ return result;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gmat.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gmat.cpp
new file mode 100644
index 000000000..e8c528555
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gmat.cpp
@@ -0,0 +1,78 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+#include <opencv2/gapi/opencv_includes.hpp>
+#include <opencv2/gapi/own/mat.hpp> //gapi::own::Mat
+
+#include "opencv2/gapi/gmat.hpp"
+#include "api/gapi_priv.hpp" // GOrigin
+
+// cv::GMat public implementation //////////////////////////////////////////////
+cv::GMat::GMat()
+ : m_priv(new GOrigin(GShape::GMAT, GNode::Param()))
+{
+}
+
+cv::GMat::GMat(const GNode &n, std::size_t out)
+ : m_priv(new GOrigin(GShape::GMAT, n, out))
+{
+}
+
+cv::GOrigin& cv::GMat::priv()
+{
+ return *m_priv;
+}
+
+const cv::GOrigin& cv::GMat::priv() const
+{
+ return *m_priv;
+}
+
+#if !defined(GAPI_STANDALONE)
+cv::GMatDesc cv::descr_of(const cv::Mat &mat)
+{
+ return GMatDesc{mat.depth(), mat.channels(), {mat.cols, mat.rows}};
+}
+cv::GMatDesc cv::descr_of(const cv::UMat &mat)
+{
+ return GMatDesc{ mat.depth(), mat.channels(),{ mat.cols, mat.rows } };
+}
+#endif
+
+cv::GMatDesc cv::gapi::own::descr_of(const cv::gapi::own::Mat &mat)
+{
+ return GMatDesc{mat.depth(), mat.channels(), {mat.cols, mat.rows}};
+}
+
+namespace cv {
+std::ostream& operator<<(std::ostream& os, const cv::GMatDesc &desc)
+{
+ switch (desc.depth)
+ {
+#define TT(X) case CV_##X: os << #X; break;
+ TT(8U);
+ TT(8S);
+ TT(16U);
+ TT(16S);
+ TT(32S);
+ TT(32F);
+ TT(64F);
+#undef TT
+ default:
+ os << "(user type "
+ << std::hex << desc.depth << std::dec
+ << ")";
+ break;
+ }
+
+ os << "C" << desc.chan << " ";
+ os << desc.size.width << "x" << desc.size.height;
+
+ return os;
+}
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode.cpp
new file mode 100644
index 000000000..efda5d542
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode.cpp
@@ -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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+#include <cassert>
+
+#include "api/gnode.hpp"
+#include "api/gnode_priv.hpp"
+
+// GNode private implementation
+cv::GNode::Priv::Priv()
+ : m_shape(NodeShape::EMPTY)
+{
+}
+
+cv::GNode::Priv::Priv(GCall c)
+ : m_shape(NodeShape::CALL), m_spec(c)
+{
+}
+
+cv::GNode::Priv::Priv(ParamTag)
+ : m_shape(NodeShape::PARAM)
+{
+}
+
+cv::GNode::Priv::Priv(ConstTag)
+ : m_shape(NodeShape::CONST_BOUNDED)
+{
+}
+
+// GNode public implementation
+cv::GNode::GNode()
+ : m_priv(new Priv())
+{
+}
+
+cv::GNode::GNode(const GCall &c)
+ : m_priv(new Priv(c))
+{
+}
+
+cv::GNode::GNode(ParamTag)
+ : m_priv(new Priv(Priv::ParamTag()))
+{
+}
+
+cv::GNode::GNode(ConstTag)
+ : m_priv(new Priv(Priv::ConstTag()))
+{
+}
+
+cv::GNode cv::GNode::Call(const GCall &c)
+{
+ return GNode(c);
+}
+
+cv::GNode cv::GNode::Param()
+{
+ return GNode(ParamTag());
+}
+
+cv::GNode cv::GNode::Const()
+{
+ return GNode(ConstTag());
+}
+
+cv::GNode::Priv& cv::GNode::priv()
+{
+ return *m_priv;
+}
+
+const cv::GNode::Priv& cv::GNode::priv() const
+{
+ return *m_priv;
+}
+
+const cv::GNode::NodeShape& cv::GNode::shape() const
+{
+ return m_priv->m_shape;
+}
+
+const cv::GCall& cv::GNode::call() const
+{
+ return util::get<GCall>(m_priv->m_spec);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode.hpp
new file mode 100644
index 000000000..bd6c7901e
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode.hpp
@@ -0,0 +1,58 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GNODE_HPP
+#define OPENCV_GAPI_GNODE_HPP
+
+#include <memory> // std::shared_ptr
+
+namespace cv {
+
+class GCall;
+
+// TODO Move "internal" namespace
+// TODO Expose details?
+
+// This class won't be public
+
+// data GNode = Call Operation [GNode]
+// | Const <T>
+// | Param <GMat|GParam>
+
+class GNode
+{
+public:
+ class Priv;
+
+ // Constructors
+ GNode(); // Empty (invalid) constructor
+ static GNode Call (const GCall &c); // Call constructor
+ static GNode Param(); // Param constructor
+ static GNode Const();
+
+ // Internal use only
+ Priv& priv();
+ const Priv& priv() const;
+ enum class NodeShape: unsigned int;
+
+ const NodeShape& shape() const;
+ const GCall& call() const;
+
+protected:
+ struct ParamTag {};
+ struct ConstTag {};
+
+ explicit GNode(const GCall &c);
+ explicit GNode(ParamTag unused);
+ explicit GNode(ConstTag unused);
+
+ std::shared_ptr<Priv> m_priv;
+};
+
+}
+
+#endif // OPENCV_GAPI_GNODE_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode_priv.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode_priv.hpp
new file mode 100644
index 000000000..5425471f8
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gnode_priv.hpp
@@ -0,0 +1,52 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GNODE_PRIV_HPP
+#define OPENCV_GNODE_PRIV_HPP
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+#include "opencv2/gapi/util/variant.hpp"
+
+#include "opencv2/gapi/gcall.hpp"
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+
+#include "api/gnode.hpp"
+
+namespace cv {
+
+enum class GNode::NodeShape: unsigned int
+{
+ EMPTY,
+ CALL,
+ PARAM,
+ CONST_BOUNDED
+};
+
+class GNode::Priv
+{
+public:
+ // TODO: replace with optional?
+ typedef util::variant<util::monostate, GCall> NodeSpec;
+ const NodeShape m_shape;
+ const NodeSpec m_spec;
+ std::string m_island; // user-modifiable attribute
+ struct ParamTag {};
+ struct ConstTag {};
+
+ Priv(); // Empty (invalid) constructor
+ explicit Priv(GCall c); // Call conctrustor
+ explicit Priv(ParamTag u); // Param constructor
+ explicit Priv(ConstTag u); // Param constructor
+};
+
+}
+
+#endif // OPENCV_GNODE_PRIV_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto.cpp
new file mode 100644
index 000000000..2482d628b
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto.cpp
@@ -0,0 +1,162 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <ade/util/algorithm.hpp>
+#include "opencv2/gapi/util/throw.hpp"
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gproto.hpp"
+
+#include "api/gapi_priv.hpp"
+#include "api/gproto_priv.hpp"
+
+// FIXME: it should be a visitor!
+// FIXME: Reimplement with traits?
+
+const cv::GOrigin& cv::gimpl::proto::origin_of(const cv::GProtoArg &arg)
+{
+ switch (arg.index())
+ {
+ case cv::GProtoArg::index_of<cv::GMat>():
+ return util::get<cv::GMat>(arg).priv();
+
+ case cv::GProtoArg::index_of<cv::GScalar>():
+ return util::get<cv::GScalar>(arg).priv();
+
+ case cv::GProtoArg::index_of<cv::detail::GArrayU>():
+ return util::get<cv::detail::GArrayU>(arg).priv();
+
+ default:
+ util::throw_error(std::logic_error("Unsupported GProtoArg type"));
+ }
+}
+
+const cv::GOrigin& cv::gimpl::proto::origin_of(const cv::GArg &arg)
+{
+ // Generic, but not very efficient implementation
+ // FIXME: Walking a thin line here!!! Here we rely that GArg and
+ // GProtoArg share the same object and this is true while objects
+ // are reference-counted, so return value is not a reference to a tmp.
+ return origin_of(rewrap(arg));
+}
+
+bool cv::gimpl::proto::is_dynamic(const cv::GArg& arg)
+{
+ // FIXME: refactor this method to be auto-generated from
+ // - GProtoArg variant parameter pack, and
+ // - traits over every type
+ switch (arg.kind)
+ {
+ case detail::ArgKind::GMAT:
+ case detail::ArgKind::GSCALAR:
+ case detail::ArgKind::GARRAY:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+cv::GRunArg cv::value_of(const cv::GOrigin &origin)
+{
+ switch (origin.shape)
+ {
+ case GShape::GSCALAR: return GRunArg(util::get<cv::gapi::own::Scalar>(origin.value));
+ default: util::throw_error(std::logic_error("Unsupported shape for constant"));
+ }
+}
+
+cv::GProtoArg cv::gimpl::proto::rewrap(const cv::GArg &arg)
+{
+ // FIXME: replace with a more generic any->variant
+ // (or variant<T> -> variant<U>) conversion?
+ switch (arg.kind)
+ {
+ case detail::ArgKind::GMAT: return GProtoArg(arg.get<cv::GMat>());
+ case detail::ArgKind::GSCALAR: return GProtoArg(arg.get<cv::GScalar>());
+ case detail::ArgKind::GARRAY: return GProtoArg(arg.get<cv::detail::GArrayU>());
+ default: util::throw_error(std::logic_error("Unsupported GArg type"));
+ }
+}
+
+cv::GMetaArg cv::descr_of(const cv::GRunArg &arg)
+{
+ switch (arg.index())
+ {
+#if !defined(GAPI_STANDALONE)
+ case GRunArg::index_of<cv::Mat>():
+ return cv::GMetaArg(descr_of(util::get<cv::Mat>(arg)));
+
+ case GRunArg::index_of<cv::Scalar>():
+ return cv::GMetaArg(descr_of(util::get<cv::Scalar>(arg)));
+#endif // !defined(GAPI_STANDALONE)
+
+ case GRunArg::index_of<cv::gapi::own::Mat>():
+ return cv::GMetaArg(descr_of(util::get<cv::gapi::own::Mat>(arg)));
+
+ case GRunArg::index_of<cv::gapi::own::Scalar>():
+ return cv::GMetaArg(descr_of(util::get<cv::gapi::own::Scalar>(arg)));
+
+ case GRunArg::index_of<cv::detail::VectorRef>():
+ return cv::GMetaArg(util::get<cv::detail::VectorRef>(arg).descr_of());
+
+ default: util::throw_error(std::logic_error("Unsupported GRunArg type"));
+ }
+}
+
+cv::GMetaArgs cv::descr_of(const cv::GRunArgs &args)
+{
+ cv::GMetaArgs metas;
+ ade::util::transform(args, std::back_inserter(metas), [](const cv::GRunArg &arg){ return descr_of(arg); });
+ return metas;
+}
+
+cv::GMetaArg cv::descr_of(const cv::GRunArgP &argp)
+{
+ switch (argp.index())
+ {
+#if !defined(GAPI_STANDALONE)
+ case GRunArgP::index_of<cv::Mat*>(): return GMetaArg(descr_of(*util::get<cv::Mat*>(argp)));
+ case GRunArgP::index_of<cv::UMat*>(): return GMetaArg(descr_of(*util::get<cv::UMat*>(argp)));
+ case GRunArgP::index_of<cv::Scalar*>(): return GMetaArg(descr_of(*util::get<cv::Scalar*>(argp)));
+#endif // !defined(GAPI_STANDALONE)
+ case GRunArgP::index_of<cv::gapi::own::Mat*>(): return GMetaArg(descr_of(*util::get<cv::gapi::own::Mat*>(argp)));
+ case GRunArgP::index_of<cv::gapi::own::Scalar*>(): return GMetaArg(descr_of(*util::get<cv::gapi::own::Scalar*>(argp)));
+ case GRunArgP::index_of<cv::detail::VectorRef>(): return GMetaArg(util::get<cv::detail::VectorRef>(argp).descr_of());
+ default: util::throw_error(std::logic_error("Unsupported GRunArgP type"));
+ }
+}
+
+namespace cv {
+std::ostream& operator<<(std::ostream& os, const cv::GMetaArg &arg)
+{
+ // FIXME: Implement via variant visitor
+ switch (arg.index())
+ {
+ case cv::GMetaArg::index_of<util::monostate>():
+ os << "(unresolved)";
+ break;
+
+ case cv::GMetaArg::index_of<cv::GMatDesc>():
+ os << util::get<cv::GMatDesc>(arg);
+ break;
+
+ case cv::GMetaArg::index_of<cv::GScalarDesc>():
+ os << util::get<cv::GScalarDesc>(arg);
+ break;
+
+ case cv::GMetaArg::index_of<cv::GArrayDesc>():
+ os << util::get<cv::GArrayDesc>(arg);
+ break;
+ default:
+ GAPI_Assert(false);
+ }
+
+ return os;
+}
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto_priv.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto_priv.hpp
new file mode 100644
index 000000000..2684924c7
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gproto_priv.hpp
@@ -0,0 +1,35 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GPROTO_PRIV_HPP
+#define OPENCV_GAPI_GPROTO_PRIV_HPP
+
+#include "opencv2/gapi/gproto.hpp"
+#include "opencv2/gapi/garg.hpp"
+
+#include "api/gapi_priv.hpp"
+
+namespace cv {
+namespace gimpl {
+namespace proto {
+
+// These methods are used by GModelBuilder only
+// FIXME: Document semantics
+
+// FIXME: GAPI_EXPORTS because of tests only!
+// FIXME: Possible dangling reference alert!!!
+GAPI_EXPORTS const GOrigin& origin_of (const GProtoArg &arg);
+GAPI_EXPORTS const GOrigin& origin_of (const GArg &arg);
+
+bool is_dynamic(const GArg &arg);
+GProtoArg rewrap (const GArg &arg);
+
+} // proto
+} // gimpl
+} // cv
+
+#endif // OPENCV_GAPI_GPROTO_PRIV_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/gscalar.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gscalar.cpp
new file mode 100644
index 000000000..30f3dc944
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/gscalar.cpp
@@ -0,0 +1,73 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/gscalar.hpp"
+#include "opencv2/gapi/own/convert.hpp"
+#include "api/gapi_priv.hpp" // GOrigin
+
+// cv::GScalar public implementation ///////////////////////////////////////////
+cv::GScalar::GScalar()
+ : m_priv(new GOrigin(GShape::GSCALAR, cv::GNode::Param()))
+{
+}
+
+cv::GScalar::GScalar(const GNode &n, std::size_t out)
+ : m_priv(new GOrigin(GShape::GSCALAR, n, out))
+{
+}
+
+cv::GScalar::GScalar(const cv::gapi::own::Scalar& s)
+ : m_priv(new GOrigin(GShape::GSCALAR, cv::gimpl::ConstVal(s)))
+{
+}
+
+cv::GScalar::GScalar(cv::gapi::own::Scalar&& s)
+ : m_priv(new GOrigin(GShape::GSCALAR, cv::gimpl::ConstVal(std::move(s))))
+{
+}
+
+cv::GScalar::GScalar(double v0)
+ : m_priv(new GOrigin(GShape::GSCALAR, cv::gimpl::ConstVal(cv::gapi::own::Scalar(v0))))
+{
+}
+
+cv::GOrigin& cv::GScalar::priv()
+{
+ return *m_priv;
+}
+
+const cv::GOrigin& cv::GScalar::priv() const
+{
+ return *m_priv;
+}
+
+cv::GScalarDesc cv::descr_of(const cv::gapi::own::Scalar &)
+{
+ return empty_scalar_desc();
+}
+
+#if !defined(GAPI_STANDALONE)
+cv::GScalar::GScalar(const cv::Scalar& s)
+ : m_priv(new GOrigin(GShape::GSCALAR, cv::gimpl::ConstVal(to_own(s))))
+{
+}
+
+cv::GScalarDesc cv::descr_of(const cv::Scalar& s)
+{
+ return cv::descr_of(to_own(s));
+}
+#endif // !defined(GAPI_STANDALONE)
+
+namespace cv {
+std::ostream& operator<<(std::ostream& os, const cv::GScalarDesc &)
+{
+ os << "(scalar)";
+ return os;
+}
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_core.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_core.cpp
new file mode 100644
index 000000000..c9fe19ed6
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_core.cpp
@@ -0,0 +1,359 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/gcall.hpp"
+#include "opencv2/gapi/gscalar.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+#include "opencv2/gapi/core.hpp"
+
+#include <tuple>
+#include <numeric>
+
+namespace cv { namespace gapi {
+
+GMat add(const GMat& src1, const GMat& src2, int dtype)
+{
+ return core::GAdd::on(src1, src2, dtype);
+}
+
+GMat addC(const GMat& src1, const GScalar& c, int dtype)
+{
+ return core::GAddC::on(src1, c, dtype);
+}
+
+GMat addC(const GScalar& c, const GMat& src1, int dtype)
+{
+ return core::GAddC::on(src1, c, dtype);
+}
+
+GMat sub(const GMat& src1, const GMat& src2, int dtype)
+{
+ return core::GSub::on(src1, src2, dtype);
+}
+
+GMat subC(const GMat& src1, const GScalar& c, int dtype)
+{
+ return core::GSubC::on(src1, c, dtype);
+}
+
+GMat subRC(const GScalar& c, const GMat& src, int dtype)
+{
+ return core::GSubRC::on(c, src, dtype);
+}
+
+GMat mul(const GMat& src1, const GMat& src2, double scale, int dtype)
+{
+ return core::GMul::on(src1, src2, scale, dtype);
+}
+
+GMat mulC(const GMat& src, double scale, int dtype)
+{
+ return core::GMulCOld::on(src, scale, dtype);
+}
+
+GMat mulC(const GMat& src, const GScalar& multiplier, int dtype)
+{
+ return core::GMulC::on(src, multiplier, dtype);
+}
+
+GMat mulC(const GScalar& multiplier, const GMat& src, int dtype)
+{
+ return core::GMulC::on(src, multiplier, dtype);
+}
+
+GMat div(const GMat& src1, const GMat& src2, double scale, int dtype)
+{
+ return core::GDiv::on(src1, src2, scale, dtype);
+}
+
+GMat divC(const GMat& src, const GScalar& divisor, double scale, int dtype)
+{
+ return core::GDivC::on(src, divisor, scale, dtype);
+}
+
+GMat divRC(const GScalar& divident, const GMat& src, double scale, int dtype)
+{
+ return core::GDivRC::on(divident, src, scale, dtype);
+}
+
+GScalar mean(const GMat& src)
+{
+ return core::GMean::on(src);
+}
+
+GMat mask(const GMat& src, const GMat& mask)
+{
+ return core::GMask::on(src, mask);
+}
+
+std::tuple<GMat, GMat> polarToCart(const GMat& magnitude, const GMat& angle,
+ bool angleInDegrees)
+{
+ return core::GPolarToCart::on(magnitude, angle, angleInDegrees);
+}
+
+std::tuple<GMat, GMat> cartToPolar(const GMat& x, const GMat& y,
+ bool angleInDegrees)
+{
+ return core::GCartToPolar::on(x, y, angleInDegrees);
+}
+
+GMat phase(const GMat &x, const GMat &y, bool angleInDegrees)
+{
+ return core::GPhase::on(x, y, angleInDegrees);
+}
+
+GMat cmpGT(const GMat& src1, const GMat& src2)
+{
+ return core::GCmpGT::on(src1, src2);
+}
+
+GMat cmpLT(const GMat& src1, const GMat& src2)
+{
+ return core::GCmpLT::on(src1, src2);
+}
+
+GMat cmpGE(const GMat& src1, const GMat& src2)
+{
+ return core::GCmpGE::on(src1, src2);
+}
+
+GMat cmpLE(const GMat& src1, const GMat& src2)
+{
+ return core::GCmpLE::on(src1, src2);
+}
+
+GMat cmpEQ(const GMat& src1, const GMat& src2)
+{
+ return core::GCmpEQ::on(src1, src2);
+}
+
+GMat cmpNE(const GMat& src1, const GMat& src2)
+{
+ return core::GCmpNE::on(src1, src2);
+}
+
+GMat cmpGT(const GMat& src1, const GScalar& src2)
+{
+ return core::GCmpGTScalar::on(src1, src2);
+}
+
+GMat cmpLT(const GMat& src1, const GScalar& src2)
+{
+ return core::GCmpLTScalar::on(src1, src2);
+}
+
+GMat cmpGE(const GMat& src1, const GScalar& src2)
+{
+ return core::GCmpGEScalar::on(src1, src2);
+}
+
+GMat cmpLE(const GMat& src1, const GScalar& src2)
+{
+ return core::GCmpLEScalar::on(src1, src2);
+}
+
+GMat cmpEQ(const GMat& src1, const GScalar& src2)
+{
+ return core::GCmpEQScalar::on(src1, src2);
+}
+
+GMat cmpNE(const GMat& src1, const GScalar& src2)
+{
+ return core::GCmpNEScalar::on(src1, src2);
+}
+
+GMat min(const GMat& src1, const GMat& src2)
+{
+ return core::GMin::on(src1, src2);
+}
+
+GMat max(const GMat& src1, const GMat& src2)
+{
+ return core::GMax::on(src1, src2);
+}
+
+GMat absDiff(const GMat& src1, const GMat& src2)
+{
+ return core::GAbsDiff::on(src1, src2);
+}
+
+GMat absDiffC(const GMat& src, const GScalar& c)
+{
+ return core::GAbsDiffC::on(src, c);
+}
+
+GMat bitwise_and(const GMat& src1, const GMat& src2)
+{
+ return core::GAnd::on(src1, src2);
+}
+
+GMat bitwise_and(const GMat& src1, const GScalar& src2)
+{
+ return core::GAndS::on(src1, src2);
+}
+
+GMat bitwise_or(const GMat& src1, const GMat& src2)
+{
+ return core::GOr::on(src1, src2);
+}
+
+GMat bitwise_or(const GMat& src1, const GScalar& src2)
+{
+ return core::GOrS::on(src1, src2);
+}
+
+GMat bitwise_xor(const GMat& src1, const GMat& src2)
+{
+ return core::GXor::on(src1, src2);
+}
+
+GMat bitwise_xor(const GMat& src1, const GScalar& src2)
+{
+ return core::GXorS::on(src1, src2);
+}
+
+GMat bitwise_not(const GMat& src1)
+{
+ return core::GNot::on(src1);
+}
+
+GMat select(const GMat& src1, const GMat& src2, const GMat& mask)
+{
+ return core::GSelect::on(src1, src2, mask);
+}
+
+GScalar sum(const GMat& src)
+{
+ return core::GSum::on(src);
+}
+
+GMat addWeighted(const GMat& src1, double alpha, const GMat& src2, double beta, double gamma, int dtype)
+{
+ return core::GAddW::on(src1, alpha, src2, beta, gamma, dtype);
+}
+
+GScalar normL1(const GMat& src)
+{
+ return core::GNormL1::on(src);
+}
+
+GScalar normL2(const GMat& src)
+{
+ return core::GNormL2::on(src);
+}
+
+GScalar normInf(const GMat& src)
+{
+ return core::GNormInf::on(src);
+}
+
+std::tuple<GMat, GMat> integral(const GMat& src, int sdepth, int sqdepth)
+{
+ return core::GIntegral::on(src, sdepth, sqdepth);
+}
+
+GMat threshold(const GMat& src, const GScalar& thresh, const GScalar& maxval, int type)
+{
+ GAPI_Assert(type != cv::THRESH_TRIANGLE && type != cv::THRESH_OTSU);
+ return core::GThreshold::on(src, thresh, maxval, type);
+}
+
+std::tuple<GMat, GScalar> threshold(const GMat& src, const GScalar& maxval, int type)
+{
+ GAPI_Assert(type == cv::THRESH_TRIANGLE || type == cv::THRESH_OTSU);
+ return core::GThresholdOT::on(src, maxval, type);
+}
+
+GMat inRange(const GMat& src, const GScalar& threshLow, const GScalar& threshUp)
+{
+ return core::GInRange::on(src, threshLow, threshUp);
+}
+
+std::tuple<GMat, GMat, GMat> split3(const GMat& src)
+{
+ return core::GSplit3::on(src);
+}
+
+std::tuple<GMat, GMat, GMat, GMat> split4(const GMat& src)
+{
+ return core::GSplit4::on(src);
+}
+
+GMat merge3(const GMat& src1, const GMat& src2, const GMat& src3)
+{
+ return core::GMerge3::on(src1, src2, src3);
+}
+
+GMat merge4(const GMat& src1, const GMat& src2, const GMat& src3, const GMat& src4)
+{
+ return core::GMerge4::on(src1, src2, src3, src4);
+}
+
+GMat resize(const GMat& src, const Size& dsize, double fx, double fy, int interpolation)
+{
+ return core::GResize::on(src, dsize, fx, fy, interpolation);
+}
+
+GMat remap(const GMat& src, const Mat& map1, const Mat& map2,
+ int interpolation, int borderMode,
+ const Scalar& borderValue)
+{
+ return core::GRemap::on(src, map1, map2, interpolation, borderMode, borderValue);
+}
+
+GMat flip(const GMat& src, int flipCode)
+{
+ return core::GFlip::on(src, flipCode);
+}
+
+GMat crop(const GMat& src, const Rect& rect)
+{
+ return core::GCrop::on(src, rect);
+}
+
+GMat concatHor(const GMat& src1, const GMat& src2)
+{
+ return core::GConcatHor::on(src1, src2);
+}
+
+GMat concatHor(const std::vector<GMat>& v)
+{
+ GAPI_Assert(v.size() >= 2);
+ return std::accumulate(v.begin()+1, v.end(), v[0], core::GConcatHor::on);
+}
+
+GMat concatVert(const GMat& src1, const GMat& src2)
+{
+ return core::GConcatVert::on(src1, src2);
+}
+
+GMat concatVert(const std::vector<GMat>& v)
+{
+ GAPI_Assert(v.size() >= 2);
+ return std::accumulate(v.begin()+1, v.end(), v[0], core::GConcatVert::on);
+}
+
+GMat LUT(const GMat& src, const Mat& lut)
+{
+ return core::GLUT::on(src, lut);
+}
+
+GMat convertTo(const GMat& m, int rtype, double alpha, double beta)
+{
+ return core::GConvertTo::on(m, rtype, alpha, beta);
+}
+
+GMat sqrt(const GMat& src)
+{
+ return core::GSqrt::on(src);
+}
+
+} //namespace gapi
+} //namespace cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_imgproc.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_imgproc.cpp
new file mode 100644
index 000000000..7c4b522e9
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/kernels_imgproc.cpp
@@ -0,0 +1,144 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/gscalar.hpp"
+#include "opencv2/gapi/gcall.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+#include "opencv2/gapi/imgproc.hpp"
+
+namespace cv { namespace gapi {
+
+GMat sepFilter(const GMat& src, int ddepth, const Mat& kernelX, const Mat& kernelY, const Point& anchor,
+ const Scalar& delta, int borderType, const Scalar& borderVal)
+{
+ return imgproc::GSepFilter::on(src, ddepth, kernelX, kernelY, anchor, delta, borderType, borderVal);
+}
+
+GMat filter2D(const GMat& src, int ddepth, const Mat& kernel, const Point& anchor, const Scalar& delta, int borderType,
+ const Scalar& bordVal)
+{
+ return imgproc::GFilter2D::on(src, ddepth, kernel, anchor, delta, borderType, bordVal);
+}
+
+GMat boxFilter(const GMat& src, int dtype, const Size& ksize, const Point& anchor,
+ bool normalize, int borderType, const Scalar& bordVal)
+{
+ return imgproc::GBoxFilter::on(src, dtype, ksize, anchor, normalize, borderType, bordVal);
+}
+
+GMat blur(const GMat& src, const Size& ksize, const Point& anchor,
+ int borderType, const Scalar& bordVal)
+{
+ return imgproc::GBlur::on(src, ksize, anchor, borderType, bordVal);
+}
+
+GMat gaussianBlur(const GMat& src, const Size& ksize, double sigmaX, double sigmaY,
+ int borderType, const Scalar& bordVal)
+{
+ return imgproc::GGaussBlur::on(src, ksize, sigmaX, sigmaY, borderType, bordVal);
+}
+
+GMat medianBlur(const GMat& src, int ksize)
+{
+ return imgproc::GMedianBlur::on(src, ksize);
+}
+
+GMat erode(const GMat& src, const Mat& kernel, const Point& anchor, int iterations,
+ int borderType, const Scalar& borderValue )
+{
+ return imgproc::GErode::on(src, kernel, anchor, iterations, borderType, borderValue);
+}
+
+GMat erode3x3(const GMat& src, int iterations,
+ int borderType, const Scalar& borderValue )
+{
+ return erode(src, cv::Mat(), cv::Point(-1, -1), iterations, borderType, borderValue);
+}
+
+GMat dilate(const GMat& src, const Mat& kernel, const Point& anchor, int iterations,
+ int borderType, const Scalar& borderValue)
+{
+ return imgproc::GDilate::on(src, kernel, anchor, iterations, borderType, borderValue);
+}
+
+GMat dilate3x3(const GMat& src, int iterations,
+ int borderType, const Scalar& borderValue)
+{
+ return dilate(src, cv::Mat(), cv::Point(-1,-1), iterations, borderType, borderValue);
+}
+
+GMat Sobel(const GMat& src, int ddepth, int dx, int dy, int ksize,
+ double scale, double delta,
+ int borderType, const Scalar& bordVal)
+{
+ return imgproc::GSobel::on(src, ddepth, dx, dy, ksize, scale, delta, borderType, bordVal);
+}
+
+GMat equalizeHist(const GMat& src)
+{
+ return imgproc::GEqHist::on(src);
+}
+
+GMat Canny(const GMat& src, double thr1, double thr2, int apertureSize, bool l2gradient)
+{
+ return imgproc::GCanny::on(src, thr1, thr2, apertureSize, l2gradient);
+}
+
+GMat RGB2Gray(const GMat& src)
+{
+ return imgproc::GRGB2Gray::on(src);
+}
+
+GMat RGB2Gray(const GMat& src, float rY, float gY, float bY)
+{
+ return imgproc::GRGB2GrayCustom::on(src, rY, gY, bY);
+}
+
+GMat BGR2Gray(const GMat& src)
+{
+ return imgproc::GBGR2Gray::on(src);
+}
+
+GMat RGB2YUV(const GMat& src)
+{
+ return imgproc::GRGB2YUV::on(src);
+}
+
+GMat BGR2LUV(const GMat& src)
+{
+ return imgproc::GBGR2LUV::on(src);
+}
+
+GMat LUV2BGR(const GMat& src)
+{
+ return imgproc::GLUV2BGR::on(src);
+}
+
+GMat BGR2YUV(const GMat& src)
+{
+ return imgproc::GBGR2YUV::on(src);
+}
+
+GMat YUV2BGR(const GMat& src)
+{
+ return imgproc::GYUV2BGR::on(src);
+}
+
+GMat YUV2RGB(const GMat& src)
+{
+ return imgproc::GYUV2RGB::on(src);
+}
+
+GMat RGB2Lab(const GMat& src)
+{
+ return imgproc::GRGB2Lab::on(src);
+}
+
+} //namespace gapi
+} //namespace cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/api/operators.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/api/operators.cpp
new file mode 100644
index 000000000..44fc4fa52
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/api/operators.cpp
@@ -0,0 +1,213 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/imgproc.hpp"
+#include "opencv2/gapi/core.hpp"
+#include "opencv2/gapi/gscalar.hpp"
+#include "opencv2/gapi/operators.hpp"
+
+cv::GMat operator+(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::add(lhs, rhs);
+}
+
+cv::GMat operator+(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::addC(lhs, rhs);
+}
+
+cv::GMat operator+(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::addC(rhs, lhs);
+}
+
+cv::GMat operator-(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::sub(lhs, rhs);
+}
+
+cv::GMat operator-(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::subC(lhs, rhs);
+}
+
+cv::GMat operator-(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::subRC(lhs, rhs);
+}
+
+cv::GMat operator*(const cv::GMat& lhs, float rhs)
+{
+ return cv::gapi::mulC(lhs, static_cast<double>(rhs));
+}
+
+cv::GMat operator*(float lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::mulC(rhs, static_cast<double>(lhs));
+}
+
+cv::GMat operator*(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::mulC(lhs, rhs);
+}
+
+cv::GMat operator*(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::mulC(rhs, lhs);
+}
+
+cv::GMat operator/(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::divC(lhs, rhs, 1.0);
+}
+
+cv::GMat operator/(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::div(lhs, rhs, 1.0);
+}
+
+cv::GMat operator/(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::divRC(lhs, rhs, 1.0);
+}
+
+cv::GMat operator&(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::bitwise_and(lhs, rhs);
+}
+
+cv::GMat operator&(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::bitwise_and(lhs, rhs);
+}
+
+cv::GMat operator&(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::bitwise_and(rhs, lhs);
+}
+
+cv::GMat operator|(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::bitwise_or(lhs, rhs);
+}
+
+cv::GMat operator|(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::bitwise_or(lhs, rhs);
+}
+
+cv::GMat operator|(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::bitwise_or(rhs, lhs);
+}
+
+cv::GMat operator^(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::bitwise_xor(lhs, rhs);
+}
+
+cv::GMat operator^(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::bitwise_xor(lhs, rhs);
+}
+
+cv::GMat operator^(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::bitwise_xor(rhs, lhs);
+}
+
+cv::GMat operator~(const cv::GMat& lhs)
+{
+ return cv::gapi::bitwise_not(lhs);
+}
+
+cv::GMat operator>(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpGT(lhs, rhs);
+}
+
+cv::GMat operator>=(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpGE(lhs, rhs);
+}
+
+cv::GMat operator<(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpLT(lhs, rhs);
+}
+
+cv::GMat operator<=(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpLE(lhs, rhs);
+}
+
+cv::GMat operator==(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpEQ(lhs, rhs);
+}
+
+cv::GMat operator!=(const cv::GMat& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpNE(lhs, rhs);
+}
+
+cv::GMat operator>(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::cmpGT(lhs, rhs);
+}
+
+cv::GMat operator>=(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::cmpGE(lhs, rhs);
+}
+
+cv::GMat operator<(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::cmpLT(lhs, rhs);
+}
+
+cv::GMat operator<=(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::cmpLE(lhs, rhs);
+}
+
+cv::GMat operator==(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::cmpEQ(lhs, rhs);
+}
+
+cv::GMat operator!=(const cv::GMat& lhs, const cv::GScalar& rhs)
+{
+ return cv::gapi::cmpNE(lhs, rhs);
+}
+
+cv::GMat operator>(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpLT(rhs, lhs);
+}
+cv::GMat operator>=(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpLE(rhs, lhs);
+}
+cv::GMat operator<(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpGT(rhs, lhs);
+}
+cv::GMat operator<=(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpGE(rhs, lhs);
+}
+cv::GMat operator==(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpEQ(rhs, lhs);
+}
+cv::GMat operator!=(const cv::GScalar& lhs, const cv::GMat& rhs)
+{
+ return cv::gapi::cmpNE(rhs, lhs);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/README.md b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/README.md
new file mode 100644
index 000000000..3aeeb1ece
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/README.md
@@ -0,0 +1,2 @@
+This directory contains various G-API backends, which provide scheduling
+logic and kernel implementations for specific targets. \ No newline at end of file
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gbackend.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gbackend.hpp
new file mode 100644
index 000000000..613022cb9
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gbackend.hpp
@@ -0,0 +1,106 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GBACKEND_HPP
+#define OPENCV_GAPI_GBACKEND_HPP
+
+#include <string>
+#include <memory>
+
+#include <ade/node.hpp>
+
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/own/mat.hpp"
+
+#include "opencv2/gapi/util/optional.hpp"
+#include "opencv2/gapi/own/scalar.hpp"
+
+#include "compiler/gmodel.hpp"
+
+namespace cv {
+namespace gimpl {
+
+ // Forward declarations
+ struct Data;
+ struct RcDesc;
+
+namespace magazine {
+ template<typename... Ts> struct Class
+ {
+ template<typename T> using MapT = std::unordered_map<int, T>;
+ template<typename T> MapT<T>& slot()
+ {
+ return std::get<ade::util::type_list_index<T, Ts...>::value>(slots);
+ }
+ template<typename T> const MapT<T>& slot() const
+ {
+ return std::get<ade::util::type_list_index<T, Ts...>::value>(slots);
+ }
+ private:
+ std::tuple<MapT<Ts>...> slots;
+ };
+
+} // namespace magazine
+#if !defined(GAPI_STANDALONE)
+using Mag = magazine::Class<cv::gapi::own::Mat, cv::UMat, cv::gapi::own::Scalar, cv::detail::VectorRef>;
+#else
+using Mag = magazine::Class<cv::gapi::own::Mat, cv::gapi::own::Scalar, cv::detail::VectorRef>;
+#endif
+
+namespace magazine
+{
+ void bindInArg (Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat = false);
+ void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat = false);
+
+ void resetInternalData(Mag& mag, const Data &d);
+ cv::GRunArg getArg (const Mag& mag, const RcDesc &ref);
+ cv::GRunArgP getObjPtr ( Mag& mag, const RcDesc &rc, bool is_umat = false);
+ void writeBack (const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat = false);
+} // namespace magazine
+
+namespace detail
+{
+template<typename... Ts> struct magazine
+{
+ template<typename T> using MapT = std::unordered_map<int, T>;
+ template<typename T> MapT<T>& slot()
+ {
+ return std::get<util::type_list_index<T, Ts...>::value>(slots);
+ }
+ template<typename T> const MapT<T>& slot() const
+ {
+ return std::get<util::type_list_index<T, Ts...>::value>(slots);
+ }
+private:
+ std::tuple<MapT<Ts>...> slots;
+};
+} // namespace detail
+
+struct GRuntimeArgs
+{
+ GRunArgs inObjs;
+ GRunArgsP outObjs;
+};
+
+template<typename T>
+inline cv::util::optional<T> getCompileArg(const cv::GCompileArgs &args)
+{
+ for (auto &compile_arg : args)
+ {
+ if (compile_arg.tag == cv::detail::CompileArgTag<T>::tag())
+ {
+ return cv::util::optional<T>(compile_arg.get<T>());
+ }
+ }
+ return cv::util::optional<T>();
+}
+
+
+
+}} // cv::gimpl
+
+#endif // OPENCV_GAPI_GBACKEND_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gcompoundbackend.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gcompoundbackend.cpp
new file mode 100644
index 000000000..948898f28
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gcompoundbackend.cpp
@@ -0,0 +1,20 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/gcompoundkernel.hpp" // compound::backend()
+
+#include "api/gbackend_priv.hpp"
+#include "compiler/gislandmodel.hpp" // GIslandExecutable
+
+cv::gapi::GBackend cv::gapi::compound::backend()
+{
+ // A pointer to dummy Priv is used to uniquely identify backends
+ static cv::gapi::GBackend this_backend(std::make_shared<cv::gapi::GBackend::Priv>());
+ return this_backend;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gcompoundkernel.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gcompoundkernel.cpp
new file mode 100644
index 000000000..89abcef59
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/common/gcompoundkernel.cpp
@@ -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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <ade/util/zip_range.hpp> // util::indexed
+#include "opencv2/gapi/gcompoundkernel.hpp"
+#include "compiler/gobjref.hpp"
+
+// FIXME move to backends
+
+cv::detail::GCompoundContext::GCompoundContext(const cv::GArgs& in_args)
+{
+ m_args.resize(in_args.size());
+ for (const auto& it : ade::util::indexed(in_args))
+ {
+ const auto& i = ade::util::index(it);
+ const auto& in_arg = ade::util::value(it);
+
+ if (in_arg.kind != cv::detail::ArgKind::GOBJREF)
+ {
+ m_args[i] = in_arg;
+ }
+ else
+ {
+ const cv::gimpl::RcDesc &ref = in_arg.get<cv::gimpl::RcDesc>();
+ switch (ref.shape)
+ {
+ case GShape::GMAT : m_args[i] = GArg(GMat()); break;
+ case GShape::GSCALAR: m_args[i] = GArg(GScalar()); break;
+ case GShape::GARRAY :/* do nothing - as handled in a special way, see gcompoundkernel.hpp for details */; break;
+ default: GAPI_Assert(false);
+ }
+ }
+ }
+ GAPI_Assert(m_args.size() == in_args.size());
+}
+
+cv::detail::GCompoundKernel::GCompoundKernel(const F& f) : m_f(f)
+{
+}
+
+void cv::detail::GCompoundKernel::apply(cv::detail::GCompoundContext& ctx) { m_f(ctx); }
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.cpp
new file mode 100644
index 000000000..5cc8bb0b7
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.cpp
@@ -0,0 +1,229 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <functional>
+#include <unordered_set>
+
+#include <ade/util/algorithm.hpp>
+
+#include <ade/util/range.hpp>
+#include <ade/util/zip_range.hpp>
+#include <ade/util/chain_range.hpp>
+
+#include <ade/typed_graph.hpp>
+
+#include "opencv2/gapi/gcommon.hpp"
+#include "opencv2/gapi/util/any.hpp"
+#include "opencv2/gapi/gtype_traits.hpp"
+
+#include "compiler/gobjref.hpp"
+#include "compiler/gmodel.hpp"
+
+#include "backends/cpu/gcpubackend.hpp"
+#include "backends/cpu/gcpuimgproc.hpp"
+#include "backends/cpu/gcpucore.hpp"
+
+#include "api/gbackend_priv.hpp" // FIXME: Make it part of Backend SDK!
+
+// FIXME: Is there a way to take a typed graph (our GModel),
+// and create a new typed graph _ATOP_ of that (by extending with a couple of
+// new types?).
+// Alternatively, is there a way to compose types graphs?
+//
+// If not, we need to introduce that!
+using GCPUModel = ade::TypedGraph
+ < cv::gimpl::Unit
+ , cv::gimpl::Protocol
+ >;
+
+// FIXME: Same issue with Typed and ConstTyped
+using GConstGCPUModel = ade::ConstTypedGraph
+ < cv::gimpl::Unit
+ , cv::gimpl::Protocol
+ >;
+
+namespace
+{
+ class GCPUBackendImpl final: public cv::gapi::GBackend::Priv
+ {
+ virtual void unpackKernel(ade::Graph &graph,
+ const ade::NodeHandle &op_node,
+ const cv::GKernelImpl &impl) override
+ {
+ GCPUModel gm(graph);
+ auto cpu_impl = cv::util::any_cast<cv::GCPUKernel>(impl.opaque);
+ gm.metadata(op_node).set(cv::gimpl::Unit{cpu_impl});
+ }
+
+ virtual EPtr compile(const ade::Graph &graph,
+ const cv::GCompileArgs &,
+ const std::vector<ade::NodeHandle> &nodes) const override
+ {
+ return EPtr{new cv::gimpl::GCPUExecutable(graph, nodes)};
+ }
+ };
+}
+
+cv::gapi::GBackend cv::gapi::cpu::backend()
+{
+ static cv::gapi::GBackend this_backend(std::make_shared<GCPUBackendImpl>());
+ return this_backend;
+}
+
+// GCPUExcecutable implementation //////////////////////////////////////////////
+cv::gimpl::GCPUExecutable::GCPUExecutable(const ade::Graph &g,
+ const std::vector<ade::NodeHandle> &nodes)
+ : m_g(g), m_gm(m_g)
+{
+ // Convert list of operations (which is topologically sorted already)
+ // into an execution script.
+ for (auto &nh : nodes)
+ {
+ switch (m_gm.metadata(nh).get<NodeType>().t)
+ {
+ case NodeType::OP: m_script.push_back({nh, GModel::collectOutputMeta(m_gm, nh)}); break;
+ case NodeType::DATA:
+ {
+ m_dataNodes.push_back(nh);
+ const auto &desc = m_gm.metadata(nh).get<Data>();
+ if (desc.storage == Data::Storage::CONST)
+ {
+ auto rc = RcDesc{desc.rc, desc.shape, desc.ctor};
+ magazine::bindInArg(m_res, rc, m_gm.metadata(nh).get<ConstValue>().arg);
+ }
+ //preallocate internal Mats in advance
+ if (desc.storage == Data::Storage::INTERNAL && desc.shape == GShape::GMAT)
+ {
+ const auto mat_desc = util::get<cv::GMatDesc>(desc.meta);
+ const auto type = CV_MAKETYPE(mat_desc.depth, mat_desc.chan);
+ m_res.slot<cv::gapi::own::Mat>()[desc.rc].create(mat_desc.size, type);
+ }
+ break;
+ }
+ default: util::throw_error(std::logic_error("Unsupported NodeType type"));
+ }
+ }
+}
+
+// FIXME: Document what it does
+cv::GArg cv::gimpl::GCPUExecutable::packArg(const GArg &arg)
+{
+ // No API placeholders allowed at this point
+ // FIXME: this check has to be done somewhere in compilation stage.
+ GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT
+ && arg.kind != cv::detail::ArgKind::GSCALAR
+ && arg.kind != cv::detail::ArgKind::GARRAY);
+
+ if (arg.kind != cv::detail::ArgKind::GOBJREF)
+ {
+ // All other cases - pass as-is, with no transformations to GArg contents.
+ return arg;
+ }
+ GAPI_Assert(arg.kind == cv::detail::ArgKind::GOBJREF);
+
+ // Wrap associated CPU object (either host or an internal one)
+ // FIXME: object can be moved out!!! GExecutor faced that.
+ const cv::gimpl::RcDesc &ref = arg.get<cv::gimpl::RcDesc>();
+ switch (ref.shape)
+ {
+ case GShape::GMAT: return GArg(m_res.slot<cv::gapi::own::Mat>() [ref.id]);
+ case GShape::GSCALAR: return GArg(m_res.slot<cv::gapi::own::Scalar>()[ref.id]);
+ // Note: .at() is intentional for GArray as object MUST be already there
+ // (and constructed by either bindIn/Out or resetInternal)
+ case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id));
+ default:
+ util::throw_error(std::logic_error("Unsupported GShape type"));
+ break;
+ }
+}
+
+void cv::gimpl::GCPUExecutable::run(std::vector<InObj> &&input_objs,
+ std::vector<OutObj> &&output_objs)
+{
+ // Update resources with run-time information - what this Island
+ // has received from user (or from another Island, or mix...)
+ // FIXME: Check input/output objects against GIsland protocol
+
+ for (auto& it : input_objs) magazine::bindInArg (m_res, it.first, it.second);
+ for (auto& it : output_objs) magazine::bindOutArg(m_res, it.first, it.second);
+
+ // Initialize (reset) internal data nodes with user structures
+ // before processing a frame (no need to do it for external data structures)
+ GModel::ConstGraph gm(m_g);
+ for (auto nh : m_dataNodes)
+ {
+ const auto &desc = gm.metadata(nh).get<Data>();
+
+ if ( desc.storage == Data::Storage::INTERNAL
+ && !util::holds_alternative<util::monostate>(desc.ctor))
+ {
+ // FIXME: Note that compile-time constant data objects (like
+ // a value-initialized GArray<T>) also satisfy this condition
+ // and should be excluded, but now we just don't support it
+ magazine::resetInternalData(m_res, desc);
+ }
+ }
+
+ // OpenCV backend execution is not a rocket science at all.
+ // Simply invoke our kernels in the proper order.
+ GConstGCPUModel gcm(m_g);
+ for (auto &op_info : m_script)
+ {
+ const auto &op = m_gm.metadata(op_info.nh).get<Op>();
+
+ // Obtain our real execution unit
+ // TODO: Should kernels be copyable?
+ GCPUKernel k = gcm.metadata(op_info.nh).get<Unit>().k;
+
+ // Initialize kernel's execution context:
+ // - Input parameters
+ GCPUContext context;
+ context.m_args.reserve(op.args.size());
+
+ using namespace std::placeholders;
+ ade::util::transform(op.args,
+ std::back_inserter(context.m_args),
+ std::bind(&GCPUExecutable::packArg, this, _1));
+
+ // - Output parameters.
+ // FIXME: pre-allocate internal Mats, etc, according to the known meta
+ for (const auto &out_it : ade::util::indexed(op.outs))
+ {
+ // FIXME: Can the same GArg type resolution mechanism be reused here?
+ const auto out_port = ade::util::index(out_it);
+ const auto out_desc = ade::util::value(out_it);
+ context.m_results[out_port] = magazine::getObjPtr(m_res, out_desc);
+ }
+
+ // Now trigger the executable unit
+ k.apply(context);
+
+ //As Kernels are forbidden to allocate memory for (Mat) outputs,
+ //this code seems redundant, at least for Mats
+ //FIXME: unify with cv::detail::ensure_out_mats_not_reallocated
+ for (const auto &out_it : ade::util::indexed(op_info.expected_out_metas))
+ {
+ const auto out_index = ade::util::index(out_it);
+ const auto expected_meta = ade::util::value(out_it);
+ const auto out_meta = descr_of(context.m_results[out_index]);
+
+ if (expected_meta != out_meta)
+ {
+ util::throw_error
+ (std::logic_error
+ ("Output meta doesn't "
+ "coincide with the generated meta\n"
+ "Expected: " + ade::util::to_string(expected_meta) + "\n"
+ "Actual : " + ade::util::to_string(out_meta)));
+ }
+ }
+ } // for(m_script)
+
+ for (auto &it : output_objs) magazine::writeBack(m_res, it.first, it.second);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.hpp
new file mode 100644
index 000000000..6ce8c4883
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpubackend.hpp
@@ -0,0 +1,72 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCPUBACKEND_HPP
+#define OPENCV_GAPI_GCPUBACKEND_HPP
+
+#include <map> // map
+#include <unordered_map> // unordered_map
+#include <tuple> // tuple
+#include <ade/util/algorithm.hpp> // type_list_index
+
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gproto.hpp"
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+
+
+#include "api/gapi_priv.hpp"
+#include "backends/common/gbackend.hpp"
+#include "compiler/gislandmodel.hpp"
+
+namespace cv { namespace gimpl {
+
+struct Unit
+{
+ static const char *name() { return "HostKernel"; }
+ GCPUKernel k;
+};
+
+class GCPUExecutable final: public GIslandExecutable
+{
+ const ade::Graph &m_g;
+ GModel::ConstGraph m_gm;
+
+ struct OperationInfo
+ {
+ ade::NodeHandle nh;
+ GMetaArgs expected_out_metas;
+ };
+
+ // Execution script, currently absolutely naive
+ std::vector<OperationInfo> m_script;
+ // List of all resources in graph (both internal and external)
+ std::vector<ade::NodeHandle> m_dataNodes;
+
+ // Actual data of all resources in graph (both internal and external)
+ Mag m_res;
+ GArg packArg(const GArg &arg);
+
+public:
+ GCPUExecutable(const ade::Graph &graph,
+ const std::vector<ade::NodeHandle> &nodes);
+
+ virtual inline bool canReshape() const override { return false; }
+ virtual inline void reshape(ade::Graph&, const GCompileArgs&) override
+ {
+ // FIXME: CPU plugin is in fact reshapeable (as it was initially,
+ // even before outMeta() has been introduced), so this limitation
+ // should be dropped.
+ util::throw_error(std::logic_error("GCPUExecutable::reshape() should never be called"));
+ }
+
+ virtual void run(std::vector<InObj> &&input_objs,
+ std::vector<OutObj> &&output_objs) override;
+};
+
+}}
+
+#endif // OPENCV_GAPI_GBACKEND_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpucore.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpucore.cpp
new file mode 100644
index 000000000..c42f863bf
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpucore.cpp
@@ -0,0 +1,595 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/core.hpp"
+#include "opencv2/gapi/cpu/core.hpp"
+#include "backends/cpu/gcpucore.hpp"
+
+GAPI_OCV_KERNEL(GCPUAdd, cv::gapi::core::GAdd)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, int dtype, cv::Mat& out)
+ {
+ cv::add(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUAddC, cv::gapi::core::GAddC)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, int dtype, cv::Mat& out)
+ {
+ cv::add(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUSub, cv::gapi::core::GSub)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, int dtype, cv::Mat& out)
+ {
+ cv::subtract(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUSubC, cv::gapi::core::GSubC)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, int dtype, cv::Mat& out)
+ {
+ cv::subtract(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUSubRC, cv::gapi::core::GSubRC)
+{
+ static void run(const cv::Scalar& a, const cv::Mat& b, int dtype, cv::Mat& out)
+ {
+ cv::subtract(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMul, cv::gapi::core::GMul)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, double scale, int dtype, cv::Mat& out)
+ {
+ cv::multiply(a, b, out, scale, dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMulCOld, cv::gapi::core::GMulCOld)
+{
+ static void run(const cv::Mat& a, double b, int dtype, cv::Mat& out)
+ {
+ cv::multiply(a, b, out, 1, dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMulC, cv::gapi::core::GMulC)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, int dtype, cv::Mat& out)
+ {
+ cv::multiply(a, b, out, 1, dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUDiv, cv::gapi::core::GDiv)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, double scale, int dtype, cv::Mat& out)
+ {
+ cv::divide(a, b, out, scale, dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUDivC, cv::gapi::core::GDivC)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, double scale, int dtype, cv::Mat& out)
+ {
+ cv::divide(a, b, out, scale, dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUDivRC, cv::gapi::core::GDivRC)
+{
+ static void run(const cv::Scalar& a, const cv::Mat& b, double scale, int dtype, cv::Mat& out)
+ {
+ cv::divide(a, b, out, scale, dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMask, cv::gapi::core::GMask)
+{
+ static void run(const cv::Mat& in, const cv::Mat& mask, cv::Mat& out)
+ {
+ out = cv::Mat::zeros(in.size(), in.type());
+ in.copyTo(out, mask);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMean, cv::gapi::core::GMean)
+{
+ static void run(const cv::Mat& in, cv::Scalar& out)
+ {
+ out = cv::mean(in);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUPolarToCart, cv::gapi::core::GPolarToCart)
+{
+ static void run(const cv::Mat& magn, const cv::Mat& angle, bool angleInDegrees, cv::Mat& outx, cv::Mat& outy)
+ {
+ cv::polarToCart(magn, angle, outx, outy, angleInDegrees);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCartToPolar, cv::gapi::core::GCartToPolar)
+{
+ static void run(const cv::Mat& x, const cv::Mat& y, bool angleInDegrees, cv::Mat& outmagn, cv::Mat& outangle)
+ {
+ cv::cartToPolar(x, y, outmagn, outangle, angleInDegrees);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUPhase, cv::gapi::core::GPhase)
+{
+ static void run(const cv::Mat &x, const cv::Mat &y, bool angleInDegrees, cv::Mat &out)
+ {
+ cv::phase(x, y, out, angleInDegrees);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpGT, cv::gapi::core::GCmpGT)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_GT);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpGE, cv::gapi::core::GCmpGE)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_GE);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpLE, cv::gapi::core::GCmpLE)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_LE);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpLT, cv::gapi::core::GCmpLT)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_LT);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpEQ, cv::gapi::core::GCmpEQ)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_EQ);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpNE, cv::gapi::core::GCmpNE)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_NE);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpGTScalar, cv::gapi::core::GCmpGTScalar)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_GT);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpGEScalar, cv::gapi::core::GCmpGEScalar)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_GE);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpLEScalar, cv::gapi::core::GCmpLEScalar)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_LE);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpLTScalar, cv::gapi::core::GCmpLTScalar)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_LT);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpEQScalar, cv::gapi::core::GCmpEQScalar)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_EQ);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCmpNEScalar, cv::gapi::core::GCmpNEScalar)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, cv::Mat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_NE);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUAnd, cv::gapi::core::GAnd)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
+ {
+ cv::bitwise_and(a, b, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUAndS, cv::gapi::core::GAndS)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, cv::Mat& out)
+ {
+ cv::bitwise_and(a, b, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUOr, cv::gapi::core::GOr)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
+ {
+ cv::bitwise_or(a, b, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUOrS, cv::gapi::core::GOrS)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, cv::Mat& out)
+ {
+ cv::bitwise_or(a, b, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUXor, cv::gapi::core::GXor)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
+ {
+ cv::bitwise_xor(a, b, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUXorS, cv::gapi::core::GXorS)
+{
+ static void run(const cv::Mat& a, const cv::Scalar& b, cv::Mat& out)
+ {
+ cv::bitwise_xor(a, b, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUNot, cv::gapi::core::GNot)
+{
+ static void run(const cv::Mat& a, cv::Mat& out)
+ {
+ cv::bitwise_not(a, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUSelect, cv::gapi::core::GSelect)
+{
+ static void run(const cv::Mat& src1, const cv::Mat& src2, const cv::Mat& mask, cv::Mat& out)
+ {
+ src2.copyTo(out);
+ src1.copyTo(out, mask);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMin, cv::gapi::core::GMin)
+{
+ static void run(const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out)
+ {
+ out = cv::min(in1, in2);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMax, cv::gapi::core::GMax)
+{
+ static void run(const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out)
+ {
+ out = cv::max(in1, in2);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUAbsDiff, cv::gapi::core::GAbsDiff)
+{
+ static void run(const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out)
+ {
+ cv::absdiff(in1, in2, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUAbsDiffC, cv::gapi::core::GAbsDiffC)
+{
+ static void run(const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out)
+ {
+ cv::absdiff(in1, in2, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUSum, cv::gapi::core::GSum)
+{
+ static void run(const cv::Mat& in, cv::Scalar& out)
+ {
+ out = cv::sum(in);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUAddW, cv::gapi::core::GAddW)
+{
+ static void run(const cv::Mat& in1, double alpha, const cv::Mat& in2, double beta, double gamma, int dtype, cv::Mat& out)
+ {
+ cv::addWeighted(in1, alpha, in2, beta, gamma, out, dtype);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUNormL1, cv::gapi::core::GNormL1)
+{
+ static void run(const cv::Mat& in, cv::Scalar& out)
+ {
+ out = cv::norm(in, cv::NORM_L1);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUNormL2, cv::gapi::core::GNormL2)
+{
+ static void run(const cv::Mat& in, cv::Scalar& out)
+ {
+ out = cv::norm(in, cv::NORM_L2);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUNormInf, cv::gapi::core::GNormInf)
+{
+ static void run(const cv::Mat& in, cv::Scalar& out)
+ {
+ out = cv::norm(in, cv::NORM_INF);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUIntegral, cv::gapi::core::GIntegral)
+{
+ static void run(const cv::Mat& in, int sdepth, int sqdepth, cv::Mat& out, cv::Mat& outSq)
+ {
+ cv::integral(in, out, outSq, sdepth, sqdepth);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUThreshold, cv::gapi::core::GThreshold)
+{
+ static void run(const cv::Mat& in, const cv::Scalar& a, const cv::Scalar& b, int type, cv::Mat& out)
+ {
+ cv::threshold(in, out, a.val[0], b.val[0], type);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUThresholdOT, cv::gapi::core::GThresholdOT)
+{
+ static void run(const cv::Mat& in, const cv::Scalar& b, int type, cv::Mat& out, cv::Scalar& outScalar)
+ {
+ outScalar = cv::threshold(in, out, b.val[0], b.val[0], type);
+ }
+};
+
+
+GAPI_OCV_KERNEL(GCPUInRange, cv::gapi::core::GInRange)
+{
+ static void run(const cv::Mat& in, const cv::Scalar& low, const cv::Scalar& up, cv::Mat& out)
+ {
+ cv::inRange(in, low, up, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUSplit3, cv::gapi::core::GSplit3)
+{
+ static void run(const cv::Mat& in, cv::Mat &m1, cv::Mat &m2, cv::Mat &m3)
+ {
+ std::vector<cv::Mat> outMats = {m1, m2, m3};
+ cv::split(in, outMats);
+
+ // Write back FIXME: Write a helper or avoid this nonsence completely!
+ m1 = outMats[0];
+ m2 = outMats[1];
+ m3 = outMats[2];
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUSplit4, cv::gapi::core::GSplit4)
+{
+ static void run(const cv::Mat& in, cv::Mat &m1, cv::Mat &m2, cv::Mat &m3, cv::Mat &m4)
+ {
+ std::vector<cv::Mat> outMats = {m1, m2, m3, m4};
+ cv::split(in, outMats);
+
+ // Write back FIXME: Write a helper or avoid this nonsence completely!
+ m1 = outMats[0];
+ m2 = outMats[1];
+ m3 = outMats[2];
+ m4 = outMats[3];
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMerge3, cv::gapi::core::GMerge3)
+{
+ static void run(const cv::Mat& in1, const cv::Mat& in2, const cv::Mat& in3, cv::Mat &out)
+ {
+ std::vector<cv::Mat> inMats = {in1, in2, in3};
+ cv::merge(inMats, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMerge4, cv::gapi::core::GMerge4)
+{
+ static void run(const cv::Mat& in1, const cv::Mat& in2, const cv::Mat& in3, const cv::Mat& in4, cv::Mat &out)
+ {
+ std::vector<cv::Mat> inMats = {in1, in2, in3, in4};
+ cv::merge(inMats, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUResize, cv::gapi::core::GResize)
+{
+ static void run(const cv::Mat& in, cv::Size sz, double fx, double fy, int interp, cv::Mat &out)
+ {
+ cv::resize(in, out, sz, fx, fy, interp);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPURemap, cv::gapi::core::GRemap)
+{
+ static void run(const cv::Mat& in, const cv::Mat& x, const cv::Mat& y, int a, int b, cv::Scalar s, cv::Mat& out)
+ {
+ cv::remap(in, out, x, y, a, b, s);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUFlip, cv::gapi::core::GFlip)
+{
+ static void run(const cv::Mat& in, int code, cv::Mat& out)
+ {
+ cv::flip(in, out, code);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCrop, cv::gapi::core::GCrop)
+{
+ static void run(const cv::Mat& in, cv::Rect rect, cv::Mat& out)
+ {
+ cv::Mat(in, rect).copyTo(out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUConcatHor, cv::gapi::core::GConcatHor)
+{
+ static void run(const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out)
+ {
+ cv::hconcat(in1, in2, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUConcatVert, cv::gapi::core::GConcatVert)
+{
+ static void run(const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out)
+ {
+ cv::vconcat(in1, in2, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPULUT, cv::gapi::core::GLUT)
+{
+ static void run(const cv::Mat& in, const cv::Mat& lut, cv::Mat& out)
+ {
+ cv::LUT(in, lut, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUConvertTo, cv::gapi::core::GConvertTo)
+{
+ static void run(const cv::Mat& in, int rtype, double alpha, double beta, cv::Mat& out)
+ {
+ in.convertTo(out, rtype, alpha, beta);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUSqrt, cv::gapi::core::GSqrt)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::sqrt(in, out);
+ }
+};
+
+cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
+{
+ static auto pkg = cv::gapi::kernels
+ < GCPUAdd
+ , GCPUAddC
+ , GCPUSub
+ , GCPUSubC
+ , GCPUSubRC
+ , GCPUMul
+ , GCPUMulC
+ , GCPUMulCOld
+ , GCPUDiv
+ , GCPUDivC
+ , GCPUDivRC
+ , GCPUMean
+ , GCPUMask
+ , GCPUPolarToCart
+ , GCPUCartToPolar
+ , GCPUPhase
+ , GCPUCmpGT
+ , GCPUCmpGE
+ , GCPUCmpLE
+ , GCPUCmpLT
+ , GCPUCmpEQ
+ , GCPUCmpNE
+ , GCPUCmpGTScalar
+ , GCPUCmpGEScalar
+ , GCPUCmpLEScalar
+ , GCPUCmpLTScalar
+ , GCPUCmpEQScalar
+ , GCPUCmpNEScalar
+ , GCPUAnd
+ , GCPUAndS
+ , GCPUOr
+ , GCPUOrS
+ , GCPUXor
+ , GCPUXorS
+ , GCPUNot
+ , GCPUSelect
+ , GCPUMin
+ , GCPUMax
+ , GCPUAbsDiff
+ , GCPUAbsDiffC
+ , GCPUSum
+ , GCPUAddW
+ , GCPUNormL1
+ , GCPUNormL2
+ , GCPUNormInf
+ , GCPUIntegral
+ , GCPUThreshold
+ , GCPUThresholdOT
+ , GCPUInRange
+ , GCPUSplit3
+ , GCPUSplit4
+ , GCPUResize
+ , GCPUMerge3
+ , GCPUMerge4
+ , GCPURemap
+ , GCPUFlip
+ , GCPUCrop
+ , GCPUConcatHor
+ , GCPUConcatVert
+ , GCPULUT
+ , GCPUConvertTo
+ , GCPUSqrt
+ >();
+ return pkg;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpucore.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpucore.hpp
new file mode 100644
index 000000000..77e9e82a0
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpucore.hpp
@@ -0,0 +1,24 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCPUCORE_HPP
+#define OPENCV_GAPI_GCPUCORE_HPP
+
+#include <map>
+#include <string>
+
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+
+namespace cv { namespace gimpl {
+
+// NB: This is what a "Kernel Package" from the original Wiki doc should be.
+void loadCPUCore(std::map<std::string, cv::GCPUKernel> &kmap);
+
+}
+}
+
+#endif // OPENCV_GAPI_GCPUCORE_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuimgproc.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuimgproc.cpp
new file mode 100644
index 000000000..d14584bfa
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuimgproc.cpp
@@ -0,0 +1,273 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/imgproc.hpp"
+#include "opencv2/gapi/cpu/imgproc.hpp"
+#include "backends/cpu/gcpuimgproc.hpp"
+
+GAPI_OCV_KERNEL(GCPUSepFilter, cv::gapi::imgproc::GSepFilter)
+{
+ static void run(const cv::Mat& in, int ddepth, const cv::Mat& kernX, const cv::Mat& kernY, const cv::Point& anchor, const cv::Scalar& delta,
+ int border, const cv::Scalar& bordVal, cv::Mat &out)
+ {
+ if( border == cv::BORDER_CONSTANT )
+ {
+ cv::Mat temp_in;
+ int width_add = (kernY.cols - 1) / 2;
+ int height_add = (kernX.rows - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, border, bordVal);
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::sepFilter2D(temp_in(rect), out, ddepth, kernX, kernY, anchor, delta.val[0], border);
+ }
+ else
+ cv::sepFilter2D(in, out, ddepth, kernX, kernY, anchor, delta.val[0], border);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUBoxFilter, cv::gapi::imgproc::GBoxFilter)
+{
+ static void run(const cv::Mat& in, int ddepth, const cv::Size& ksize, const cv::Point& anchor, bool normalize, int borderType, const cv::Scalar& bordVal, cv::Mat &out)
+ {
+ if( borderType == cv::BORDER_CONSTANT )
+ {
+ cv::Mat temp_in;
+ int width_add = (ksize.width - 1) / 2;
+ int height_add = (ksize.height - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, borderType, bordVal);
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::boxFilter(temp_in(rect), out, ddepth, ksize, anchor, normalize, borderType);
+ }
+ else
+ cv::boxFilter(in, out, ddepth, ksize, anchor, normalize, borderType);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUBlur, cv::gapi::imgproc::GBlur)
+{
+ static void run(const cv::Mat& in, const cv::Size& ksize, const cv::Point& anchor, int borderType, const cv::Scalar& bordVal, cv::Mat &out)
+ {
+ if( borderType == cv::BORDER_CONSTANT )
+ {
+ cv::Mat temp_in;
+ int width_add = (ksize.width - 1) / 2;
+ int height_add = (ksize.height - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, borderType, bordVal);
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::blur(temp_in(rect), out, ksize, anchor, borderType);
+ }
+ else
+ cv::blur(in, out, ksize, anchor, borderType);
+ }
+};
+
+
+GAPI_OCV_KERNEL(GCPUFilter2D, cv::gapi::imgproc::GFilter2D)
+{
+ static void run(const cv::Mat& in, int ddepth, const cv::Mat& k, const cv::Point& anchor, const cv::Scalar& delta, int border,
+ const cv::Scalar& bordVal, cv::Mat &out)
+ {
+ if( border == cv::BORDER_CONSTANT )
+ {
+ cv::Mat temp_in;
+ int width_add = (k.cols - 1) / 2;
+ int height_add = (k.rows - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, border, bordVal );
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::filter2D(temp_in(rect), out, ddepth, k, anchor, delta.val[0], border);
+ }
+ else
+ cv::filter2D(in, out, ddepth, k, anchor, delta.val[0], border);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUGaussBlur, cv::gapi::imgproc::GGaussBlur)
+{
+ static void run(const cv::Mat& in, const cv::Size& ksize, double sigmaX, double sigmaY, int borderType, const cv::Scalar& bordVal, cv::Mat &out)
+ {
+ if( borderType == cv::BORDER_CONSTANT )
+ {
+ cv::Mat temp_in;
+ int width_add = (ksize.width - 1) / 2;
+ int height_add = (ksize.height - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, borderType, bordVal );
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::GaussianBlur(temp_in(rect), out, ksize, sigmaX, sigmaY, borderType);
+ }
+ else
+ cv::GaussianBlur(in, out, ksize, sigmaX, sigmaY, borderType);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUMedianBlur, cv::gapi::imgproc::GMedianBlur)
+{
+ static void run(const cv::Mat& in, int ksize, cv::Mat &out)
+ {
+ cv::medianBlur(in, out, ksize);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUErode, cv::gapi::imgproc::GErode)
+{
+ static void run(const cv::Mat& in, const cv::Mat& kernel, const cv::Point& anchor, int iterations, int borderType, const cv::Scalar& borderValue, cv::Mat &out)
+ {
+ cv::erode(in, out, kernel, anchor, iterations, borderType, borderValue);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUDilate, cv::gapi::imgproc::GDilate)
+{
+ static void run(const cv::Mat& in, const cv::Mat& kernel, const cv::Point& anchor, int iterations, int borderType, const cv::Scalar& borderValue, cv::Mat &out)
+ {
+ cv::dilate(in, out, kernel, anchor, iterations, borderType, borderValue);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUSobel, cv::gapi::imgproc::GSobel)
+{
+ static void run(const cv::Mat& in, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType,
+ const cv::Scalar& bordVal, cv::Mat &out)
+ {
+ if( borderType == cv::BORDER_CONSTANT )
+ {
+ cv::Mat temp_in;
+ int add = (ksize - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, add, add, add, add, borderType, bordVal );
+ cv::Rect rect = cv::Rect(add, add, in.cols, in.rows);
+ cv::Sobel(temp_in(rect), out, ddepth, dx, dy, ksize, scale, delta, borderType);
+ }
+ else
+ cv::Sobel(in, out, ddepth, dx, dy, ksize, scale, delta, borderType);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUEqualizeHist, cv::gapi::imgproc::GEqHist)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::equalizeHist(in, out);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUCanny, cv::gapi::imgproc::GCanny)
+{
+ static void run(const cv::Mat& in, double thr1, double thr2, int apSize, bool l2gradient, cv::Mat &out)
+ {
+ cv::Canny(in, out, thr1, thr2, apSize, l2gradient);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPURGB2YUV, cv::gapi::imgproc::GRGB2YUV)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_RGB2YUV);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUYUV2RGB, cv::gapi::imgproc::GYUV2RGB)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_YUV2RGB);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPURGB2Lab, cv::gapi::imgproc::GRGB2Lab)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_RGB2Lab);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUBGR2LUV, cv::gapi::imgproc::GBGR2LUV)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_BGR2Luv);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUBGR2YUV, cv::gapi::imgproc::GBGR2YUV)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_BGR2YUV);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPULUV2BGR, cv::gapi::imgproc::GLUV2BGR)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_Luv2BGR);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUYUV2BGR, cv::gapi::imgproc::GYUV2BGR)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_YUV2BGR);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPURGB2Gray, cv::gapi::imgproc::GRGB2Gray)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_RGB2GRAY);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUBGR2Gray, cv::gapi::imgproc::GBGR2Gray)
+{
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_BGR2GRAY);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPURGB2GrayCustom, cv::gapi::imgproc::GRGB2GrayCustom)
+{
+ static void run(const cv::Mat& in, float rY, float bY, float gY, cv::Mat &out)
+ {
+ cv::Mat planes[3];
+ cv::split(in, planes);
+ out = planes[0]*rY + planes[1]*bY + planes[2]*gY;
+ }
+};
+
+cv::gapi::GKernelPackage cv::gapi::imgproc::cpu::kernels()
+{
+ static auto pkg = cv::gapi::kernels
+ < GCPUFilter2D
+ , GCPUSepFilter
+ , GCPUBoxFilter
+ , GCPUBlur
+ , GCPUGaussBlur
+ , GCPUMedianBlur
+ , GCPUErode
+ , GCPUDilate
+ , GCPUSobel
+ , GCPUCanny
+ , GCPUEqualizeHist
+ , GCPURGB2YUV
+ , GCPUYUV2RGB
+ , GCPURGB2Lab
+ , GCPUBGR2LUV
+ , GCPUBGR2YUV
+ , GCPUYUV2BGR
+ , GCPULUV2BGR
+ , GCPUBGR2Gray
+ , GCPURGB2Gray
+ , GCPURGB2GrayCustom
+ >();
+ return pkg;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuimgproc.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuimgproc.hpp
new file mode 100644
index 000000000..172871a77
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpuimgproc.hpp
@@ -0,0 +1,23 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCPUIMGPROC_HPP
+#define OPENCV_GAPI_GCPUIMGPROC_HPP
+
+#include <map>
+#include <string>
+
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+
+namespace cv { namespace gimpl {
+
+// NB: This is what a "Kernel Package" from the origianl Wiki doc should be.
+void loadCPUImgProc(std::map<std::string, cv::GCPUKernel> &kmap);
+
+}}
+
+#endif // OPENCV_GAPI_GCPUIMGPROC_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpukernel.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpukernel.cpp
new file mode 100644
index 000000000..af13eed6c
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/cpu/gcpukernel.cpp
@@ -0,0 +1,52 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <cassert>
+
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+
+const cv::gapi::own::Mat& cv::GCPUContext::inMat(int input)
+{
+ return inArg<cv::gapi::own::Mat>(input);
+}
+
+cv::gapi::own::Mat& cv::GCPUContext::outMatR(int output)
+{
+ return *util::get<cv::gapi::own::Mat*>(m_results.at(output));
+}
+
+const cv::gapi::own::Scalar& cv::GCPUContext::inVal(int input)
+{
+ return inArg<cv::gapi::own::Scalar>(input);
+}
+
+cv::gapi::own::Scalar& cv::GCPUContext::outValR(int output)
+{
+ return *util::get<cv::gapi::own::Scalar*>(m_results.at(output));
+}
+
+cv::detail::VectorRef& cv::GCPUContext::outVecRef(int output)
+{
+ return util::get<cv::detail::VectorRef>(m_results.at(output));
+}
+
+cv::GCPUKernel::GCPUKernel()
+{
+}
+
+cv::GCPUKernel::GCPUKernel(const GCPUKernel::F &f)
+ : m_f(f)
+{
+}
+
+void cv::GCPUKernel::apply(GCPUContext &ctx)
+{
+ GAPI_Assert(m_f);
+ m_f(ctx);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.cpp
new file mode 100644
index 000000000..e6eaaae8c
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.cpp
@@ -0,0 +1,1383 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <functional>
+#include <iostream>
+#include <iomanip> // std::fixed, std::setprecision
+#include <unordered_set>
+#include <stack>
+
+#include <ade/util/algorithm.hpp>
+#include <ade/util/chain_range.hpp>
+#include <ade/util/range.hpp>
+#include <ade/util/zip_range.hpp>
+
+#include <ade/typed_graph.hpp>
+#include <ade/execution_engine/execution_engine.hpp>
+
+#include "opencv2/gapi/gcommon.hpp"
+#include "logger.hpp"
+
+#include "opencv2/gapi/own/convert.hpp"
+#include "opencv2/gapi/gmat.hpp" //for version of descr_of
+// PRIVATE STUFF!
+#include "compiler/gobjref.hpp"
+#include "compiler/gmodel.hpp"
+
+#include "backends/fluid/gfluidbuffer_priv.hpp"
+#include "backends/fluid/gfluidbackend.hpp"
+
+#include "api/gbackend_priv.hpp" // FIXME: Make it part of Backend SDK!
+
+// FIXME: Is there a way to take a typed graph (our GModel),
+// and create a new typed graph _ATOP_ of that (by extending with a couple of
+// new types?).
+// Alternatively, is there a way to compose types graphs?
+//
+// If not, we need to introduce that!
+using GFluidModel = ade::TypedGraph
+ < cv::gimpl::FluidUnit
+ , cv::gimpl::FluidData
+ , cv::gimpl::Protocol
+ , cv::gimpl::FluidUseOwnBorderBuffer
+ >;
+
+// FIXME: Same issue with Typed and ConstTyped
+using GConstFluidModel = ade::ConstTypedGraph
+ < cv::gimpl::FluidUnit
+ , cv::gimpl::FluidData
+ , cv::gimpl::Protocol
+ , cv::gimpl::FluidUseOwnBorderBuffer
+ >;
+
+// FluidBackend middle-layer implementation ////////////////////////////////////
+namespace
+{
+ class GFluidBackendImpl final: public cv::gapi::GBackend::Priv
+ {
+ virtual void unpackKernel(ade::Graph &graph,
+ const ade::NodeHandle &op_node,
+ const cv::GKernelImpl &impl) override
+ {
+ GFluidModel fm(graph);
+ auto fluid_impl = cv::util::any_cast<cv::GFluidKernel>(impl.opaque);
+ fm.metadata(op_node).set(cv::gimpl::FluidUnit{fluid_impl, {}, 0, 0, 0.0});
+ }
+
+ virtual EPtr compile(const ade::Graph &graph,
+ const cv::GCompileArgs &args,
+ const std::vector<ade::NodeHandle> &nodes) const override
+ {
+ using namespace cv::gimpl;
+ GModel::ConstGraph g(graph);
+ auto isl_graph = g.metadata().get<IslandModel>().model;
+ GIslandModel::Graph gim(*isl_graph);
+
+ const auto num_islands = std::count_if
+ (gim.nodes().begin(), gim.nodes().end(),
+ [&](const ade::NodeHandle &nh) {
+ return gim.metadata(nh).get<NodeKind>().k == NodeKind::ISLAND;
+ });
+
+ const auto out_rois = cv::gimpl::getCompileArg<cv::GFluidOutputRois>(args);
+ if (num_islands > 1 && out_rois.has_value())
+ cv::util::throw_error(std::logic_error("GFluidOutputRois feature supports only one-island graphs"));
+
+ auto rois = out_rois.value_or(cv::GFluidOutputRois());
+ return EPtr{new cv::gimpl::GFluidExecutable(graph, nodes, std::move(rois.rois))};
+ }
+
+ virtual void addBackendPasses(ade::ExecutionEngineSetupContext &ectx) override;
+
+ };
+}
+
+cv::gapi::GBackend cv::gapi::fluid::backend()
+{
+ static cv::gapi::GBackend this_backend(std::make_shared<GFluidBackendImpl>());
+ return this_backend;
+}
+
+// FluidAgent implementation ///////////////////////////////////////////////////
+
+namespace cv { namespace gimpl {
+struct FluidMapper
+{
+ FluidMapper(double ratio, int lpi) : m_ratio(ratio), m_lpi(lpi) {}
+ virtual ~FluidMapper() = default;
+ virtual int firstWindow(int outCoord, int lpi) const = 0;
+ virtual std::pair<int,int> linesReadAndNextWindow(int outCoord, int lpi) const = 0;
+
+protected:
+ double m_ratio = 0.0;
+ int m_lpi = 0;
+};
+
+struct FluidDownscaleMapper : public FluidMapper
+{
+ virtual int firstWindow(int outCoord, int lpi) const override;
+ virtual std::pair<int,int> linesReadAndNextWindow(int outCoord, int lpi) const override;
+ using FluidMapper::FluidMapper;
+};
+
+struct FluidUpscaleMapper : public FluidMapper
+{
+ virtual int firstWindow(int outCoord, int lpi) const override;
+ virtual std::pair<int,int> linesReadAndNextWindow(int outCoord, int lpi) const override;
+ FluidUpscaleMapper(double ratio, int lpi, int inHeight) : FluidMapper(ratio, lpi), m_inHeight(inHeight) {}
+private:
+ int m_inHeight = 0;
+};
+
+struct FluidFilterAgent : public FluidAgent
+{
+private:
+ virtual int firstWindow() const override;
+ virtual std::pair<int,int> linesReadAndnextWindow() const override;
+ virtual void setRatio(double) override { /* nothing */ }
+public:
+ using FluidAgent::FluidAgent;
+};
+
+struct FluidResizeAgent : public FluidAgent
+{
+private:
+ virtual int firstWindow() const override;
+ virtual std::pair<int,int> linesReadAndnextWindow() const override;
+ virtual void setRatio(double ratio) override;
+
+ std::unique_ptr<FluidMapper> m_mapper;
+public:
+ using FluidAgent::FluidAgent;
+};
+}} // namespace cv::gimpl
+
+cv::gimpl::FluidAgent::FluidAgent(const ade::Graph &g, ade::NodeHandle nh)
+ : k(GConstFluidModel(g).metadata(nh).get<FluidUnit>().k) // init(0)
+ , op_handle(nh) // init(1)
+ , op_name(GModel::ConstGraph(g).metadata(nh).get<Op>().k.name) // init(2)
+{
+ std::set<int> out_w;
+ std::set<int> out_h;
+ GModel::ConstGraph cm(g);
+ for (auto out_data : nh->outNodes())
+ {
+ const auto &d = cm.metadata(out_data).get<Data>();
+ cv::GMatDesc d_meta = cv::util::get<cv::GMatDesc>(d.meta);
+ out_w.insert(d_meta.size.width);
+ out_h.insert(d_meta.size.height);
+ }
+
+ // Different output sizes are not supported
+ GAPI_Assert(out_w.size() == 1 && out_h.size() == 1);
+}
+
+void cv::gimpl::FluidAgent::reset()
+{
+ m_producedLines = 0;
+
+ auto lines = firstWindow();
+ for (auto &v : in_views)
+ {
+ if (v)
+ {
+ v.priv().reset(lines);
+ }
+ }
+}
+
+namespace {
+static int calcGcd (int n1, int n2)
+{
+ return (n2 == 0) ? n1 : calcGcd (n2, n1 % n2);
+}
+
+// This is an empiric formula and this is not 100% guaranteed
+// that it produces correct results in all possible cases
+// FIXME:
+// prove correctness or switch to some trusted method
+//
+// When performing resize input/output pixels form a cyclic
+// pattern where inH/gcd input pixels are mapped to outH/gcd
+// output pixels (pattern repeats gcd times).
+//
+// Output pixel can partually cover some of the input pixels.
+// There are 3 possible cases:
+//
+// :___ ___: :___ _:_ ___: :___ __: ___ :__ ___:
+// |___|___| |___|_:_|___| |___|__:|___|:__|___|
+// : : : : : : : : :
+//
+// 1) No partial coverage, max window = scaleFactor;
+// 2) Partial coverage occurs on the one side of the output pixel,
+// max window = scaleFactor + 1;
+// 3) Partial coverage occurs at both sides of the output pixel,
+// max window = scaleFactor + 2;
+//
+// Type of the coverage is determined by remainder of
+// inPeriodH/outPeriodH division, but it's an heuristic
+// (howbeit didn't found the proof of the opposite so far).
+
+static int calcResizeWindow(int inH, int outH)
+{
+ GAPI_Assert(inH >= outH);
+ auto gcd = calcGcd(inH, outH);
+ int inPeriodH = inH/gcd;
+ int outPeriodH = outH/gcd;
+ int scaleFactor = inPeriodH / outPeriodH;
+
+ switch ((inPeriodH) % (outPeriodH))
+ {
+ case 0: return scaleFactor; break;
+ case 1: return scaleFactor + 1; break;
+ default: return scaleFactor + 2;
+ }
+}
+
+static int maxLineConsumption(const cv::GFluidKernel& k, int inH, int outH, int lpi)
+{
+ switch (k.m_kind)
+ {
+ case cv::GFluidKernel::Kind::Filter: return k.m_window + lpi - 1; break;
+ case cv::GFluidKernel::Kind::Resize:
+ {
+ if (inH >= outH)
+ {
+ // FIXME:
+ // This is a suboptimal value, can be reduced
+ return calcResizeWindow(inH, outH) * lpi;
+ }
+ else
+ {
+ // FIXME:
+ // This is a suboptimal value, can be reduced
+ return (inH == 1) ? 1 : 2 + lpi - 1;
+ }
+ } break;
+ default: GAPI_Assert(false); return 0;
+ }
+}
+
+static int borderSize(const cv::GFluidKernel& k)
+{
+ switch (k.m_kind)
+ {
+ case cv::GFluidKernel::Kind::Filter: return (k.m_window - 1) / 2; break;
+ // Resize never reads from border pixels
+ case cv::GFluidKernel::Kind::Resize: return 0; break;
+ default: GAPI_Assert(false); return 0;
+ }
+}
+
+inline double inCoord(int outIdx, double ratio)
+{
+ return outIdx * ratio;
+}
+
+inline int windowStart(int outIdx, double ratio)
+{
+ return static_cast<int>(inCoord(outIdx, ratio) + 1e-3);
+}
+
+inline int windowEnd(int outIdx, double ratio)
+{
+ return static_cast<int>(std::ceil(inCoord(outIdx + 1, ratio) - 1e-3));
+}
+
+inline double inCoordUpscale(int outCoord, double ratio)
+{
+ // Calculate the projection of output pixel's center
+ return (outCoord + 0.5) * ratio - 0.5;
+}
+
+inline int upscaleWindowStart(int outCoord, double ratio)
+{
+ int start = static_cast<int>(inCoordUpscale(outCoord, ratio));
+ GAPI_DbgAssert(start >= 0);
+ return start;
+}
+
+inline int upscaleWindowEnd(int outCoord, double ratio, int inSz)
+{
+ int end = static_cast<int>(std::ceil(inCoordUpscale(outCoord, ratio)) + 1);
+ if (end > inSz)
+ {
+ end = inSz;
+ }
+ return end;
+}
+} // anonymous namespace
+
+int cv::gimpl::FluidDownscaleMapper::firstWindow(int outCoord, int lpi) const
+{
+ return windowEnd(outCoord + lpi - 1, m_ratio) - windowStart(outCoord, m_ratio);
+}
+
+std::pair<int,int> cv::gimpl::FluidDownscaleMapper::linesReadAndNextWindow(int outCoord, int lpi) const
+{
+ auto nextStartIdx = outCoord + 1 + m_lpi - 1;
+ auto nextEndIdx = nextStartIdx + lpi - 1;
+
+ auto currStart = windowStart(outCoord, m_ratio);
+ auto nextStart = windowStart(nextStartIdx, m_ratio);
+ auto nextEnd = windowEnd(nextEndIdx, m_ratio);
+
+ auto lines_read = nextStart - currStart;
+ auto next_window = nextEnd - nextStart;
+
+ return std::make_pair(lines_read, next_window);
+}
+
+int cv::gimpl::FluidUpscaleMapper::firstWindow(int outCoord, int lpi) const
+{
+ return upscaleWindowEnd(outCoord + lpi - 1, m_ratio, m_inHeight) - upscaleWindowStart(outCoord, m_ratio);
+}
+
+std::pair<int,int> cv::gimpl::FluidUpscaleMapper::linesReadAndNextWindow(int outCoord, int lpi) const
+{
+ auto nextStartIdx = outCoord + 1 + m_lpi - 1;
+ auto nextEndIdx = nextStartIdx + lpi - 1;
+
+ auto currStart = upscaleWindowStart(outCoord, m_ratio);
+ auto nextStart = upscaleWindowStart(nextStartIdx, m_ratio);
+ auto nextEnd = upscaleWindowEnd(nextEndIdx, m_ratio, m_inHeight);
+
+ auto lines_read = nextStart - currStart;
+ auto next_window = nextEnd - nextStart;
+
+ return std::make_pair(lines_read, next_window);
+}
+
+int cv::gimpl::FluidFilterAgent::firstWindow() const
+{
+ return k.m_window + k.m_lpi - 1;
+}
+
+std::pair<int,int> cv::gimpl::FluidFilterAgent::linesReadAndnextWindow() const
+{
+ int lpi = std::min(k.m_lpi, m_outputLines - m_producedLines - k.m_lpi);
+ return std::make_pair(k.m_lpi, k.m_window - 1 + lpi);
+}
+
+int cv::gimpl::FluidResizeAgent::firstWindow() const
+{
+ auto outIdx = out_buffers[0]->priv().y();
+ auto lpi = std::min(m_outputLines - m_producedLines, k.m_lpi);
+ return m_mapper->firstWindow(outIdx, lpi);
+}
+
+std::pair<int,int> cv::gimpl::FluidResizeAgent::linesReadAndnextWindow() const
+{
+ auto outIdx = out_buffers[0]->priv().y();
+ auto lpi = std::min(m_outputLines - m_producedLines - k.m_lpi, k.m_lpi);
+ return m_mapper->linesReadAndNextWindow(outIdx, lpi);
+}
+
+void cv::gimpl::FluidResizeAgent::setRatio(double ratio)
+{
+ if (ratio >= 1.0)
+ {
+ m_mapper.reset(new FluidDownscaleMapper(ratio, k.m_lpi));
+ }
+ else
+ {
+ m_mapper.reset(new FluidUpscaleMapper(ratio, k.m_lpi, in_views[0].meta().size.height));
+ }
+}
+
+bool cv::gimpl::FluidAgent::canRead() const
+{
+ // An agent can work if every input buffer have enough data to start
+ for (const auto& in_view : in_views)
+ {
+ if (in_view)
+ {
+ if (!in_view.ready())
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cv::gimpl::FluidAgent::canWrite() const
+{
+ // An agent can work if there is space to write in its output
+ // allocated buffers
+ GAPI_DbgAssert(!out_buffers.empty());
+ auto out_begin = out_buffers.begin();
+ auto out_end = out_buffers.end();
+ if (k.m_scratch) out_end--;
+ for (auto it = out_begin; it != out_end; ++it)
+ {
+ if ((*it)->priv().full())
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cv::gimpl::FluidAgent::canWork() const
+{
+ return canRead() && canWrite();
+}
+
+void cv::gimpl::FluidAgent::doWork()
+{
+ GAPI_DbgAssert(m_outputLines > m_producedLines);
+ for (auto& in_view : in_views)
+ {
+ if (in_view) in_view.priv().prepareToRead();
+ }
+
+ k.m_f(in_args, out_buffers);
+
+ for (auto& in_view : in_views)
+ {
+ if (in_view)
+ {
+ auto pair = linesReadAndnextWindow();
+ in_view.priv().readDone(pair.first, pair.second);
+ };
+ }
+
+ for (auto out_buf : out_buffers)
+ {
+ out_buf->priv().writeDone();
+ // FIXME WARNING: Scratch buffers rotated here too!
+ }
+
+ m_producedLines += k.m_lpi;
+}
+
+bool cv::gimpl::FluidAgent::done() const
+{
+ // m_producedLines is a multiple of LPI, while original
+ // height may be not.
+ return m_producedLines >= m_outputLines;
+}
+
+void cv::gimpl::FluidAgent::debug(std::ostream &os)
+{
+ os << "Fluid Agent " << std::hex << this
+ << " (" << op_name << ") --"
+ << " canWork=" << std::boolalpha << canWork()
+ << " canRead=" << std::boolalpha << canRead()
+ << " canWrite=" << std::boolalpha << canWrite()
+ << " done=" << done()
+ << " lines=" << std::dec << m_producedLines << "/" << m_outputLines
+ << " {{\n";
+ for (auto out_buf : out_buffers)
+ {
+ out_buf->debug(os);
+ }
+ std::cout << "}}" << std::endl;
+}
+
+// GCPUExcecutable implementation //////////////////////////////////////////////
+
+void cv::gimpl::GFluidExecutable::initBufferRois(std::vector<int>& readStarts,
+ std::vector<cv::gapi::own::Rect>& rois,
+ const std::vector<cv::gapi::own::Rect>& out_rois)
+{
+ GConstFluidModel fg(m_g);
+ auto proto = m_gm.metadata().get<Protocol>();
+ std::stack<ade::NodeHandle> nodesToVisit;
+
+ // FIXME?
+ // There is possible case when user pass the vector full of default Rect{}-s,
+ // Can be diagnosed and handled appropriately
+ if (proto.outputs.size() != out_rois.size())
+ {
+ GAPI_Assert(out_rois.size() == 0);
+ // No inference required, buffers will obtain roi from meta
+ return;
+ }
+
+ // First, initialize rois for output nodes, add them to traversal stack
+ for (const auto& it : ade::util::indexed(proto.out_nhs))
+ {
+ const auto idx = ade::util::index(it);
+ const auto nh = ade::util::value(it);
+
+ const auto &d = m_gm.metadata(nh).get<Data>();
+
+ // This is not our output
+ if (m_id_map.count(d.rc) == 0)
+ {
+ continue;
+ }
+
+ if (d.shape == GShape::GMAT)
+ {
+ auto desc = util::get<GMatDesc>(d.meta);
+ auto id = m_id_map.at(d.rc);
+ readStarts[id] = 0;
+
+ if (out_rois[idx] == gapi::own::Rect{})
+ {
+ rois[id] = gapi::own::Rect{ 0, 0, desc.size.width, desc.size.height };
+ }
+ else
+ {
+ // Only slices are supported at the moment
+ GAPI_Assert(out_rois[idx].x == 0);
+ GAPI_Assert(out_rois[idx].width == desc.size.width);
+ rois[id] = out_rois[idx];
+ }
+
+ nodesToVisit.push(nh);
+ }
+ }
+
+ // Perform a wide search from each of the output nodes
+ // And extend roi of buffers by border_size
+ // Each node can be visited multiple times
+ // (if node has been already visited, the check that inferred rois are the same is performed)
+ while (!nodesToVisit.empty())
+ {
+ const auto startNode = nodesToVisit.top();
+ nodesToVisit.pop();
+
+ if (!startNode->inNodes().empty())
+ {
+ GAPI_Assert(startNode->inNodes().size() == 1);
+ const auto& oh = startNode->inNodes().front();
+
+ const auto& data = m_gm.metadata(startNode).get<Data>();
+ // only GMats participate in the process so it's valid to obtain GMatDesc
+ const auto& meta = util::get<GMatDesc>(data.meta);
+
+ for (const auto& inNode : oh->inNodes())
+ {
+ const auto& in_data = m_gm.metadata(inNode).get<Data>();
+
+ if (in_data.shape == GShape::GMAT && fg.metadata(inNode).contains<FluidData>())
+ {
+ const auto& in_meta = util::get<GMatDesc>(in_data.meta);
+ const auto& fd = fg.metadata(inNode).get<FluidData>();
+
+ auto adjFilterRoi = [](cv::gapi::own::Rect produced, int b, int max_height) {
+ // Extend with border roi which should be produced, crop to logical image size
+ cv::gapi::own::Rect roi = {produced.x, produced.y - b, produced.width, produced.height + 2*b};
+ cv::gapi::own::Rect fullImg{ 0, 0, produced.width, max_height };
+ return roi & fullImg;
+ };
+
+ auto adjResizeRoi = [](cv::gapi::own::Rect produced, cv::gapi::own::Size inSz, cv::gapi::own::Size outSz) {
+ auto map = [](int outCoord, int producedSz, int inSize, int outSize) {
+ double ratio = (double)inSize / outSize;
+ int w0 = 0, w1 = 0;
+ if (ratio >= 1.0)
+ {
+ w0 = windowStart(outCoord, ratio);
+ w1 = windowEnd (outCoord + producedSz - 1, ratio);
+ }
+ else
+ {
+ w0 = upscaleWindowStart(outCoord, ratio);
+ w1 = upscaleWindowEnd(outCoord + producedSz - 1, ratio, inSize);
+ }
+ return std::make_pair(w0, w1);
+ };
+
+ auto mapY = map(produced.y, produced.height, inSz.height, outSz.height);
+ auto y0 = mapY.first;
+ auto y1 = mapY.second;
+
+ auto mapX = map(produced.x, produced.width, inSz.width, outSz.width);
+ auto x0 = mapX.first;
+ auto x1 = mapX.second;
+
+ cv::gapi::own::Rect roi = {x0, y0, x1 - x0, y1 - y0};
+ return roi;
+ };
+
+ cv::gapi::own::Rect produced = rois[m_id_map.at(data.rc)];
+
+ cv::gapi::own::Rect resized;
+ switch (fg.metadata(oh).get<FluidUnit>().k.m_kind)
+ {
+ case GFluidKernel::Kind::Filter: resized = produced; break;
+ case GFluidKernel::Kind::Resize: resized = adjResizeRoi(produced, in_meta.size, meta.size); break;
+ default: GAPI_Assert(false);
+ }
+
+ int readStart = resized.y;
+ cv::gapi::own::Rect roi = adjFilterRoi(resized, fd.border_size, in_meta.size.height);
+
+ auto in_id = m_id_map.at(in_data.rc);
+ if (rois[in_id] == cv::gapi::own::Rect{})
+ {
+ readStarts[in_id] = readStart;
+ rois[in_id] = roi;
+ // Continue traverse on internal (w.r.t Island) data nodes only.
+ if (fd.internal) nodesToVisit.push(inNode);
+ }
+ else
+ {
+ GAPI_Assert(readStarts[in_id] == readStart);
+ GAPI_Assert(rois[in_id] == roi);
+ }
+ } // if (in_data.shape == GShape::GMAT)
+ } // for (const auto& inNode : oh->inNodes())
+ } // if (!startNode->inNodes().empty())
+ } // while (!nodesToVisit.empty())
+}
+
+cv::gimpl::GFluidExecutable::GFluidExecutable(const ade::Graph &g,
+ const std::vector<ade::NodeHandle> &nodes,
+ const std::vector<cv::gapi::own::Rect> &outputRois)
+ : m_g(g), m_gm(m_g)
+{
+ GConstFluidModel fg(m_g);
+
+ // Initialize vector of data buffers, build list of operations
+ // FIXME: There _must_ be a better way to [query] count number of DATA nodes
+ std::size_t mat_count = 0;
+ std::size_t last_agent = 0;
+
+ auto grab_mat_nh = [&](ade::NodeHandle nh) {
+ auto rc = m_gm.metadata(nh).get<Data>().rc;
+ if (m_id_map.count(rc) == 0)
+ {
+ m_all_gmat_ids[mat_count] = nh;
+ m_id_map[rc] = mat_count++;
+ }
+ };
+
+ for (const auto &nh : nodes)
+ {
+ switch (m_gm.metadata(nh).get<NodeType>().t)
+ {
+ case NodeType::DATA:
+ if (m_gm.metadata(nh).get<Data>().shape == GShape::GMAT)
+ grab_mat_nh(nh);
+ break;
+
+ case NodeType::OP:
+ {
+ const auto& fu = fg.metadata(nh).get<FluidUnit>();
+ switch (fu.k.m_kind)
+ {
+ case GFluidKernel::Kind::Filter: m_agents.emplace_back(new FluidFilterAgent(m_g, nh)); break;
+ case GFluidKernel::Kind::Resize: m_agents.emplace_back(new FluidResizeAgent(m_g, nh)); break;
+ default: GAPI_Assert(false);
+ }
+ // NB.: in_buffer_ids size is equal to Arguments size, not Edges size!!!
+ m_agents.back()->in_buffer_ids.resize(m_gm.metadata(nh).get<Op>().args.size(), -1);
+ for (auto eh : nh->inEdges())
+ {
+ // FIXME Only GMats are currently supported (which can be represented
+ // as fluid buffers
+ if (m_gm.metadata(eh->srcNode()).get<Data>().shape == GShape::GMAT)
+ {
+ const auto in_port = m_gm.metadata(eh).get<Input>().port;
+ const int in_buf = m_gm.metadata(eh->srcNode()).get<Data>().rc;
+
+ m_agents.back()->in_buffer_ids[in_port] = in_buf;
+ grab_mat_nh(eh->srcNode());
+ }
+ }
+ // FIXME: Assumption that all operation outputs MUST be connected
+ m_agents.back()->out_buffer_ids.resize(nh->outEdges().size(), -1);
+ for (auto eh : nh->outEdges())
+ {
+ const auto& data = m_gm.metadata(eh->dstNode()).get<Data>();
+ const auto out_port = m_gm.metadata(eh).get<Output>().port;
+ const int out_buf = data.rc;
+
+ m_agents.back()->out_buffer_ids[out_port] = out_buf;
+ if (data.shape == GShape::GMAT) grab_mat_nh(eh->dstNode());
+ }
+ if (fu.k.m_scratch)
+ m_scratch_users.push_back(last_agent);
+ last_agent++;
+ break;
+ }
+ default: GAPI_Assert(false);
+ }
+ }
+
+ // Check that IDs form a continiuos set (important for further indexing)
+ GAPI_Assert(m_id_map.size() > 0);
+ GAPI_Assert(m_id_map.size() == static_cast<size_t>(mat_count));
+
+ // Actually initialize Fluid buffers
+ GAPI_LOG_INFO(NULL, "Initializing " << mat_count << " fluid buffer(s)" << std::endl);
+ m_num_int_buffers = mat_count;
+ const std::size_t num_scratch = m_scratch_users.size();
+ m_buffers.resize(m_num_int_buffers + num_scratch);
+
+ // After buffers are allocated, repack: ...
+ for (auto &agent : m_agents)
+ {
+ // a. Agent input parameters with View pointers (creating Views btw)
+ const auto &op = m_gm.metadata(agent->op_handle).get<Op>();
+ const auto &fu = fg.metadata(agent->op_handle).get<FluidUnit>();
+ agent->in_args.resize(op.args.size());
+ agent->in_views.resize(op.args.size());
+ for (auto it : ade::util::indexed(ade::util::toRange(agent->in_buffer_ids)))
+ {
+ auto in_idx = ade::util::index(it);
+ auto buf_idx = ade::util::value(it);
+
+ if (buf_idx >= 0)
+ {
+ // IF there is input buffer, register a view (every unique
+ // reader has its own), and store it in agent Args
+ gapi::fluid::Buffer &buffer = m_buffers.at(m_id_map.at(buf_idx));
+
+ auto inEdge = GModel::getInEdgeByPort(m_g, agent->op_handle, in_idx);
+ auto ownStorage = fg.metadata(inEdge).get<FluidUseOwnBorderBuffer>().use;
+
+ gapi::fluid::View view = buffer.mkView(fu.border_size, ownStorage);
+ // NB: It is safe to keep ptr as view lifetime is buffer lifetime
+ agent->in_views[in_idx] = view;
+ agent->in_args[in_idx] = GArg(view);
+ }
+ else
+ {
+ // Copy(FIXME!) original args as is
+ agent->in_args[in_idx] = op.args[in_idx];
+ }
+ }
+
+ // b. Agent output parameters with Buffer pointers.
+ agent->out_buffers.resize(agent->op_handle->outEdges().size(), nullptr);
+ for (auto it : ade::util::indexed(ade::util::toRange(agent->out_buffer_ids)))
+ {
+ auto out_idx = ade::util::index(it);
+ auto buf_idx = m_id_map.at(ade::util::value(it));
+ agent->out_buffers.at(out_idx) = &m_buffers.at(buf_idx);
+ }
+ }
+
+ // After parameters are there, initialize scratch buffers
+ if (num_scratch)
+ {
+ GAPI_LOG_INFO(NULL, "Initializing " << num_scratch << " scratch buffer(s)" << std::endl);
+ std::size_t last_scratch_id = 0;
+
+ for (auto i : m_scratch_users)
+ {
+ auto &agent = m_agents.at(i);
+ GAPI_Assert(agent->k.m_scratch);
+ const std::size_t new_scratch_idx = m_num_int_buffers + last_scratch_id;
+ agent->out_buffers.emplace_back(&m_buffers[new_scratch_idx]);
+ last_scratch_id++;
+ }
+ }
+
+ makeReshape(outputRois);
+
+ std::size_t total_size = 0;
+ for (const auto &i : ade::util::indexed(m_buffers))
+ {
+ // Check that all internal and scratch buffers are allocated
+ const auto idx = ade::util::index(i);
+ const auto b = ade::util::value(i);
+ if (idx >= m_num_int_buffers ||
+ fg.metadata(m_all_gmat_ids[idx]).get<FluidData>().internal == true)
+ {
+ GAPI_Assert(b.priv().size() > 0);
+ }
+
+ // Buffers which will be bound to real images may have size of 0 at this moment
+ // (There can be non-zero sized const border buffer allocated in such buffers)
+ total_size += b.priv().size();
+ }
+ GAPI_LOG_INFO(NULL, "Internal buffers: " << std::fixed << std::setprecision(2) << static_cast<float>(total_size)/1024 << " KB\n");
+}
+
+namespace
+{
+ void resetFluidData(ade::Graph& graph)
+ {
+ using namespace cv::gimpl;
+ GModel::Graph g(graph);
+ GFluidModel fg(graph);
+ for (const auto node : g.nodes())
+ {
+ if (g.metadata(node).get<NodeType>().t == NodeType::DATA)
+ {
+ auto& fd = fg.metadata(node).get<FluidData>();
+ fd.latency = 0;
+ fd.skew = 0;
+ fd.max_consumption = 0;
+ }
+ }
+ }
+
+ void initFluidUnits(ade::Graph& graph)
+ {
+ using namespace cv::gimpl;
+ GModel::Graph g(graph);
+ GFluidModel fg(graph);
+
+ auto sorted = g.metadata().get<ade::passes::TopologicalSortData>().nodes();
+ for (auto node : sorted)
+ {
+ if (fg.metadata(node).contains<FluidUnit>())
+ {
+ std::set<int> in_hs, out_ws, out_hs;
+
+ for (const auto& in : node->inNodes())
+ {
+ const auto& d = g.metadata(in).get<Data>();
+ if (d.shape == cv::GShape::GMAT)
+ {
+ const auto& meta = cv::util::get<cv::GMatDesc>(d.meta);
+ in_hs.insert(meta.size.height);
+ }
+ }
+
+ for (const auto& out : node->outNodes())
+ {
+ const auto& d = g.metadata(out).get<Data>();
+ if (d.shape == cv::GShape::GMAT)
+ {
+ const auto& meta = cv::util::get<cv::GMatDesc>(d.meta);
+ out_ws.insert(meta.size.width);
+ out_hs.insert(meta.size.height);
+ }
+ }
+
+ GAPI_Assert(in_hs.size() == 1 && out_ws.size() == 1 && out_hs.size() == 1);
+
+ auto in_h = *in_hs .cbegin();
+ auto out_h = *out_hs.cbegin();
+
+ auto &fu = fg.metadata(node).get<FluidUnit>();
+ fu.ratio = (double)in_h / out_h;
+
+ int line_consumption = maxLineConsumption(fu.k, in_h, out_h, fu.k.m_lpi);
+ int border_size = borderSize(fu.k);
+
+ fu.border_size = border_size;
+ fu.line_consumption = line_consumption;
+
+ GModel::log(g, node, "Line consumption: " + std::to_string(fu.line_consumption));
+ GModel::log(g, node, "Border size: " + std::to_string(fu.border_size));
+ }
+ }
+ }
+
+ // FIXME!
+ // Split into initLineConsumption and initBorderSizes,
+ // call only consumption related stuff during reshape
+ void initLineConsumption(ade::Graph& graph)
+ {
+ using namespace cv::gimpl;
+ GModel::Graph g(graph);
+ GFluidModel fg(graph);
+
+ for (const auto &node : g.nodes())
+ {
+ if (fg.metadata(node).contains<FluidUnit>())
+ {
+ const auto &fu = fg.metadata(node).get<FluidUnit>();
+
+ for (const auto &in_data_node : node->inNodes())
+ {
+ auto &fd = fg.metadata(in_data_node).get<FluidData>();
+
+ // Update (not Set) fields here since a single data node may be
+ // accessed by multiple consumers
+ fd.max_consumption = std::max(fu.line_consumption, fd.max_consumption);
+ fd.border_size = std::max(fu.border_size, fd.border_size);
+
+ GModel::log(g, in_data_node, "Line consumption: " + std::to_string(fd.max_consumption)
+ + " (upd by " + std::to_string(fu.line_consumption) + ")", node);
+ GModel::log(g, in_data_node, "Border size: " + std::to_string(fd.border_size), node);
+ }
+ }
+ }
+ }
+
+ void calcLatency(ade::Graph& graph)
+ {
+ using namespace cv::gimpl;
+ GModel::Graph g(graph);
+ GFluidModel fg(graph);
+
+ auto sorted = g.metadata().get<ade::passes::TopologicalSortData>().nodes();
+ for (const auto &node : sorted)
+ {
+ if (fg.metadata(node).contains<FluidUnit>())
+ {
+ const auto &fu = fg.metadata(node).get<FluidUnit>();
+
+ const int own_latency = fu.line_consumption - fu.border_size;
+ GModel::log(g, node, "LPI: " + std::to_string(fu.k.m_lpi));
+
+ // Output latency is max(input_latency) + own_latency
+ int in_latency = 0;
+ for (const auto &in_data_node : node->inNodes())
+ {
+ // FIXME: ASSERT(DATA), ASSERT(FLUIDDATA)
+ in_latency = std::max(in_latency, fg.metadata(in_data_node).get<FluidData>().latency);
+ }
+ const int out_latency = in_latency + own_latency;
+
+ for (const auto &out_data_node : node->outNodes())
+ {
+ // FIXME: ASSERT(DATA), ASSERT(FLUIDDATA)
+ auto &fd = fg.metadata(out_data_node).get<FluidData>();
+ fd.latency = out_latency;
+ fd.lpi_write = fu.k.m_lpi;
+ GModel::log(g, out_data_node, "Latency: " + std::to_string(out_latency));
+ }
+ }
+ }
+ }
+
+ void calcSkew(ade::Graph& graph)
+ {
+ using namespace cv::gimpl;
+ GModel::Graph g(graph);
+ GFluidModel fg(graph);
+
+ auto sorted = g.metadata().get<ade::passes::TopologicalSortData>().nodes();
+ for (const auto &node : sorted)
+ {
+ if (fg.metadata(node).contains<FluidUnit>())
+ {
+ int max_latency = 0;
+ for (const auto &in_data_node : node->inNodes())
+ {
+ // FIXME: ASSERT(DATA), ASSERT(FLUIDDATA)
+ max_latency = std::max(max_latency, fg.metadata(in_data_node).get<FluidData>().latency);
+ }
+ for (const auto &in_data_node : node->inNodes())
+ {
+ // FIXME: ASSERT(DATA), ASSERT(FLUIDDATA)
+ auto &fd = fg.metadata(in_data_node).get<FluidData>();
+
+ // Update (not Set) fields here since a single data node may be
+ // accessed by multiple consumers
+ fd.skew = std::max(fd.skew, max_latency - fd.latency);
+
+ GModel::log(g, in_data_node, "Skew: " + std::to_string(fd.skew), node);
+ }
+ }
+ }
+ }
+}
+
+void cv::gimpl::GFluidExecutable::makeReshape(const std::vector<gapi::own::Rect> &out_rois)
+{
+ GConstFluidModel fg(m_g);
+
+ // Calculate rois for each fluid buffer
+ std::vector<int> readStarts(m_num_int_buffers);
+ std::vector<cv::gapi::own::Rect> rois(m_num_int_buffers);
+ initBufferRois(readStarts, rois, out_rois);
+
+ // NB: Allocate ALL buffer object at once, and avoid any further reallocations
+ // (since raw pointers-to-elements are taken)
+ for (const auto &it : m_all_gmat_ids)
+ {
+ auto id = it.first;
+ auto nh = it.second;
+ const auto & d = m_gm.metadata(nh).get<Data>();
+ const auto &fd = fg.metadata(nh).get<FluidData>();
+ const auto meta = cv::util::get<GMatDesc>(d.meta);
+
+ m_buffers[id].priv().init(meta, fd.lpi_write, readStarts[id], rois[id]);
+
+ // TODO:
+ // Introduce Storage::INTERNAL_GRAPH and Storage::INTERNAL_ISLAND?
+ if (fd.internal == true)
+ {
+ m_buffers[id].priv().allocate(fd.border, fd.border_size, fd.max_consumption, fd.skew);
+ std::stringstream stream;
+ m_buffers[id].debug(stream);
+ GAPI_LOG_INFO(NULL, stream.str());
+ }
+ }
+
+ // Allocate views, initialize agents
+ for (auto &agent : m_agents)
+ {
+ const auto &fu = fg.metadata(agent->op_handle).get<FluidUnit>();
+ for (auto it : ade::util::indexed(ade::util::toRange(agent->in_buffer_ids)))
+ {
+ auto in_idx = ade::util::index(it);
+ auto buf_idx = ade::util::value(it);
+
+ if (buf_idx >= 0)
+ {
+ agent->in_views[in_idx].priv().allocate(fu.line_consumption, fu.border);
+ }
+ }
+
+ agent->setRatio(fu.ratio);
+ agent->m_outputLines = agent->out_buffers.front()->priv().outputLines();
+ }
+
+ // Initialize scratch buffers
+ if (m_scratch_users.size())
+ {
+ for (auto i : m_scratch_users)
+ {
+ auto &agent = m_agents.at(i);
+ GAPI_Assert(agent->k.m_scratch);
+
+ // Trigger Scratch buffer initialization method
+ agent->k.m_is(GModel::collectInputMeta(m_gm, agent->op_handle), agent->in_args, *agent->out_buffers.back());
+ std::stringstream stream;
+ agent->out_buffers.back()->debug(stream);
+ GAPI_LOG_INFO(NULL, stream.str());
+ }
+ }
+
+ // FIXME: calculate the size (lpi * ..)
+ m_script.clear();
+ m_script.reserve(10000);
+}
+
+void cv::gimpl::GFluidExecutable::reshape(ade::Graph &g, const GCompileArgs &args)
+{
+ // FIXME: Probably this needs to be integrated into common pass re-run routine
+ // Backends may want to mark with passes to re-run on reshape and framework could
+ // do it system-wide (without need in every backend handling reshape() directly).
+ // This design needs to be analyzed for implementation.
+ resetFluidData(g);
+ initFluidUnits(g);
+ initLineConsumption(g);
+ calcLatency(g);
+ calcSkew(g);
+ const auto out_rois = cv::gimpl::getCompileArg<cv::GFluidOutputRois>(args).value_or(cv::GFluidOutputRois());
+ makeReshape(out_rois.rois);
+}
+
+// FIXME: Document what it does
+void cv::gimpl::GFluidExecutable::bindInArg(const cv::gimpl::RcDesc &rc, const GRunArg &arg)
+{
+ switch (rc.shape)
+ {
+ case GShape::GMAT: m_buffers[m_id_map.at(rc.id)].priv().bindTo(util::get<cv::gapi::own::Mat>(arg), true); break;
+ case GShape::GSCALAR: m_res.slot<cv::gapi::own::Scalar>()[rc.id] = util::get<cv::gapi::own::Scalar>(arg); break;
+ default: util::throw_error(std::logic_error("Unsupported GShape type"));
+ }
+}
+
+void cv::gimpl::GFluidExecutable::bindOutArg(const cv::gimpl::RcDesc &rc, const GRunArgP &arg)
+{
+ // Only GMat is supported as return type
+ switch (rc.shape)
+ {
+ case GShape::GMAT:
+ {
+ cv::GMatDesc desc = m_buffers[m_id_map.at(rc.id)].meta();
+ auto &outMat = *util::get<cv::gapi::own::Mat*>(arg);
+ GAPI_Assert(outMat.data != nullptr);
+ GAPI_Assert(descr_of(outMat) == desc && "Output argument was not preallocated as it should be ?");
+ m_buffers[m_id_map.at(rc.id)].priv().bindTo(outMat, false);
+ break;
+ }
+ default: util::throw_error(std::logic_error("Unsupported return GShape type"));
+ }
+}
+
+void cv::gimpl::GFluidExecutable::packArg(cv::GArg &in_arg, const cv::GArg &op_arg)
+{
+ GAPI_Assert(op_arg.kind != cv::detail::ArgKind::GMAT
+ && op_arg.kind != cv::detail::ArgKind::GSCALAR);
+
+ if (op_arg.kind == cv::detail::ArgKind::GOBJREF)
+ {
+ const cv::gimpl::RcDesc &ref = op_arg.get<cv::gimpl::RcDesc>();
+ if (ref.shape == GShape::GSCALAR)
+ {
+ in_arg = GArg(m_res.slot<cv::gapi::own::Scalar>()[ref.id]);
+ }
+ }
+}
+
+void cv::gimpl::GFluidExecutable::run(std::vector<InObj> &&input_objs,
+ std::vector<OutObj> &&output_objs)
+{
+ // Bind input buffers from parameters
+ for (auto& it : input_objs) bindInArg(it.first, it.second);
+ for (auto& it : output_objs) bindOutArg(it.first, it.second);
+
+ // Reset Buffers and Agents state before we go
+ for (auto &buffer : m_buffers)
+ buffer.priv().reset();
+
+ for (auto &agent : m_agents)
+ {
+ agent->reset();
+ // Pass input cv::Scalar's to agent argument
+ const auto& op = m_gm.metadata(agent->op_handle).get<Op>();
+ for (const auto& it : ade::util::indexed(op.args))
+ {
+ const auto& arg = ade::util::value(it);
+ packArg(agent->in_args[ade::util::index(it)], arg);
+ }
+ }
+
+ // Explicitly reset Scratch buffers, if any
+ for (auto scratch_i : m_scratch_users)
+ {
+ auto &agent = m_agents[scratch_i];
+ GAPI_DbgAssert(agent->k.m_scratch);
+ agent->k.m_rs(*agent->out_buffers.back());
+ }
+
+ // Now start executing our stuff!
+ // Fluid execution is:
+ // - run through list of Agents from Left to Right
+ // - for every Agent:
+ // - if all input Buffers have enough data to fulfill
+ // Agent's window - trigger Agent
+ // - on trigger, Agent takes all input lines from input buffers
+ // and produces a single output line
+ // - once Agent finishes, input buffers get "readDone()",
+ // and output buffers get "writeDone()"
+ // - if there's not enough data, Agent is skipped
+ // Yes, THAT easy!
+
+ if (m_script.empty())
+ {
+ bool complete = true;
+ do {
+ complete = true;
+ bool work_done=false;
+ for (auto &agent : m_agents)
+ {
+ // agent->debug(std::cout);
+ if (!agent->done())
+ {
+ if (agent->canWork())
+ {
+ agent->doWork(); work_done=true;
+ m_script.push_back(agent.get());
+ }
+ if (!agent->done()) complete = false;
+ }
+ }
+ GAPI_Assert(work_done || complete);
+ } while (!complete); // FIXME: number of iterations can be calculated statically
+ }
+ else
+ {
+ for (auto &agent : m_script)
+ {
+ agent->doWork();
+ }
+ }
+}
+
+// FIXME: these passes operate on graph global level!!!
+// Need to fix this for heterogeneous (island-based) processing
+void GFluidBackendImpl::addBackendPasses(ade::ExecutionEngineSetupContext &ectx)
+{
+ using namespace cv::gimpl;
+
+ // FIXME: all passes were moved to "exec" stage since Fluid
+ // should check Islands configuration first (which is now quite
+ // limited), and only then continue with all other passes.
+ //
+ // The passes/stages API must be streamlined!
+ ectx.addPass("exec", "init_fluid_data", [](ade::passes::PassContext &ctx)
+ {
+ GModel::Graph g(ctx.graph);
+ if (!GModel::isActive(g, cv::gapi::fluid::backend())) // FIXME: Rearchitect this!
+ return;
+
+ auto isl_graph = g.metadata().get<IslandModel>().model;
+ GIslandModel::Graph gim(*isl_graph);
+
+ GFluidModel fg(ctx.graph);
+
+ const auto setFluidData = [&](ade::NodeHandle nh, bool internal) {
+ FluidData fd;
+ fd.internal = internal;
+ fg.metadata(nh).set(fd);
+ };
+
+ for (const auto& nh : gim.nodes())
+ {
+ if (gim.metadata(nh).get<NodeKind>().k == NodeKind::ISLAND)
+ {
+ const auto isl = gim.metadata(nh).get<FusedIsland>().object;
+ if (isl->backend() == cv::gapi::fluid::backend())
+ {
+ // add FluidData to all data nodes inside island
+ for (const auto node : isl->contents())
+ {
+ if (g.metadata(node).get<NodeType>().t == NodeType::DATA)
+ setFluidData(node, true);
+ }
+
+ // add FluidData to slot if it's read/written by fluid
+ std::vector<ade::NodeHandle> io_handles;
+ for (const auto &in_op : isl->in_ops())
+ {
+ ade::util::copy(in_op->inNodes(), std::back_inserter(io_handles));
+ }
+ for (const auto &out_op : isl->out_ops())
+ {
+ ade::util::copy(out_op->outNodes(), std::back_inserter(io_handles));
+ }
+ for (const auto &io_node : io_handles)
+ {
+ if (!fg.metadata(io_node).contains<FluidData>())
+ setFluidData(io_node, false);
+ }
+ } // if (fluid backend)
+ } // if (ISLAND)
+ } // for (gim.nodes())
+ });
+ // FIXME:
+ // move to unpackKernel method
+ // when https://gitlab-icv.inn.intel.com/G-API/g-api/merge_requests/66 is merged
+ ectx.addPass("exec", "init_fluid_unit_borders", [](ade::passes::PassContext &ctx)
+ {
+ GModel::Graph g(ctx.graph);
+ if (!GModel::isActive(g, cv::gapi::fluid::backend())) // FIXME: Rearchitect this!
+ return;
+
+ GFluidModel fg(ctx.graph);
+
+ auto sorted = g.metadata().get<ade::passes::TopologicalSortData>().nodes();
+ for (auto node : sorted)
+ {
+ if (fg.metadata(node).contains<FluidUnit>())
+ {
+ // FIXME: check that op has only one data node on input
+ auto &fu = fg.metadata(node).get<FluidUnit>();
+ const auto &op = g.metadata(node).get<Op>();
+
+ // Trigger user-defined "getBorder" callback
+ fu.border = fu.k.m_b(GModel::collectInputMeta(fg, node), op.args);
+ }
+ }
+ });
+ ectx.addPass("exec", "init_fluid_units", [](ade::passes::PassContext &ctx)
+ {
+ GModel::Graph g(ctx.graph);
+ if (!GModel::isActive(g, cv::gapi::fluid::backend())) // FIXME: Rearchitect this!
+ return;
+
+ initFluidUnits(ctx.graph);
+ });
+ ectx.addPass("exec", "init_line_consumption", [](ade::passes::PassContext &ctx)
+ {
+ GModel::Graph g(ctx.graph);
+ if (!GModel::isActive(g, cv::gapi::fluid::backend())) // FIXME: Rearchitect this!
+ return;
+
+ initLineConsumption(ctx.graph);
+ });
+ ectx.addPass("exec", "calc_latency", [](ade::passes::PassContext &ctx)
+ {
+ GModel::Graph g(ctx.graph);
+ if (!GModel::isActive(g, cv::gapi::fluid::backend())) // FIXME: Rearchitect this!
+ return;
+
+ calcLatency(ctx.graph);
+ });
+ ectx.addPass("exec", "calc_skew", [](ade::passes::PassContext &ctx)
+ {
+ GModel::Graph g(ctx.graph);
+ if (!GModel::isActive(g, cv::gapi::fluid::backend())) // FIXME: Rearchitect this!
+ return;
+
+ calcSkew(ctx.graph);
+ });
+
+ ectx.addPass("exec", "init_buffer_borders", [](ade::passes::PassContext &ctx)
+ {
+ GModel::Graph g(ctx.graph);
+ if (!GModel::isActive(g, cv::gapi::fluid::backend())) // FIXME: Rearchitect this!
+ return;
+
+ GFluidModel fg(ctx.graph);
+ auto sorted = g.metadata().get<ade::passes::TopologicalSortData>().nodes();
+ for (auto node : sorted)
+ {
+ if (fg.metadata(node).contains<FluidData>())
+ {
+ auto &fd = fg.metadata(node).get<FluidData>();
+
+ // Assign border stuff to FluidData
+
+ // In/out data nodes are bound to user data directly,
+ // so cannot be extended with a border
+ if (fd.internal == true)
+ {
+ // For now border of the buffer's storage is the border
+ // of the first reader whose border size is the same.
+ // FIXME: find more clever strategy of border picking
+ // (it can be a border which is common for majority of the
+ // readers, also we can calculate the number of lines which
+ // will be copied by views on each iteration and base our choice
+ // on this criteria)
+ auto readers = node->outNodes();
+ const auto &candidate = ade::util::find_if(readers, [&](ade::NodeHandle nh) {
+ return fg.metadata(nh).contains<FluidUnit>() &&
+ fg.metadata(nh).get<FluidUnit>().border_size == fd.border_size;
+ });
+
+ GAPI_Assert(candidate != readers.end());
+
+ const auto &fu = fg.metadata(*candidate).get<FluidUnit>();
+ fd.border = fu.border;
+ }
+
+ if (fd.border)
+ {
+ GModel::log(g, node, "Border type: " + std::to_string(fd.border->type), node);
+ }
+ }
+ }
+ });
+ ectx.addPass("exec", "init_view_borders", [](ade::passes::PassContext &ctx)
+ {
+ GModel::Graph g(ctx.graph);
+ if (!GModel::isActive(g, cv::gapi::fluid::backend())) // FIXME: Rearchitect this!
+ return;
+
+ GFluidModel fg(ctx.graph);
+ for (auto node : g.nodes())
+ {
+ if (fg.metadata(node).contains<FluidData>())
+ {
+ auto &fd = fg.metadata(node).get<FluidData>();
+ for (auto out_edge : node->outEdges())
+ {
+ const auto dstNode = out_edge->dstNode();
+ if (fg.metadata(dstNode).contains<FluidUnit>())
+ {
+ const auto &fu = fg.metadata(dstNode).get<FluidUnit>();
+
+ // There is no need in own storage for view if it's border is
+ // the same as the buffer's (view can have equal or smaller border
+ // size in this case)
+ if (fu.border_size == 0 ||
+ (fu.border && fd.border && (*fu.border == *fd.border)))
+ {
+ GAPI_Assert(fu.border_size <= fd.border_size);
+ fg.metadata(out_edge).set(FluidUseOwnBorderBuffer{false});
+ }
+ else
+ {
+ fg.metadata(out_edge).set(FluidUseOwnBorderBuffer{true});
+ GModel::log(g, out_edge, "OwnBufferStorage: true");
+ }
+ }
+ }
+ }
+ }
+ });
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.hpp
new file mode 100644
index 000000000..ba8b9771f
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbackend.hpp
@@ -0,0 +1,137 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_FLUID_BACKEND_HPP
+#define OPENCV_GAPI_FLUID_BACKEND_HPP
+
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gproto.hpp"
+#include "opencv2/gapi/fluid/gfluidkernel.hpp"
+#include "opencv2/gapi/fluid/gfluidbuffer.hpp"
+
+// PRIVATE STUFF!
+#include "backends/common/gbackend.hpp"
+#include "compiler/gislandmodel.hpp"
+
+namespace cv { namespace gimpl {
+
+struct FluidUnit
+{
+ static const char *name() { return "FluidUnit"; }
+ GFluidKernel k;
+ gapi::fluid::BorderOpt border;
+ int border_size;
+ int line_consumption;
+ double ratio;
+};
+
+struct FluidUseOwnBorderBuffer
+{
+ static const char *name() { return "FluidUseOwnBorderBuffer"; }
+ bool use;
+};
+
+struct FluidData
+{
+ static const char *name() { return "FluidData"; }
+
+ // FIXME: This structure starts looking like "FluidBuffer" meta
+ int latency = 0;
+ int skew = 0;
+ int max_consumption = 1;
+ int border_size = 0;
+ int lpi_write = 1;
+ bool internal = false; // is node internal to any fluid island
+ gapi::fluid::BorderOpt border;
+};
+
+struct FluidAgent
+{
+public:
+ virtual ~FluidAgent() = default;
+ FluidAgent(const ade::Graph &g, ade::NodeHandle nh);
+
+ GFluidKernel k;
+ ade::NodeHandle op_handle; // FIXME: why it is here??//
+ std::string op_name;
+
+ // < 0 - not a buffer
+ // >= 0 - a buffer with RcID
+ std::vector<int> in_buffer_ids;
+ std::vector<int> out_buffer_ids;
+
+ cv::GArgs in_args;
+ std::vector<cv::gapi::fluid::View> in_views; // sparce list of IN views
+ std::vector<cv::gapi::fluid::Buffer*> out_buffers;
+
+ // FIXME Current assumption is that outputs have EQUAL SIZES
+ int m_outputLines = 0;
+ int m_producedLines = 0;
+
+ // Execution methods
+ void reset();
+ bool canWork() const;
+ bool canRead() const;
+ bool canWrite() const;
+ void doWork();
+ bool done() const;
+
+ void debug(std::ostream& os);
+
+ // FIXME:
+ // refactor (implement a more solid replacement or
+ // drop this method completely)
+ virtual void setRatio(double ratio) = 0;
+
+private:
+ // FIXME!!!
+ // move to another class
+ virtual int firstWindow() const = 0;
+ virtual std::pair<int,int> linesReadAndnextWindow() const = 0;
+};
+
+class GFluidExecutable final: public GIslandExecutable
+{
+ const ade::Graph &m_g;
+ GModel::ConstGraph m_gm;
+
+ std::vector<std::unique_ptr<FluidAgent>> m_agents;
+ std::vector<cv::gapi::fluid::Buffer> m_buffers;
+
+ std::vector<FluidAgent*> m_script;
+
+ using Magazine = detail::magazine<cv::gapi::own::Scalar>;
+ Magazine m_res;
+
+ std::size_t m_num_int_buffers; // internal buffers counter (m_buffers - num_scratch)
+ std::vector<std::size_t> m_scratch_users;
+
+ std::unordered_map<int, std::size_t> m_id_map; // GMat id -> buffer idx map
+ std::map<std::size_t, ade::NodeHandle> m_all_gmat_ids;
+
+ void bindInArg (const RcDesc &rc, const GRunArg &arg);
+ void bindOutArg(const RcDesc &rc, const GRunArgP &arg);
+ void packArg (GArg &in_arg, const GArg &op_arg);
+
+ void initBufferRois(std::vector<int>& readStarts, std::vector<cv::gapi::own::Rect>& rois, const std::vector<gapi::own::Rect> &out_rois);
+ void makeReshape(const std::vector<cv::gapi::own::Rect>& out_rois);
+
+public:
+ GFluidExecutable(const ade::Graph &g,
+ const std::vector<ade::NodeHandle> &nodes,
+ const std::vector<cv::gapi::own::Rect> &outputRois);
+
+ virtual inline bool canReshape() const override { return true; }
+ virtual void reshape(ade::Graph& g, const GCompileArgs& args) override;
+
+ virtual void run(std::vector<InObj> &&input_objs,
+ std::vector<OutObj> &&output_objs) override;
+};
+}} // cv::gimpl
+
+
+#endif // OPENCV_GAPI_FLUID_BACKEND_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer.cpp
new file mode 100644
index 000000000..6672ea272
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer.cpp
@@ -0,0 +1,760 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <iomanip> // hex, dec (debug)
+
+#include "opencv2/gapi/own/convert.hpp"
+#include "opencv2/gapi/own/types.hpp"
+
+#include "opencv2/gapi/fluid/gfluidbuffer.hpp"
+#include "backends/fluid/gfluidbuffer_priv.hpp"
+#include "opencv2/gapi/opencv_includes.hpp"
+
+#include "backends/fluid/gfluidutils.hpp" // saturate
+
+namespace cv {
+namespace gapi {
+namespace fluid {
+bool operator == (const fluid::Border& b1, const fluid::Border& b2)
+{
+ return b1.type == b2.type && b1.value == b2.value;
+}
+} // namespace fluid
+
+// Fluid BorderHandler implementation /////////////////////////////////////////////////
+
+namespace {
+template<typename T>
+// Expected inputs:
+// row - row buffer allocated with border in mind (have memory for both image and border pixels)
+// length - size of the buffer with left and right borders included
+void fillBorderReplicateRow(uint8_t* row, int length, int chan, int borderSize)
+{
+ auto leftBorder = reinterpret_cast<T*>(row);
+ auto rightBorder = leftBorder + (length - borderSize) * chan;
+ for (int b = 0; b < borderSize; b++)
+ {
+ for (int c = 0; c < chan; c++)
+ {
+ leftBorder [b*chan + c] = leftBorder [borderSize*chan + c];
+ rightBorder[b*chan + c] = rightBorder[-chan + c];
+ }
+ }
+}
+
+template<typename T>
+void fillBorderReflectRow(uint8_t* row, int length, int chan, int borderSize)
+{
+ auto leftBorder = reinterpret_cast<T*>(row);
+ auto rightBorder = leftBorder + (length - borderSize) * chan;
+ for (int b = 0; b < borderSize; b++)
+ {
+ for (int c = 0; c < chan; c++)
+ {
+ leftBorder [b*chan + c] = leftBorder [(2*borderSize - b)*chan + c];
+ rightBorder[b*chan + c] = rightBorder[(-b - 2)*chan + c];
+ }
+ }
+}
+
+template<typename T>
+void fillConstBorderRow(uint8_t* row, int length, int chan, int borderSize, cv::gapi::own::Scalar borderValue)
+{
+ GAPI_DbgAssert(chan > 0 && chan <= 4);
+
+ auto leftBorder = reinterpret_cast<T*>(row);
+ auto rightBorder = leftBorder + (length - borderSize) * chan;
+ for (int b = 0; b < borderSize; b++)
+ {
+ for (int c = 0; c < chan; c++)
+ {
+ leftBorder [b*chan + c] = fluid::saturate<T>(borderValue[c], fluid::roundd);
+ rightBorder[b*chan + c] = fluid::saturate<T>(borderValue[c], fluid::roundd);
+ }
+ }
+}
+
+// Fills const border pixels in the whole mat
+void fillBorderConstant(int borderSize, cv::gapi::own::Scalar borderValue, cv::gapi::own::Mat& mat)
+{
+ // cv::Scalar can contain maximum 4 chan
+ GAPI_Assert(mat.channels() > 0 && mat.channels() <= 4);
+
+ auto getFillBorderRowFunc = [&](int type) {
+ switch(type)
+ {
+ case CV_8U: return &fillConstBorderRow< uint8_t>; break;
+ case CV_16S: return &fillConstBorderRow< int16_t>; break;
+ case CV_16U: return &fillConstBorderRow<uint16_t>; break;
+ case CV_32F: return &fillConstBorderRow< float >; break;
+ default: GAPI_Assert(false); return &fillConstBorderRow<uint8_t>;
+ }
+ };
+
+ auto fillBorderRow = getFillBorderRowFunc(mat.depth());
+ for (int y = 0; y < mat.rows; y++)
+ {
+ fillBorderRow(mat.ptr(y), mat.cols, mat.channels(), borderSize, borderValue);
+ }
+}
+} // anonymous namespace
+
+fluid::BorderHandler::BorderHandler(int border_size)
+{
+ GAPI_Assert(border_size > 0);
+ m_border_size = border_size;
+}
+
+template <int BorderType>
+fluid::BorderHandlerT<BorderType>::BorderHandlerT(int border_size, int data_type)
+ : BorderHandler(border_size)
+{
+ auto getFillBorderRowFunc = [&](int border, int depth) {
+ if (border == cv::BORDER_REPLICATE)
+ {
+ switch(depth)
+ {
+ case CV_8U: return &fillBorderReplicateRow< uint8_t>; break;
+ case CV_16S: return &fillBorderReplicateRow< int16_t>; break;
+ case CV_16U: return &fillBorderReplicateRow<uint16_t>; break;
+ case CV_32F: return &fillBorderReplicateRow< float >; break;
+ default: GAPI_Assert(!"Unsupported data type"); return &fillBorderReplicateRow<uint8_t>;
+ }
+ }
+ else if (border == cv::BORDER_REFLECT_101)
+ {
+ switch(depth)
+ {
+ case CV_8U: return &fillBorderReflectRow< uint8_t>; break;
+ case CV_16S: return &fillBorderReflectRow< int16_t>; break;
+ case CV_16U: return &fillBorderReflectRow<uint16_t>; break;
+ case CV_32F: return &fillBorderReflectRow< float >; break;
+ default: GAPI_Assert(!"Unsupported data type"); return &fillBorderReflectRow<uint8_t>;
+ }
+ }
+ else
+ {
+ GAPI_Assert(!"Unsupported border type");
+ return &fillBorderReflectRow<uint8_t>;
+ }
+ };
+
+ m_fill_border_row = getFillBorderRowFunc(BorderType, CV_MAT_DEPTH(data_type));
+}
+
+namespace {
+template <int BorderType> int getBorderIdx(int log_idx, int desc_height);
+
+template<> int getBorderIdx<cv::BORDER_REPLICATE>(int log_idx, int desc_height)
+{
+ return log_idx < 0 ? 0 : desc_height - 1;
+}
+
+template<> int getBorderIdx<cv::BORDER_REFLECT_101>(int log_idx, int desc_height)
+{
+ return log_idx < 0 ? -log_idx : 2*(desc_height - 1) - log_idx;
+}
+} // namespace
+
+template <int BorderType>
+const uint8_t* fluid::BorderHandlerT<BorderType>::inLineB(int log_idx, const BufferStorageWithBorder& data, int desc_height) const
+{
+ auto idx = getBorderIdx<BorderType>(log_idx, desc_height);
+ return data.ptr(idx);
+}
+
+fluid::BorderHandlerT<cv::BORDER_CONSTANT>::BorderHandlerT(int border_size, cv::gapi::own::Scalar border_value)
+ : BorderHandler(border_size), m_border_value(border_value)
+{ /* nothing */ }
+
+const uint8_t* fluid::BorderHandlerT<cv::BORDER_CONSTANT>::inLineB(int /*log_idx*/, const BufferStorageWithBorder& /*data*/, int /*desc_height*/) const
+{
+ return m_const_border.ptr(0, m_border_size);
+}
+
+void fluid::BorderHandlerT<cv::BORDER_CONSTANT>::fillCompileTimeBorder(BufferStorageWithBorder& data)
+{
+ m_const_border.create(1, data.cols(), data.data().type());
+ m_const_border = m_border_value;
+
+ cv::gapi::fillBorderConstant(m_border_size, m_border_value, data.data());
+}
+
+template <int BorderType>
+void fluid::BorderHandlerT<BorderType>::updateBorderPixels(BufferStorageWithBorder &data, int startLine, int nLines) const
+{
+ auto& mat = data.data();
+ auto length = mat.cols;
+ auto chan = mat.channels();
+
+ for (int l = startLine; l < startLine + nLines; l++)
+ {
+ auto row = mat.ptr(data.physIdx(l));
+ m_fill_border_row(row, length, chan, m_border_size);
+ }
+}
+
+std::size_t fluid::BorderHandlerT<cv::BORDER_CONSTANT>::size() const
+{
+ return m_const_border.total() * m_const_border.elemSize();
+}
+
+// Fluid BufferStorage implementation //////////////////////////////////////////
+
+void fluid::BufferStorage::updateInCache(View::Cache& cache, int start_log_idx, int nLines) const
+{
+ for (int i = 0; i < nLines; i++)
+ {
+ cache.m_linePtrs[i] = inLineB(start_log_idx + i, cache.m_desc.size.height);
+ }
+}
+
+void fluid::BufferStorage::updateOutCache(Buffer::Cache& cache, int start_log_idx, int nLines)
+{
+ for (int i = 0; i < nLines; i++)
+ {
+ cache.m_linePtrs[i] = ptr(start_log_idx + i);
+ }
+}
+
+void fluid::BufferStorageWithBorder::init(int dtype, int border_size, Border border)
+{
+ switch(border.type)
+ {
+ case cv::BORDER_CONSTANT:
+ m_borderHandler.reset(new BorderHandlerT<cv::BORDER_CONSTANT>(border_size, border.value)); break;
+ case cv::BORDER_REPLICATE:
+ m_borderHandler.reset(new BorderHandlerT<cv::BORDER_REPLICATE>(border_size, dtype)); break;
+ case cv::BORDER_REFLECT_101:
+ m_borderHandler.reset(new BorderHandlerT<cv::BORDER_REFLECT_101>(border_size, dtype)); break;
+ default:
+ GAPI_Assert(false);
+ }
+}
+
+void fluid::BufferStorageWithBorder::create(int capacity, int desc_width, int dtype)
+{
+ auto borderSize = m_borderHandler->borderSize();
+ auto width = (desc_width + 2*borderSize);
+ m_data.create(capacity, width, dtype);
+
+ m_borderHandler->fillCompileTimeBorder(*this);
+}
+
+void fluid::BufferStorageWithoutBorder::create(int capacity, int desc_width, int dtype)
+{
+ auto width = desc_width;
+ m_data.create(capacity, width, dtype);
+
+ m_is_virtual = true;
+}
+
+const uint8_t* fluid::BufferStorageWithBorder::inLineB(int log_idx, int desc_height) const
+{
+ if (log_idx < 0 || log_idx >= desc_height)
+ {
+ return m_borderHandler->inLineB(log_idx, *this, desc_height);
+ }
+ else
+ {
+ return ptr(log_idx);
+ }
+}
+
+static void copyWithoutBorder(const cv::gapi::own::Mat& src, int src_border_size, cv::gapi::own::Mat& dst, int dst_border_size, int startSrcLine, int startDstLine, int lpi)
+{
+ auto subSrc = src(cv::gapi::own::Rect{src_border_size, startSrcLine, src.cols - 2*src_border_size, lpi});
+ auto subDst = dst(cv::gapi::own::Rect{dst_border_size, startDstLine, dst.cols - 2*dst_border_size, lpi});
+
+ subSrc.copyTo(subDst);
+}
+
+void fluid::BufferStorageWithoutBorder::copyTo(BufferStorageWithBorder &dst, int startLine, int nLines) const
+{
+ for (int l = startLine; l < startLine + nLines; l++)
+ {
+ copyWithoutBorder(m_data, 0, dst.data(), dst.borderSize(), physIdx(l), dst.physIdx(l), 1);
+ }
+}
+
+void fluid::BufferStorageWithBorder::copyTo(BufferStorageWithBorder &dst, int startLine, int nLines) const
+{
+ // Copy required lpi lines line by line (to avoid wrap if invoked for multiple lines)
+ for (int l = startLine; l < startLine + nLines; l++)
+ {
+ copyWithoutBorder(m_data, borderSize(), dst.data(), dst.borderSize(), physIdx(l), dst.physIdx(l), 1);
+ }
+}
+
+// FIXME? remember parent and remove src parameter?
+void fluid::BufferStorageWithBorder::updateBeforeRead(int startLine, int nLines, const BufferStorage& src)
+{
+ // TODO:
+ // Cover with tests!!
+ // (Ensure that there are no redundant copies done
+ // and only required (not fetched before) lines are copied)
+
+ GAPI_DbgAssert(startLine >= 0);
+
+ src.copyTo(*this, startLine, nLines);
+ m_borderHandler->updateBorderPixels(*this, startLine, nLines);
+}
+
+void fluid::BufferStorageWithoutBorder::updateBeforeRead(int /*startLine*/, int /*lpi*/, const BufferStorage& /*src*/)
+{
+ /* nothing */
+}
+
+void fluid::BufferStorageWithBorder::updateAfterWrite(int startLine, int nLines)
+{
+ // FIXME?
+ // Actually startLine + nLines can be > logical height so
+ // redundant end lines which will never be read
+ // can be filled in the ring buffer
+ m_borderHandler->updateBorderPixels(*this, startLine, nLines);
+}
+
+void fluid::BufferStorageWithoutBorder::updateAfterWrite(int /*startLine*/, int /*lpi*/)
+{
+ /* nothing */
+}
+
+size_t fluid::BufferStorageWithBorder::size() const
+{
+ return m_data.total()*m_data.elemSize() + m_borderHandler->size();
+}
+
+size_t fluid::BufferStorageWithoutBorder::size() const
+{
+ return m_data.total()*m_data.elemSize();
+}
+
+namespace fluid {
+namespace {
+std::unique_ptr<fluid::BufferStorage> createStorage(int capacity, int desc_width, int type,
+ int border_size, fluid::BorderOpt border);
+std::unique_ptr<fluid::BufferStorage> createStorage(int capacity, int desc_width, int type,
+ int border_size, fluid::BorderOpt border)
+{
+ if (border)
+ {
+ std::unique_ptr<fluid::BufferStorageWithBorder> storage(new BufferStorageWithBorder);
+ storage->init(type, border_size, border.value());
+ storage->create(capacity, desc_width, type);
+ return std::move(storage);
+ }
+
+ std::unique_ptr<BufferStorageWithoutBorder> storage(new BufferStorageWithoutBorder);
+ storage->create(capacity, desc_width, type);
+ return std::move(storage);
+}
+
+std::unique_ptr<BufferStorage> createStorage(const cv::gapi::own::Mat& data, cv::gapi::own::Rect roi);
+std::unique_ptr<BufferStorage> createStorage(const cv::gapi::own::Mat& data, cv::gapi::own::Rect roi)
+{
+ std::unique_ptr<BufferStorageWithoutBorder> storage(new BufferStorageWithoutBorder);
+ storage->attach(data, roi);
+ return std::move(storage);
+}
+} // namespace
+} // namespace fluid
+
+// Fluid View implementation ///////////////////////////////////////////////////
+
+void fluid::View::Priv::reset(int linesForFirstIteration)
+{
+ GAPI_DbgAssert(m_p);
+
+ m_lines_next_iter = linesForFirstIteration;
+ m_read_caret = m_p->priv().readStart();
+}
+
+void fluid::View::Priv::readDone(int linesRead, int linesForNextIteration)
+{
+ GAPI_DbgAssert(m_p);
+ m_read_caret += linesRead;
+ m_lines_next_iter = linesForNextIteration;
+}
+
+bool fluid::View::Priv::ready() const
+{
+ auto lastWrittenLine = m_p->priv().writeStart() + m_p->linesReady();
+ // + bottom border
+ if (lastWrittenLine == m_p->meta().size.height) lastWrittenLine += m_border_size;
+ // + top border
+ lastWrittenLine += m_border_size;
+
+ auto lastRequiredLine = m_read_caret + m_lines_next_iter;
+
+ return lastWrittenLine >= lastRequiredLine;
+}
+
+fluid::ViewPrivWithoutOwnBorder::ViewPrivWithoutOwnBorder(const Buffer *parent, int borderSize)
+{
+ GAPI_Assert(parent);
+ m_p = parent;
+ m_border_size = borderSize;
+}
+
+const uint8_t* fluid::ViewPrivWithoutOwnBorder::InLineB(int index) const
+{
+ GAPI_DbgAssert(m_p);
+
+ const auto &p_priv = m_p->priv();
+
+ GAPI_DbgAssert(index >= -m_border_size
+ && index < -m_border_size + m_lines_next_iter);
+
+ const int log_idx = m_read_caret + index;
+
+ return p_priv.storage().inLineB(log_idx, m_p->meta().size.height);
+}
+
+void fluid::ViewPrivWithoutOwnBorder::allocate(int lineConsumption, BorderOpt)
+{
+ initCache(lineConsumption);
+}
+
+void fluid::ViewPrivWithoutOwnBorder::prepareToRead()
+{
+ const auto &storage = m_p->priv().storage();
+
+ const int start_log_idx = m_read_caret - m_border_size;
+ storage.updateInCache(m_cache, start_log_idx, m_lines_next_iter);
+}
+
+fluid::ViewPrivWithOwnBorder::ViewPrivWithOwnBorder(const Buffer *parent, int borderSize)
+{
+ GAPI_Assert(parent);
+ m_p = parent;
+ m_border_size = borderSize;
+}
+
+void fluid::ViewPrivWithOwnBorder::allocate(int lineConsumption, BorderOpt border)
+{
+ initCache(lineConsumption);
+
+ const auto& desc = m_cache.m_desc;
+ int type = CV_MAKETYPE(desc.depth, desc.chan);
+ m_own_storage.init(type, m_border_size, border.value());
+ m_own_storage.create(lineConsumption, desc.size.width, type);
+}
+
+void fluid::ViewPrivWithOwnBorder::prepareToRead()
+{
+ int startLine = 0;
+ int nLines = 0;
+
+ if (m_read_caret == m_p->priv().readStart())
+ {
+ // Need to fetch full window on the first iteration
+ startLine = (m_read_caret > m_border_size) ? m_read_caret - m_border_size : 0;
+ nLines = m_lines_next_iter;
+ }
+ else
+ {
+ startLine = m_read_caret + m_border_size;
+ nLines = m_lines_next_iter - 2*m_border_size;
+ }
+
+ m_own_storage.updateBeforeRead(startLine, nLines, m_p->priv().storage());
+
+ const int start_log_idx = m_read_caret - m_border_size;
+ m_own_storage.updateInCache(m_cache, start_log_idx, m_lines_next_iter);
+}
+
+std::size_t fluid::ViewPrivWithOwnBorder::size() const
+{
+ GAPI_DbgAssert(m_p);
+ return m_own_storage.size();
+}
+
+const uint8_t* fluid::ViewPrivWithOwnBorder::InLineB(int index) const
+{
+ GAPI_DbgAssert(m_p);
+ GAPI_DbgAssert(index >= -m_border_size
+ && index < -m_border_size + m_lines_next_iter);
+
+ const int log_idx = m_read_caret + index;
+
+ return m_own_storage.inLineB(log_idx, m_p->meta().size.height);
+}
+
+bool fluid::View::ready() const
+{
+ return m_priv->ready();
+}
+
+int fluid::View::y() const
+{
+ return m_priv->m_read_caret - m_priv->m_border_size;
+}
+
+fluid::View::Priv& fluid::View::priv()
+{
+ return *m_priv;
+}
+
+const fluid::View::Priv& fluid::View::priv() const
+{
+ return *m_priv;
+}
+
+void fluid::View::Priv::initCache(int lineConsumption)
+{
+ m_cache.m_linePtrs.resize(lineConsumption);
+ m_cache.m_desc = m_p->priv().meta();
+ m_cache.m_border_size = m_border_size;
+}
+
+// Fluid Buffer implementation /////////////////////////////////////////////////
+
+fluid::Buffer::Priv::Priv(int read_start, cv::gapi::own::Rect roi)
+ : m_readStart(read_start)
+ , m_roi(roi)
+{}
+
+void fluid::Buffer::Priv::init(const cv::GMatDesc &desc,
+ int writer_lpi,
+ int readStartPos,
+ cv::gapi::own::Rect roi)
+{
+ m_writer_lpi = writer_lpi;
+ m_desc = desc;
+ m_readStart = readStartPos;
+ m_roi = roi == own::Rect{} ? own::Rect{ 0, 0, desc.size.width, desc.size.height }
+ : roi;
+ m_cache.m_linePtrs.resize(writer_lpi);
+ m_cache.m_desc = desc;
+}
+
+void fluid::Buffer::Priv::allocate(BorderOpt border,
+ int border_size,
+ int line_consumption,
+ int skew)
+{
+ GAPI_Assert(line_consumption > 0);
+
+ // Init physical buffer
+
+ // FIXME? combine line_consumption with skew?
+ auto data_height = std::max(line_consumption, skew) + m_writer_lpi - 1;
+
+ m_storage = createStorage(data_height,
+ m_desc.size.width,
+ CV_MAKETYPE(m_desc.depth, m_desc.chan),
+ border_size,
+ border);
+
+ // Finally, initialize carets
+ m_write_caret = writeStart();
+
+ m_storage->updateOutCache(m_cache, m_write_caret, m_writer_lpi);
+}
+
+void fluid::Buffer::Priv::bindTo(const cv::gapi::own::Mat &data, bool is_input)
+{
+ // FIXME: move all these fields into a separate structure
+ GAPI_Assert(m_desc == descr_of(data));
+
+ // Currently m_writer_lpi is obtained from metadata which is shared between islands
+ // and this assert can trigger for slot which connects two fluid islands.
+ // m_writer_lpi is used only in write-related functions and doesn't affect
+ // buffer which is island's input so it's safe to skip this check.
+ // FIXME:
+ // Bring back this check when we move to 1 buffer <-> 1 metadata model
+ // if (is_input) GAPI_Assert(m_writer_lpi == 1);
+
+ m_storage = createStorage(data, m_roi);
+
+ m_is_input = is_input;
+ m_write_caret = is_input ? writeEnd(): writeStart();
+ // NB: views remain the same!
+
+ m_storage->updateOutCache(m_cache, m_write_caret, m_writer_lpi);
+}
+
+bool fluid::Buffer::Priv::full() const
+{
+ int slowest_y = writeEnd();
+ if (!m_views.empty())
+ {
+ // reset with maximum possible value and then find minimum
+ slowest_y = m_desc.size.height;
+ for (const auto &v : m_views) slowest_y = std::min(slowest_y, v.y());
+ }
+
+ return m_write_caret + lpi() - slowest_y > m_storage->rows();
+}
+
+void fluid::Buffer::Priv::writeDone()
+{
+ // There are possible optimizations which can be done to fill a border values
+ // in compile time of the graph (for example border is const),
+ // so there is no need to update border values after each write.
+ // If such optimizations weren't applied, fill border for lines
+ // which have been just written
+ m_storage->updateAfterWrite(m_write_caret, m_writer_lpi);
+
+ // Final write may produce less LPI, so
+ // write caret may exceed logical buffer size
+ m_write_caret += m_writer_lpi;
+ // FIXME: add consistency check!
+
+ m_storage->updateOutCache(m_cache, m_write_caret, m_writer_lpi);
+}
+
+void fluid::Buffer::Priv::reset()
+{
+ m_write_caret = m_is_input ? writeEnd() : writeStart();
+ m_storage->updateOutCache(m_cache, m_write_caret, m_writer_lpi);
+}
+
+int fluid::Buffer::Priv::size() const
+{
+ std::size_t view_sz = 0;
+ for (const auto &v : m_views) view_sz += v.priv().size();
+
+ auto total = view_sz;
+ if (m_storage) total += m_storage->size();
+
+ // FIXME: Change API to return size_t!!!
+ return static_cast<int>(total);
+}
+
+int fluid::Buffer::Priv::linesReady() const
+{
+ if (m_is_input)
+ {
+ return m_storage->rows();
+ }
+ else
+ {
+ const int writes = std::min(m_write_caret - writeStart(), outputLines());
+ return writes;
+ }
+}
+
+uint8_t* fluid::Buffer::Priv::OutLineB(int index)
+{
+ GAPI_DbgAssert(index >= 0 && index < m_writer_lpi);
+
+ return m_storage->ptr(m_write_caret + index);
+}
+
+int fluid::Buffer::Priv::lpi() const
+{
+ // FIXME:
+ // m_write_caret can be greater than m_writeRoi.y + m_writeRoi.height, so return value can be negative !!!
+ return std::min(writeEnd() - m_write_caret, m_writer_lpi);
+}
+
+fluid::Buffer::Buffer()
+ : m_priv(new Priv())
+ , m_cache(&m_priv->cache())
+{
+}
+
+fluid::Buffer::Buffer(const cv::GMatDesc &desc)
+ : m_priv(new Priv())
+ , m_cache(&m_priv->cache())
+{
+ int lineConsumption = 1;
+ int border = 0, skew = 0, wlpi = 1, readStart = 0;
+ cv::gapi::own::Rect roi = {0, 0, desc.size.width, desc.size.height};
+ m_priv->init(desc, wlpi, readStart, roi);
+ m_priv->allocate({}, border, lineConsumption, skew);
+}
+
+fluid::Buffer::Buffer(const cv::GMatDesc &desc,
+ int max_line_consumption,
+ int border_size,
+ int skew,
+ int wlpi,
+ BorderOpt border)
+ : m_priv(new Priv())
+ , m_cache(&m_priv->cache())
+{
+ int readStart = 0;
+ cv::gapi::own::Rect roi = {0, 0, desc.size.width, desc.size.height};
+ m_priv->init(desc, wlpi, readStart, roi);
+ m_priv->allocate(border, border_size, max_line_consumption, skew);
+}
+
+fluid::Buffer::Buffer(const cv::gapi::own::Mat &data, bool is_input)
+ : m_priv(new Priv())
+ , m_cache(&m_priv->cache())
+{
+ int wlpi = 1, readStart = 0;
+ cv::gapi::own::Rect roi{0, 0, data.cols, data.rows};
+ m_priv->init(descr_of(data), wlpi, readStart, roi);
+ m_priv->bindTo(data, is_input);
+}
+
+int fluid::Buffer::linesReady() const
+{
+ return m_priv->linesReady();
+}
+
+int fluid::Buffer::lpi() const
+{
+ return m_priv->lpi();
+}
+
+fluid::View::View(Priv* p)
+ : m_priv(p), m_cache(&p->cache())
+{ /* nothing */ }
+
+fluid::View fluid::Buffer::mkView(int borderSize, bool ownStorage)
+{
+ // FIXME: logic outside of Priv (because View takes pointer to Buffer)
+ auto view = ownStorage ? View(new ViewPrivWithOwnBorder(this, borderSize))
+ : View(new ViewPrivWithoutOwnBorder(this, borderSize));
+ m_priv->addView(view);
+ return view;
+}
+
+void fluid::debugBufferPriv(const fluid::Buffer& buffer, std::ostream &os)
+{
+ // FIXME Use cv::gapi::own Size and Rect with operator<<, when merged ADE-285
+ const auto& p = buffer.priv();
+ os << "Fluid buffer " << std::hex << &buffer << std::dec
+ << " " << p.m_desc.size.width << " x " << p.m_desc.size.height << "]"
+ << " readStart:" << p.m_readStart
+ << " roi:" << "[" << p.m_roi.width << " x " << p.m_roi.height << " from (" << p.m_roi.x << ", " << p.m_roi.y << ")]"
+ <<" (phys " << "[" << p.storage().cols() << " x " << p.storage().rows() << "]" << ") :"
+ << " w: " << p.m_write_caret
+ << ", r: [";
+ for (const auto &v : p.m_views) { os << &v.priv() << ":" << v.y() << " "; }
+ os << "], avail: " << buffer.linesReady()
+ << std::endl;
+}
+
+void fluid::Buffer::debug(std::ostream &os) const
+{
+ debugBufferPriv(*this, os);
+}
+
+fluid::Buffer::Priv& fluid::Buffer::priv()
+{
+ return *m_priv;
+}
+
+const fluid::Buffer::Priv& fluid::Buffer::priv() const
+{
+ return *m_priv;
+}
+
+int fluid::Buffer::y() const
+{
+ return m_priv->y();
+}
+
+} // namespace cv::gapi
+} // namespace cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer_priv.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer_priv.hpp
new file mode 100644
index 000000000..1f3eadc11
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidbuffer_priv.hpp
@@ -0,0 +1,308 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_FLUID_BUFFER_PRIV_HPP
+#define OPENCV_GAPI_FLUID_BUFFER_PRIV_HPP
+
+#include <vector>
+
+#include "opencv2/gapi/fluid/gfluidbuffer.hpp"
+#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS
+
+namespace cv {
+namespace gapi {
+namespace fluid {
+
+class BufferStorageWithBorder;
+
+class BorderHandler
+{
+protected:
+ int m_border_size;
+
+public:
+ BorderHandler(int border_size);
+ virtual ~BorderHandler() = default;
+ virtual const uint8_t* inLineB(int log_idx, const BufferStorageWithBorder &data, int desc_height) const = 0;
+
+ // Fills border pixels after buffer allocation (if possible (for const border))
+ inline virtual void fillCompileTimeBorder(BufferStorageWithBorder &) { /* nothing */ }
+
+ // Fills required border lines
+ inline virtual void updateBorderPixels(BufferStorageWithBorder& /*data*/, int /*startLine*/, int /*lpi*/) const { /* nothing */ }
+
+ inline int borderSize() const { return m_border_size; }
+ inline virtual std::size_t size() const { return 0; }
+};
+
+template<int BorderType>
+class BorderHandlerT : public BorderHandler
+{
+ std::function<void(uint8_t*,int,int,int)> m_fill_border_row;
+public:
+ BorderHandlerT(int border_size, int data_type);
+ virtual void updateBorderPixels(BufferStorageWithBorder& data, int startLine, int lpi) const override;
+ virtual const uint8_t* inLineB(int log_idx, const BufferStorageWithBorder &data, int desc_height) const override;
+};
+
+template<>
+class BorderHandlerT<cv::BORDER_CONSTANT> : public BorderHandler
+{
+ cv::gapi::own::Scalar m_border_value;
+ cv::gapi::own::Mat m_const_border;
+
+public:
+ BorderHandlerT(int border_size, cv::gapi::own::Scalar border_value);
+ virtual const uint8_t* inLineB(int log_idx, const BufferStorageWithBorder &data, int desc_height) const override;
+ virtual void fillCompileTimeBorder(BufferStorageWithBorder &) override;
+ virtual std::size_t size() const override;
+};
+
+class BufferStorage
+{
+protected:
+ cv::gapi::own::Mat m_data;
+
+public:
+ void updateInCache(View::Cache& cache, int start_log_idx, int nLines) const;
+ void updateOutCache(Buffer::Cache& cache, int start_log_idx, int nLines);
+
+ virtual void copyTo(BufferStorageWithBorder &dst, int startLine, int nLines) const = 0;
+
+ virtual ~BufferStorage() = default;
+
+ virtual const uint8_t* ptr(int idx) const = 0;
+ virtual uint8_t* ptr(int idx) = 0;
+
+ inline bool empty() const { return m_data.empty(); }
+
+ inline const cv::gapi::own::Mat& data() const { return m_data; }
+ inline cv::gapi::own::Mat& data() { return m_data; }
+
+ inline int rows() const { return m_data.rows; }
+ inline int cols() const { return m_data.cols; }
+ inline int type() const { return m_data.type(); }
+
+ virtual const uint8_t* inLineB(int log_idx, int desc_height) const = 0;
+
+ // FIXME? remember parent and remove src parameter?
+ virtual void updateBeforeRead(int startLine, int nLines, const BufferStorage& src) = 0;
+ virtual void updateAfterWrite(int startLine, int nLines) = 0;
+
+ virtual inline int physIdx(int logIdx) const = 0;
+
+ virtual size_t size() const = 0;
+};
+
+class BufferStorageWithoutBorder final : public BufferStorage
+{
+ bool m_is_virtual = true;
+ cv::gapi::own::Rect m_roi;
+
+public:
+ virtual void copyTo(BufferStorageWithBorder &dst, int startLine, int nLines) const override;
+
+ inline virtual const uint8_t* ptr(int idx) const override
+ {
+ GAPI_DbgAssert((m_is_virtual && m_roi == cv::gapi::own::Rect{}) || (!m_is_virtual && m_roi != cv::gapi::own::Rect{}));
+ return m_data.ptr(physIdx(idx), 0);
+ }
+ inline virtual uint8_t* ptr(int idx) override
+ {
+ GAPI_DbgAssert((m_is_virtual && m_roi == cv::gapi::own::Rect{}) || (!m_is_virtual && m_roi != cv::gapi::own::Rect{}));
+ return m_data.ptr(physIdx(idx), 0);
+ }
+
+ inline void attach(const cv::gapi::own::Mat& _data, cv::gapi::own::Rect _roi)
+ {
+ m_data = _data(_roi);
+ m_roi = _roi;
+ m_is_virtual = false;
+ }
+
+ void create(int capacity, int desc_width, int type);
+
+ inline virtual const uint8_t* inLineB(int log_idx, int /*desc_height*/) const override { return ptr(log_idx); }
+
+ virtual void updateBeforeRead(int startLine, int nLines, const BufferStorage& src) override;
+ virtual void updateAfterWrite(int startLine, int nLines) override;
+
+ inline virtual int physIdx(int logIdx) const override { return (logIdx - m_roi.y) % m_data.rows; }
+
+ virtual size_t size() const override;
+};
+
+class BufferStorageWithBorder final: public BufferStorage
+{
+ std::unique_ptr<BorderHandler> m_borderHandler;
+
+public:
+ inline int borderSize() const { return m_borderHandler->borderSize(); }
+
+ virtual void copyTo(BufferStorageWithBorder &dst, int startLine, int nLines) const override;
+
+ inline virtual const uint8_t* ptr(int idx) const override
+ {
+ return m_data.ptr(physIdx(idx), borderSize());
+ }
+ inline virtual uint8_t* ptr(int idx) override
+ {
+ return m_data.ptr(physIdx(idx), borderSize());
+ }
+
+ void init(int depth, int border_size, Border border);
+ void create(int capacity, int desc_width, int dtype);
+
+ virtual const uint8_t* inLineB(int log_idx, int desc_height) const override;
+
+ virtual void updateBeforeRead(int startLine, int nLines, const BufferStorage &src) override;
+ virtual void updateAfterWrite(int startLine, int nLines) override;
+
+ inline virtual int physIdx(int logIdx) const override { return logIdx % m_data.rows; }
+
+ virtual size_t size() const override;
+};
+
+// FIXME: GAPI_EXPORTS is used here only to access internal methods
+// like readDone/writeDone in low-level tests
+class GAPI_EXPORTS View::Priv
+{
+ friend class View;
+protected:
+ View::Cache m_cache;
+
+ const Buffer *m_p = nullptr; // FIXME replace with weak_ptr
+ int m_read_caret = -1;
+ int m_lines_next_iter = -1;
+ int m_border_size = -1;
+
+public:
+ virtual ~Priv() = default;
+ // API used by actors/backend
+
+ const View::Cache& cache() const { return m_cache; }
+ void initCache(int lineConsumption);
+
+ virtual void allocate(int lineConsumption, BorderOpt border) = 0;
+ virtual void prepareToRead() = 0;
+
+ void readDone(int linesRead, int linesForNextIteration);
+ void reset(int linesForFirstIteration);
+
+ virtual std::size_t size() const = 0;
+
+ // Does the view have enough unread lines for next iteration
+ bool ready() const;
+
+ // API used (indirectly) by user code
+ virtual const uint8_t* InLineB(int index) const = 0;
+};
+
+class ViewPrivWithoutOwnBorder final : public View::Priv
+{
+public:
+ // API used by actors/backend
+ ViewPrivWithoutOwnBorder(const Buffer *p, int borderSize);
+
+ virtual void allocate(int lineConsumption, BorderOpt) override;
+ virtual void prepareToRead() override;
+
+ inline virtual std::size_t size() const override { return 0; }
+
+ // API used (indirectly) by user code
+ virtual const uint8_t* InLineB(int index) const override;
+};
+
+class ViewPrivWithOwnBorder final : public View::Priv
+{
+ BufferStorageWithBorder m_own_storage;
+
+public:
+ // API used by actors/backend
+ ViewPrivWithOwnBorder(const Buffer *p, int borderSize);
+
+ virtual void allocate(int lineConsumption, BorderOpt border) override;
+ virtual void prepareToRead() override;
+ virtual std::size_t size() const override;
+
+ // API used (indirectly) by user code
+ virtual const uint8_t* InLineB(int index) const override;
+};
+
+void debugBufferPriv(const Buffer& buffer, std::ostream &os);
+
+// FIXME: GAPI_EXPORTS is used here only to access internal methods
+// like readDone/writeDone in low-level tests
+class GAPI_EXPORTS Buffer::Priv
+{
+ Buffer::Cache m_cache;
+
+ int m_writer_lpi = 1;
+
+ cv::GMatDesc m_desc = cv::GMatDesc{-1,-1,{-1,-1}};
+ bool m_is_input = false;
+
+ int m_write_caret = -1;
+
+ std::vector<View> m_views;
+
+ std::unique_ptr<BufferStorage> m_storage;
+
+ // Coordinate starting from which this buffer is assumed
+ // to be read (with border not being taken into account)
+ int m_readStart;
+ cv::gapi::own::Rect m_roi;
+
+ friend void debugBufferPriv(const Buffer& p, std::ostream &os);
+
+public:
+ Priv() = default;
+ Priv(int read_start, cv::gapi::own::Rect roi);
+
+ inline const BufferStorage& storage() const { return *m_storage.get(); }
+
+ // API used by actors/backend
+ void init(const cv::GMatDesc &desc,
+ int writer_lpi,
+ int readStart,
+ cv::gapi::own::Rect roi);
+
+ void allocate(BorderOpt border, int border_size, int line_consumption, int skew);
+ void bindTo(const cv::gapi::own::Mat &data, bool is_input);
+
+ inline void addView(const View& view) { m_views.push_back(view); }
+
+ inline const GMatDesc& meta() const { return m_desc; }
+
+ bool full() const;
+ void writeDone();
+ void reset();
+ int size() const;
+
+ int linesReady() const;
+
+ inline int y() const { return m_write_caret; }
+
+ inline int writer_lpi() const { return m_writer_lpi; }
+
+ // API used (indirectly) by user code
+ uint8_t* OutLineB(int index = 0);
+ int lpi() const;
+
+ inline int readStart() const { return m_readStart; }
+ inline int writeStart() const { return m_roi.y; }
+ inline int writeEnd() const { return m_roi.y + m_roi.height; }
+ inline int outputLines() const { return m_roi.height; }
+
+ inline const Buffer::Cache& cache() const { return m_cache; }
+};
+
+} // namespace cv::gapi::fluid
+} // namespace cv::gapi
+} // namespace cv
+
+#endif // OPENCV_GAPI_FLUID_BUFFER_PRIV_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidcore.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidcore.cpp
new file mode 100644
index 000000000..16a63e217
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidcore.cpp
@@ -0,0 +1,2193 @@
+// 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) 2018 Intel Corporation
+
+#if !defined(GAPI_STANDALONE)
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/own/assert.hpp"
+#include "opencv2/core/traits.hpp"
+#include "opencv2/core/hal/hal.hpp"
+#include "opencv2/core/hal/intrin.hpp"
+
+#include "opencv2/gapi/core.hpp"
+
+#include "opencv2/gapi/fluid/gfluidbuffer.hpp"
+#include "opencv2/gapi/fluid/gfluidkernel.hpp"
+#include "opencv2/gapi/fluid/core.hpp"
+
+#include "gfluidbuffer_priv.hpp"
+#include "gfluidbackend.hpp"
+#include "gfluidutils.hpp"
+
+#include <cassert>
+#include <cmath>
+#include <cstdlib>
+
+namespace cv {
+namespace gapi {
+namespace fluid {
+
+//---------------------
+//
+// Arithmetic functions
+//
+//---------------------
+
+template<typename DST, typename SRC1, typename SRC2>
+static inline DST absdiff(SRC1 x, SRC2 y)
+{
+ auto result = x > y? x - y: y - x;
+ return saturate<DST>(result, roundf);
+}
+
+template<typename DST, typename SRC1, typename SRC2>
+static inline DST addWeighted(SRC1 src1, SRC2 src2, float alpha, float beta, float gamma)
+{
+ float dst = src1*alpha + src2*beta + gamma;
+ return saturate<DST>(dst, roundf);
+}
+
+template<typename DST, typename SRC1, typename SRC2>
+static inline DST add(SRC1 x, SRC2 y)
+{
+ return saturate<DST>(x + y, roundf);
+}
+
+template<typename DST, typename SRC1, typename SRC2>
+static inline DST sub(SRC1 x, SRC2 y)
+{
+ return saturate<DST>(x - y, roundf);
+}
+
+template<typename DST, typename SRC1, typename SRC2>
+static inline DST subr(SRC1 x, SRC2 y)
+{
+ return saturate<DST>(y - x, roundf); // reverse: y - x
+}
+
+template<typename DST, typename SRC1, typename SRC2>
+static inline DST mul(SRC1 x, SRC2 y, float scale=1)
+{
+ auto result = scale * x * y;
+ return saturate<DST>(result, rintf);
+}
+
+template<typename DST, typename SRC1, typename SRC2>
+static inline DST div(SRC1 x, SRC2 y, float scale=1)
+{
+ // like OpenCV: returns 0, if y=0
+ auto result = y? scale * x / y: 0;
+ return saturate<DST>(result, rintf);
+}
+
+template<typename DST, typename SRC1, typename SRC2>
+static inline DST divr(SRC1 x, SRC2 y, float scale=1)
+{
+ auto result = x? scale * y / x: 0; // reverse: y / x
+ return saturate<DST>(result, rintf);
+}
+
+//---------------------------
+//
+// Fluid kernels: addWeighted
+//
+//---------------------------
+
+template<typename DST, typename SRC1, typename SRC2>
+static void run_addweighted(Buffer &dst, const View &src1, const View &src2,
+ double alpha, double beta, double gamma)
+{
+ static_assert(std::is_same<SRC1, SRC2>::value, "wrong types");
+
+ const auto *in1 = src1.InLine<SRC1>(0);
+ const auto *in2 = src2.InLine<SRC2>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+ int length = width * chan;
+
+ // NB: assume in/out types are not 64-bits
+ auto _alpha = static_cast<float>( alpha );
+ auto _beta = static_cast<float>( beta );
+ auto _gamma = static_cast<float>( gamma );
+
+ for (int l=0; l < length; l++)
+ out[l] = addWeighted<DST>(in1[l], in2[l], _alpha, _beta, _gamma);
+}
+
+GAPI_FLUID_KERNEL(GFluidAddW, cv::gapi::core::GAddW, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, double alpha, const View &src2,
+ double beta, double gamma, int /*dtype*/,
+ Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_addweighted, dst, src1, src2, alpha, beta, gamma);
+ BINARY_(uchar , ushort, ushort, run_addweighted, dst, src1, src2, alpha, beta, gamma);
+ BINARY_(uchar , short, short, run_addweighted, dst, src1, src2, alpha, beta, gamma);
+ BINARY_( short, short, short, run_addweighted, dst, src1, src2, alpha, beta, gamma);
+ BINARY_(ushort, ushort, ushort, run_addweighted, dst, src1, src2, alpha, beta, gamma);
+ BINARY_( float, uchar , uchar , run_addweighted, dst, src1, src2, alpha, beta, gamma);
+ BINARY_( float, ushort, ushort, run_addweighted, dst, src1, src2, alpha, beta, gamma);
+ BINARY_( float, short, short, run_addweighted, dst, src1, src2, alpha, beta, gamma);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//--------------------------
+//
+// Fluid kernels: +, -, *, /
+//
+//--------------------------
+
+enum Arithm { ARITHM_ABSDIFF, ARITHM_ADD, ARITHM_SUBTRACT, ARITHM_MULTIPLY, ARITHM_DIVIDE };
+
+template<typename DST, typename SRC1, typename SRC2>
+static void run_arithm(Buffer &dst, const View &src1, const View &src2, Arithm arithm,
+ double scale=1)
+{
+ static_assert(std::is_same<SRC1, SRC2>::value, "wrong types");
+
+ const auto *in1 = src1.InLine<SRC1>(0);
+ const auto *in2 = src2.InLine<SRC2>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+ int length = width * chan;
+
+ // NB: assume in/out types are not 64-bits
+ float _scale = static_cast<float>( scale );
+
+ switch (arithm)
+ {
+ case ARITHM_ABSDIFF:
+ for (int l=0; l < length; l++)
+ out[l] = absdiff<DST>(in1[l], in2[l]);
+ break;
+ case ARITHM_ADD:
+ for (int l=0; l < length; l++)
+ out[l] = add<DST>(in1[l], in2[l]);
+ break;
+ case ARITHM_SUBTRACT:
+ for (int l=0; l < length; l++)
+ out[l] = sub<DST>(in1[l], in2[l]);
+ break;
+ case ARITHM_MULTIPLY:
+ for (int l=0; l < length; l++)
+ out[l] = mul<DST>(in1[l], in2[l], _scale);
+ break;
+ case ARITHM_DIVIDE:
+ for (int l=0; l < length; l++)
+ out[l] = div<DST>(in1[l], in2[l], _scale);
+ break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported arithmetic operation");
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidAdd, cv::gapi::core::GAdd, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, int /*dtype*/, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_arithm, dst, src1, src2, ARITHM_ADD);
+ BINARY_(uchar , short, short, run_arithm, dst, src1, src2, ARITHM_ADD);
+ BINARY_(uchar , float, float, run_arithm, dst, src1, src2, ARITHM_ADD);
+ BINARY_( short, short, short, run_arithm, dst, src1, src2, ARITHM_ADD);
+ BINARY_( float, uchar , uchar , run_arithm, dst, src1, src2, ARITHM_ADD);
+ BINARY_( float, short, short, run_arithm, dst, src1, src2, ARITHM_ADD);
+ BINARY_( float, float, float, run_arithm, dst, src1, src2, ARITHM_ADD);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidSub, cv::gapi::core::GSub, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, int /*dtype*/, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_arithm, dst, src1, src2, ARITHM_SUBTRACT);
+ BINARY_(uchar , short, short, run_arithm, dst, src1, src2, ARITHM_SUBTRACT);
+ BINARY_(uchar , float, float, run_arithm, dst, src1, src2, ARITHM_SUBTRACT);
+ BINARY_( short, short, short, run_arithm, dst, src1, src2, ARITHM_SUBTRACT);
+ BINARY_( float, uchar , uchar , run_arithm, dst, src1, src2, ARITHM_SUBTRACT);
+ BINARY_( float, short, short, run_arithm, dst, src1, src2, ARITHM_SUBTRACT);
+ BINARY_( float, float, float, run_arithm, dst, src1, src2, ARITHM_SUBTRACT);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidMul, cv::gapi::core::GMul, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, double scale, int /*dtype*/, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_arithm, dst, src1, src2, ARITHM_MULTIPLY, scale);
+ BINARY_(uchar , short, short, run_arithm, dst, src1, src2, ARITHM_MULTIPLY, scale);
+ BINARY_(uchar , float, float, run_arithm, dst, src1, src2, ARITHM_MULTIPLY, scale);
+ BINARY_( short, short, short, run_arithm, dst, src1, src2, ARITHM_MULTIPLY, scale);
+ BINARY_( float, uchar , uchar , run_arithm, dst, src1, src2, ARITHM_MULTIPLY, scale);
+ BINARY_( float, short, short, run_arithm, dst, src1, src2, ARITHM_MULTIPLY, scale);
+ BINARY_( float, float, float, run_arithm, dst, src1, src2, ARITHM_MULTIPLY, scale);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidDiv, cv::gapi::core::GDiv, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, double scale, int /*dtype*/, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_arithm, dst, src1, src2, ARITHM_DIVIDE, scale);
+ BINARY_(uchar , short, short, run_arithm, dst, src1, src2, ARITHM_DIVIDE, scale);
+ BINARY_(uchar , float, float, run_arithm, dst, src1, src2, ARITHM_DIVIDE, scale);
+ BINARY_( short, short, short, run_arithm, dst, src1, src2, ARITHM_DIVIDE, scale);
+ BINARY_( float, uchar , uchar , run_arithm, dst, src1, src2, ARITHM_DIVIDE, scale);
+ BINARY_( float, short, short, run_arithm, dst, src1, src2, ARITHM_DIVIDE, scale);
+ BINARY_( float, float, float, run_arithm, dst, src1, src2, ARITHM_DIVIDE, scale);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidAbsDiff, cv::gapi::core::GAbsDiff, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_arithm, dst, src1, src2, ARITHM_ABSDIFF);
+ BINARY_(ushort, ushort, ushort, run_arithm, dst, src1, src2, ARITHM_ABSDIFF);
+ BINARY_( short, short, short, run_arithm, dst, src1, src2, ARITHM_ABSDIFF);
+ BINARY_( float, float, float, run_arithm, dst, src1, src2, ARITHM_ABSDIFF);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//--------------------------------------
+//
+// Fluid kernels: +, -, *, / with Scalar
+//
+//--------------------------------------
+
+static inline v_uint16x8 v_add_16u(const v_uint16x8 &x, const v_uint16x8 &y) { return x + y; }
+static inline v_uint16x8 v_sub_16u(const v_uint16x8 &x, const v_uint16x8 &y) { return x - y; }
+static inline v_uint16x8 v_subr_16u(const v_uint16x8 &x, const v_uint16x8 &y) { return y - x; }
+
+static inline v_float32x4 v_add_32f(const v_float32x4 &x, const v_float32x4 &y) { return x + y; }
+static inline v_float32x4 v_sub_32f(const v_float32x4 &x, const v_float32x4 &y) { return x - y; }
+static inline v_float32x4 v_subr_32f(const v_float32x4 &x, const v_float32x4 &y) { return y - x; }
+
+static inline int s_add_8u(uchar x, uchar y) { return x + y; }
+static inline int s_sub_8u(uchar x, uchar y) { return x - y; }
+static inline int s_subr_8u(uchar x, uchar y) { return y - x; }
+
+static inline float s_add_32f(float x, float y) { return x + y; }
+static inline float s_sub_32f(float x, float y) { return x - y; }
+static inline float s_subr_32f(float x, float y) { return y - x; }
+
+// manual SIMD if important case 8UC3
+static void run_arithm_s3(uchar out[], const uchar in[], int width, const uchar scalar[],
+ v_uint16x8 (*v_op)(const v_uint16x8&, const v_uint16x8&),
+ int (*s_op)(uchar, uchar))
+{
+ int w = 0;
+
+#if CV_SIMD128
+ for (; w <= width-16; w+=16)
+ {
+ v_uint8x16 x, y, z;
+ v_load_deinterleave(&in[3*w], x, y, z);
+
+ v_uint16x8 r0, r1;
+
+ v_expand(x, r0, r1);
+ r0 = v_op(r0, v_setall_u16(scalar[0])); // x + scalar[0]
+ r1 = v_op(r1, v_setall_u16(scalar[0]));
+ x = v_pack(r0, r1);
+
+ v_expand(y, r0, r1);
+ r0 = v_op(r0, v_setall_u16(scalar[1])); // y + scalar[1]
+ r1 = v_op(r1, v_setall_u16(scalar[1]));
+ y = v_pack(r0, r1);
+
+ v_expand(z, r0, r1);
+ r0 = v_op(r0, v_setall_u16(scalar[2])); // z + scalar[2]
+ r1 = v_op(r1, v_setall_u16(scalar[2]));
+ z = v_pack(r0, r1);
+
+ v_store_interleave(&out[3*w], x, y, z);
+ }
+#endif
+ UNUSED(v_op);
+ for (; w < width; w++)
+ {
+ out[3*w ] = saturate<uchar>( s_op(in[3*w ], scalar[0]) );
+ out[3*w + 1] = saturate<uchar>( s_op(in[3*w + 1], scalar[1]) );
+ out[3*w + 2] = saturate<uchar>( s_op(in[3*w + 2], scalar[2]) );
+ }
+}
+
+// manually SIMD if rounding 32F into 8U, single channel
+static void run_arithm_s1(uchar out[], const float in[], int width, const float scalar[],
+ v_float32x4 (*v_op)(const v_float32x4&, const v_float32x4&),
+ float (*s_op)(float, float))
+{
+ int w = 0;
+
+#if CV_SIMD128
+ for (; w <= width-16; w+=16)
+ {
+ v_float32x4 r0, r1, r2, r3;
+ r0 = v_load(&in[w ]);
+ r1 = v_load(&in[w + 4]);
+ r2 = v_load(&in[w + 8]);
+ r3 = v_load(&in[w + 12]);
+
+ r0 = v_op(r0, v_setall_f32(scalar[0])); // r + scalar[0]
+ r1 = v_op(r1, v_setall_f32(scalar[0]));
+ r2 = v_op(r2, v_setall_f32(scalar[0]));
+ r3 = v_op(r3, v_setall_f32(scalar[0]));
+
+ v_int32x4 i0, i1, i2, i3;
+ i0 = v_round(r0);
+ i1 = v_round(r1);
+ i2 = v_round(r2);
+ i3 = v_round(r3);
+
+ v_uint16x8 us0, us1;
+ us0 = v_pack_u(i0, i1);
+ us1 = v_pack_u(i2, i3);
+
+ v_uint8x16 uc;
+ uc = v_pack(us0, us1);
+
+ v_store(&out[w], uc);
+ }
+#endif
+ UNUSED(v_op);
+ for (; w < width; w++)
+ {
+ out[w] = saturate<uchar>(s_op(in[w], scalar[0]), std::roundf);
+ }
+}
+
+static void run_arithm_s_add3(uchar out[], const uchar in[], int width, const uchar scalar[])
+{
+ run_arithm_s3(out, in, width, scalar, v_add_16u, s_add_8u);
+}
+
+static void run_arithm_s_sub3(uchar out[], const uchar in[], int width, const uchar scalar[])
+{
+ run_arithm_s3(out, in, width, scalar, v_sub_16u, s_sub_8u);
+}
+
+static void run_arithm_s_subr3(uchar out[], const uchar in[], int width, const uchar scalar[])
+{
+ run_arithm_s3(out, in, width, scalar, v_subr_16u, s_subr_8u); // reverse: subr
+}
+
+static void run_arithm_s_add1(uchar out[], const float in[], int width, const float scalar[])
+{
+ run_arithm_s1(out, in, width, scalar, v_add_32f, s_add_32f);
+}
+
+static void run_arithm_s_sub1(uchar out[], const float in[], int width, const float scalar[])
+{
+ run_arithm_s1(out, in, width, scalar, v_sub_32f, s_sub_32f);
+}
+
+static void run_arithm_s_subr1(uchar out[], const float in[], int width, const float scalar[])
+{
+ run_arithm_s1(out, in, width, scalar, v_subr_32f, s_subr_32f); // reverse: subr
+}
+
+// manually unroll the inner cycle by channels
+template<typename DST, typename SRC, typename SCALAR, typename FUNC>
+static void run_arithm_s(DST out[], const SRC in[], int width, int chan,
+ const SCALAR scalar[4], FUNC func)
+{
+ if (chan == 4)
+ {
+ for (int w=0; w < width; w++)
+ {
+ out[4*w + 0] = func(in[4*w + 0], scalar[0]);
+ out[4*w + 1] = func(in[4*w + 1], scalar[1]);
+ out[4*w + 2] = func(in[4*w + 2], scalar[2]);
+ out[4*w + 3] = func(in[4*w + 3], scalar[3]);
+ }
+ }
+ else
+ if (chan == 3)
+ {
+ for (int w=0; w < width; w++)
+ {
+ out[3*w + 0] = func(in[3*w + 0], scalar[0]);
+ out[3*w + 1] = func(in[3*w + 1], scalar[1]);
+ out[3*w + 2] = func(in[3*w + 2], scalar[2]);
+ }
+ }
+ else
+ if (chan == 2)
+ {
+ for (int w=0; w < width; w++)
+ {
+ out[2*w + 0] = func(in[2*w + 0], scalar[0]);
+ out[2*w + 1] = func(in[2*w + 1], scalar[1]);
+ }
+ }
+ else
+ if (chan == 1)
+ {
+ for (int w=0; w < width; w++)
+ {
+ out[w] = func(in[w], scalar[0]);
+ }
+ }
+ else
+ CV_Error(cv::Error::StsBadArg, "unsupported number of channels");
+}
+
+template<typename DST, typename SRC>
+static void run_arithm_s(Buffer &dst, const View &src, const float scalar[4], Arithm arithm,
+ float scale=1)
+{
+ const auto *in = src.InLine<SRC>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ // What if we cast the scalar into the SRC type?
+ const SRC myscal[4] = { static_cast<SRC>(scalar[0]), static_cast<SRC>(scalar[1]),
+ static_cast<SRC>(scalar[2]), static_cast<SRC>(scalar[3]) };
+ bool usemyscal = (myscal[0] == scalar[0]) && (myscal[1] == scalar[1]) &&
+ (myscal[2] == scalar[2]) && (myscal[3] == scalar[3]);
+
+ switch (arithm)
+ {
+ case ARITHM_ABSDIFF:
+ for (int w=0; w < width; w++)
+ for (int c=0; c < chan; c++)
+ out[chan*w + c] = absdiff<DST>(in[chan*w + c], scalar[c]);
+ break;
+ case ARITHM_ADD:
+ if (usemyscal)
+ {
+ if (std::is_same<DST,uchar>::value &&
+ std::is_same<SRC,uchar>::value &&
+ chan == 3)
+ run_arithm_s_add3((uchar*)out, (const uchar*)in, width, (const uchar*)myscal);
+ else if (std::is_same<DST,uchar>::value &&
+ std::is_same<SRC,float>::value &&
+ chan == 1)
+ run_arithm_s_add1((uchar*)out, (const float*)in, width, (const float*)myscal);
+ else
+ run_arithm_s(out, in, width, chan, myscal, add<DST,SRC,SRC>);
+ }
+ else
+ run_arithm_s(out, in, width, chan, scalar, add<DST,SRC,float>);
+ break;
+ case ARITHM_SUBTRACT:
+ if (usemyscal)
+ {
+ if (std::is_same<DST,uchar>::value &&
+ std::is_same<SRC,uchar>::value &&
+ chan == 3)
+ run_arithm_s_sub3((uchar*)out, (const uchar*)in, width, (const uchar*)myscal);
+ else if (std::is_same<DST,uchar>::value &&
+ std::is_same<SRC,float>::value &&
+ chan == 1)
+ run_arithm_s_sub1((uchar*)out, (const float*)in, width, (const float*)myscal);
+ else
+ run_arithm_s(out, in, width, chan, myscal, sub<DST,SRC,SRC>);
+ }
+ else
+ run_arithm_s(out, in, width, chan, scalar, sub<DST,SRC,float>);
+ break;
+ // TODO: optimize miltiplication and division
+ case ARITHM_MULTIPLY:
+ for (int w=0; w < width; w++)
+ for (int c=0; c < chan; c++)
+ out[chan*w + c] = mul<DST>(in[chan*w + c], scalar[c], scale);
+ break;
+ case ARITHM_DIVIDE:
+ for (int w=0; w < width; w++)
+ for (int c=0; c < chan; c++)
+ out[chan*w + c] = div<DST>(in[chan*w + c], scalar[c], scale);
+ break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported arithmetic operation");
+ }
+}
+
+template<typename DST, typename SRC>
+static void run_arithm_rs(Buffer &dst, const View &src, const float scalar[4], Arithm arithm,
+ float scale=1)
+{
+ const auto *in = src.InLine<SRC>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ // What if we cast the scalar into the SRC type?
+ const SRC myscal[4] = { static_cast<SRC>(scalar[0]), static_cast<SRC>(scalar[1]),
+ static_cast<SRC>(scalar[2]), static_cast<SRC>(scalar[3]) };
+ bool usemyscal = (myscal[0] == scalar[0]) && (myscal[1] == scalar[1]) &&
+ (myscal[2] == scalar[2]) && (myscal[3] == scalar[3]);
+
+ switch (arithm)
+ {
+ case ARITHM_SUBTRACT:
+ if (usemyscal)
+ {
+ if (std::is_same<DST,uchar>::value &&
+ std::is_same<SRC,uchar>::value &&
+ chan == 3)
+ run_arithm_s_subr3((uchar*)out, (const uchar*)in, width, (const uchar*)myscal);
+ else if (std::is_same<DST,uchar>::value &&
+ std::is_same<SRC,float>::value &&
+ chan == 1)
+ run_arithm_s_subr1((uchar*)out, (const float*)in, width, (const float*)myscal);
+ else
+ run_arithm_s(out, in, width, chan, myscal, subr<DST,SRC,SRC>);
+ }
+ else
+ run_arithm_s(out, in, width, chan, scalar, subr<DST,SRC,float>);
+ break;
+ // TODO: optimize division
+ case ARITHM_DIVIDE:
+ for (int w=0; w < width; w++)
+ for (int c=0; c < chan; c++)
+ out[chan*w + c] = div<DST>(scalar[c], in[chan*w + c], scale);
+ break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported arithmetic operation");
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidAbsDiffC, cv::gapi::core::GAbsDiffC, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &_scalar, Buffer &dst)
+ {
+ const float scalar[4] = {
+ static_cast<float>(_scalar[0]),
+ static_cast<float>(_scalar[1]),
+ static_cast<float>(_scalar[2]),
+ static_cast<float>(_scalar[3])
+ };
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_arithm_s, dst, src, scalar, ARITHM_ABSDIFF);
+ UNARY_(ushort, ushort, run_arithm_s, dst, src, scalar, ARITHM_ABSDIFF);
+ UNARY_( short, short, run_arithm_s, dst, src, scalar, ARITHM_ABSDIFF);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidAddC, cv::gapi::core::GAddC, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &_scalar, int /*dtype*/, Buffer &dst)
+ {
+ const float scalar[4] = {
+ static_cast<float>(_scalar[0]),
+ static_cast<float>(_scalar[1]),
+ static_cast<float>(_scalar[2]),
+ static_cast<float>(_scalar[3])
+ };
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_arithm_s, dst, src, scalar, ARITHM_ADD);
+ UNARY_(uchar , short, run_arithm_s, dst, src, scalar, ARITHM_ADD);
+ UNARY_(uchar , float, run_arithm_s, dst, src, scalar, ARITHM_ADD);
+ UNARY_( short, short, run_arithm_s, dst, src, scalar, ARITHM_ADD);
+ UNARY_( float, uchar , run_arithm_s, dst, src, scalar, ARITHM_ADD);
+ UNARY_( float, short, run_arithm_s, dst, src, scalar, ARITHM_ADD);
+ UNARY_( float, float, run_arithm_s, dst, src, scalar, ARITHM_ADD);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidSubC, cv::gapi::core::GSubC, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &_scalar, int /*dtype*/, Buffer &dst)
+ {
+ const float scalar[4] = {
+ static_cast<float>(_scalar[0]),
+ static_cast<float>(_scalar[1]),
+ static_cast<float>(_scalar[2]),
+ static_cast<float>(_scalar[3])
+ };
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_arithm_s, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_(uchar , short, run_arithm_s, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_(uchar , float, run_arithm_s, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_( short, short, run_arithm_s, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_( float, uchar , run_arithm_s, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_( float, short, run_arithm_s, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_( float, float, run_arithm_s, dst, src, scalar, ARITHM_SUBTRACT);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidSubRC, cv::gapi::core::GSubRC, false)
+{
+ static const int Window = 1;
+
+ static void run(const cv::Scalar &_scalar, const View &src, int /*dtype*/, Buffer &dst)
+ {
+ const float scalar[4] = {
+ static_cast<float>(_scalar[0]),
+ static_cast<float>(_scalar[1]),
+ static_cast<float>(_scalar[2]),
+ static_cast<float>(_scalar[3])
+ };
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_arithm_rs, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_(uchar , short, run_arithm_rs, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_(uchar , float, run_arithm_rs, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_( short, short, run_arithm_rs, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_( float, uchar , run_arithm_rs, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_( float, short, run_arithm_rs, dst, src, scalar, ARITHM_SUBTRACT);
+ UNARY_( float, float, run_arithm_rs, dst, src, scalar, ARITHM_SUBTRACT);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidMulC, cv::gapi::core::GMulC, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &_scalar, int /*dtype*/, Buffer &dst)
+ {
+ const float scalar[4] = {
+ static_cast<float>(_scalar[0]),
+ static_cast<float>(_scalar[1]),
+ static_cast<float>(_scalar[2]),
+ static_cast<float>(_scalar[3])
+ };
+ const float scale = 1.f;
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_(uchar , short, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_(uchar , float, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_( short, short, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_( float, uchar , run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_( float, short, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_( float, float, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidMulCOld, cv::gapi::core::GMulCOld, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, double _scalar, int /*dtype*/, Buffer &dst)
+ {
+ const float scalar[4] = {
+ static_cast<float>(_scalar),
+ static_cast<float>(_scalar),
+ static_cast<float>(_scalar),
+ static_cast<float>(_scalar)
+ };
+ const float scale = 1.f;
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_(uchar , short, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_(uchar , float, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_( short, short, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_( float, uchar , run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_( float, short, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+ UNARY_( float, float, run_arithm_s, dst, src, scalar, ARITHM_MULTIPLY, scale);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidDivC, cv::gapi::core::GDivC, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &_scalar, double _scale, int /*dtype*/,
+ Buffer &dst)
+ {
+ const float scalar[4] = {
+ static_cast<float>(_scalar[0]),
+ static_cast<float>(_scalar[1]),
+ static_cast<float>(_scalar[2]),
+ static_cast<float>(_scalar[3])
+ };
+ const float scale = static_cast<float>(_scale);
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_arithm_s, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_(uchar , short, run_arithm_s, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_(uchar , float, run_arithm_s, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_( short, short, run_arithm_s, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_( float, uchar , run_arithm_s, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_( float, short, run_arithm_s, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_( float, float, run_arithm_s, dst, src, scalar, ARITHM_DIVIDE, scale);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidDivRC, cv::gapi::core::GDivRC, false)
+{
+ static const int Window = 1;
+
+ static void run(const cv::Scalar &_scalar, const View &src, double _scale, int /*dtype*/,
+ Buffer &dst)
+ {
+ const float scalar[4] = {
+ static_cast<float>(_scalar[0]),
+ static_cast<float>(_scalar[1]),
+ static_cast<float>(_scalar[2]),
+ static_cast<float>(_scalar[3])
+ };
+ const float scale = static_cast<float>(_scale);
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_arithm_rs, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_(uchar , short, run_arithm_rs, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_(uchar , float, run_arithm_rs, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_( short, short, run_arithm_rs, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_( float, uchar , run_arithm_rs, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_( float, short, run_arithm_rs, dst, src, scalar, ARITHM_DIVIDE, scale);
+ UNARY_( float, float, run_arithm_rs, dst, src, scalar, ARITHM_DIVIDE, scale);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//----------------------------
+//
+// Fluid math kernels: bitwise
+//
+//----------------------------
+
+enum Bitwise { BW_AND, BW_OR, BW_XOR, BW_NOT };
+
+template<typename DST, typename SRC1, typename SRC2>
+static void run_bitwise2(Buffer &dst, const View &src1, const View &src2, Bitwise bitwise)
+{
+ static_assert(std::is_same<DST, SRC1>::value, "wrong types");
+ static_assert(std::is_same<DST, SRC2>::value, "wrong types");
+
+ const auto *in1 = src1.InLine<SRC1>(0);
+ const auto *in2 = src2.InLine<SRC2>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+ int length = width * chan;
+
+ switch (bitwise)
+ {
+ case BW_AND:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] & in2[l];
+ break;
+ case BW_OR:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] | in2[l];
+ break;
+ case BW_XOR:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] ^ in2[l];
+ break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported bitwise operation");
+ }
+}
+
+template<typename DST, typename SRC>
+static void run_bitwise1(Buffer &dst, const View &src, Bitwise bitwise)
+{
+ static_assert(std::is_same<DST, SRC>::value, "wrong types");
+
+ const auto *in = src.InLine<SRC>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+ int length = width * chan;
+
+ switch (bitwise)
+ {
+ case BW_NOT:
+ for (int l=0; l < length; l++)
+ out[l] = ~in[l];
+ break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported bitwise operation");
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidAnd, cv::gapi::core::GAnd, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_bitwise2, dst, src1, src2, BW_AND);
+ BINARY_(ushort, ushort, ushort, run_bitwise2, dst, src1, src2, BW_AND);
+ BINARY_( short, short, short, run_bitwise2, dst, src1, src2, BW_AND);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidOr, cv::gapi::core::GOr, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_bitwise2, dst, src1, src2, BW_OR);
+ BINARY_(ushort, ushort, ushort, run_bitwise2, dst, src1, src2, BW_OR);
+ BINARY_( short, short, short, run_bitwise2, dst, src1, src2, BW_OR);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidXor, cv::gapi::core::GXor, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_bitwise2, dst, src1, src2, BW_XOR);
+ BINARY_(ushort, ushort, ushort, run_bitwise2, dst, src1, src2, BW_XOR);
+ BINARY_( short, short, short, run_bitwise2, dst, src1, src2, BW_XOR);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidNot, cv::gapi::core::GNot, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_bitwise1, dst, src, BW_NOT);
+ UNARY_(ushort, ushort, run_bitwise1, dst, src, BW_NOT);
+ UNARY_( short, short, run_bitwise1, dst, src, BW_NOT);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//-------------------
+//
+// Fluid kernels: LUT
+//
+//-------------------
+
+GAPI_FLUID_KERNEL(GFluidLUT, cv::gapi::core::GLUT, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Mat& lut, Buffer &dst)
+ {
+ GAPI_Assert(CV_8U == dst.meta().depth);
+ GAPI_Assert(CV_8U == src.meta().depth);
+
+ GAPI_DbgAssert(CV_8U == lut.type());
+ GAPI_DbgAssert(256 == lut.cols * lut.rows);
+ GAPI_DbgAssert(dst.length() == src.length());
+ GAPI_DbgAssert(dst.meta().chan == src.meta().chan);
+
+ const auto *in = src.InLine<uchar>(0);
+ auto *out = dst.OutLine<uchar>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+ int length = width * chan;
+
+ for (int l=0; l < length; l++)
+ out[l] = lut.data[ in[l] ];
+ }
+};
+
+//-------------------------
+//
+// Fluid kernels: convertTo
+//
+//-------------------------
+
+template<typename DST, typename SRC>
+static void run_convertto(Buffer &dst, const View &src, double _alpha, double _beta)
+{
+ const auto *in = src.InLine<SRC>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+ int length = width * chan;
+
+ // NB: don't do this if SRC or DST is 64-bit
+ auto alpha = static_cast<float>( _alpha );
+ auto beta = static_cast<float>( _beta );
+
+ // compute faster if no alpha no beta
+ if (alpha == 1 && beta == 0)
+ {
+ // manual SIMD if need rounding
+ if (std::is_integral<DST>::value && std::is_floating_point<SRC>::value)
+ {
+ GAPI_Assert(( std::is_same<SRC,float>::value ));
+
+ int l = 0; // cycle index
+
+ #if CV_SIMD128
+ if (std::is_same<DST,uchar>::value)
+ {
+ for (; l <= length-16; l+=16)
+ {
+ v_int32x4 i0, i1, i2, i3;
+ i0 = v_round( v_load( (float*)& in[l ] ) );
+ i1 = v_round( v_load( (float*)& in[l + 4] ) );
+ i2 = v_round( v_load( (float*)& in[l + 8] ) );
+ i3 = v_round( v_load( (float*)& in[l + 12] ) );
+
+ v_uint16x8 us0, us1;
+ us0 = v_pack_u(i0, i1);
+ us1 = v_pack_u(i2, i3);
+
+ v_uint8x16 uc;
+ uc = v_pack(us0, us1);
+ v_store((uchar*)& out[l], uc);
+ }
+ }
+ if (std::is_same<DST,ushort>::value)
+ {
+ for (; l <= length-8; l+=8)
+ {
+ v_int32x4 i0, i1;
+ i0 = v_round( v_load( (float*)& in[l ] ) );
+ i1 = v_round( v_load( (float*)& in[l + 4] ) );
+
+ v_uint16x8 us;
+ us = v_pack_u(i0, i1);
+ v_store((ushort*)& out[l], us);
+ }
+ }
+ #endif
+
+ // tail of SIMD cycle
+ for (; l < length; l++)
+ {
+ out[l] = saturate<DST>(in[l], rintf);
+ }
+ }
+ else if (std::is_integral<DST>::value) // here SRC is integral
+ {
+ for (int l=0; l < length; l++)
+ {
+ out[l] = saturate<DST>(in[l]);
+ }
+ }
+ else // DST is floating-point, SRC is any
+ {
+ for (int l=0; l < length; l++)
+ {
+ out[l] = static_cast<DST>(in[l]);
+ }
+ }
+ }
+ else // if alpha or beta is non-trivial
+ {
+ // TODO: optimize if alpha and beta and data are integral
+ for (int l=0; l < length; l++)
+ {
+ out[l] = saturate<DST>(in[l]*alpha + beta, rintf);
+ }
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidConvertTo, cv::gapi::core::GConvertTo, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, int /*rtype*/, double alpha, double beta, Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_convertto, dst, src, alpha, beta);
+ UNARY_(uchar , ushort, run_convertto, dst, src, alpha, beta);
+ UNARY_(uchar , float, run_convertto, dst, src, alpha, beta);
+ UNARY_(ushort, uchar , run_convertto, dst, src, alpha, beta);
+ UNARY_(ushort, ushort, run_convertto, dst, src, alpha, beta);
+ UNARY_(ushort, float, run_convertto, dst, src, alpha, beta);
+ UNARY_( float, uchar , run_convertto, dst, src, alpha, beta);
+ UNARY_( float, ushort, run_convertto, dst, src, alpha, beta);
+ UNARY_( float, float, run_convertto, dst, src, alpha, beta);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//-----------------------------
+//
+// Fluid math kernels: min, max
+//
+//-----------------------------
+
+enum Minmax { MM_MIN, MM_MAX };
+
+template<typename DST, typename SRC1, typename SRC2>
+static void run_minmax(Buffer &dst, const View &src1, const View &src2, Minmax minmax)
+{
+ static_assert(std::is_same<DST, SRC1>::value, "wrong types");
+ static_assert(std::is_same<DST, SRC2>::value, "wrong types");
+
+ const auto *in1 = src1.InLine<SRC1>(0);
+ const auto *in2 = src2.InLine<SRC2>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ int length = width * chan;
+
+ switch (minmax)
+ {
+ case MM_MIN:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] < in2[l]? in1[l]: in2[l];
+ break;
+ case MM_MAX:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] > in2[l]? in1[l]: in2[l];
+ break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported min/max operation");
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidMin, cv::gapi::core::GMin, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_minmax, dst, src1, src2, MM_MIN);
+ BINARY_(ushort, ushort, ushort, run_minmax, dst, src1, src2, MM_MIN);
+ BINARY_( short, short, short, run_minmax, dst, src1, src2, MM_MIN);
+ BINARY_( float, float, float, run_minmax, dst, src1, src2, MM_MIN);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidMax, cv::gapi::core::GMax, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar , uchar , uchar , run_minmax, dst, src1, src2, MM_MAX);
+ BINARY_(ushort, ushort, ushort, run_minmax, dst, src1, src2, MM_MAX);
+ BINARY_( short, short, short, run_minmax, dst, src1, src2, MM_MAX);
+ BINARY_( float, float, float, run_minmax, dst, src1, src2, MM_MAX);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//-----------------------
+//
+// Fluid kernels: compare
+//
+//-----------------------
+
+enum Compare { CMP_EQ, CMP_NE, CMP_GE, CMP_GT, CMP_LE, CMP_LT };
+
+template<typename DST, typename SRC1, typename SRC2>
+static void run_cmp(Buffer &dst, const View &src1, const View &src2, Compare compare)
+{
+ static_assert(std::is_same<SRC1, SRC2>::value, "wrong types");
+ static_assert(std::is_same<DST, uchar>::value, "wrong types");
+
+ const auto *in1 = src1.InLine<SRC1>(0);
+ const auto *in2 = src2.InLine<SRC2>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ int length = width * chan;
+
+ switch (compare)
+ {
+ case CMP_EQ:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] == in2[l]? 255: 0;
+ break;
+ case CMP_NE:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] != in2[l]? 255: 0;
+ break;
+ case CMP_GE:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] >= in2[l]? 255: 0;
+ break;
+ case CMP_LE:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] <= in2[l]? 255: 0;
+ break;
+ case CMP_GT:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] > in2[l]? 255: 0;
+ break;
+ case CMP_LT:
+ for (int l=0; l < length; l++)
+ out[l] = in1[l] < in2[l]? 255: 0;
+ break;
+ default:
+ CV_Error(cv::Error::StsBadArg, "unsupported compare operation");
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidCmpEQ, cv::gapi::core::GCmpEQ, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar, uchar , uchar , run_cmp, dst, src1, src2, CMP_EQ);
+ BINARY_(uchar, short, short, run_cmp, dst, src1, src2, CMP_EQ);
+ BINARY_(uchar, float, float, run_cmp, dst, src1, src2, CMP_EQ);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpNE, cv::gapi::core::GCmpNE, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar, uchar , uchar , run_cmp, dst, src1, src2, CMP_NE);
+ BINARY_(uchar, short, short, run_cmp, dst, src1, src2, CMP_NE);
+ BINARY_(uchar, float, float, run_cmp, dst, src1, src2, CMP_NE);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpGE, cv::gapi::core::GCmpGE, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar, uchar , uchar , run_cmp, dst, src1, src2, CMP_GE);
+ BINARY_(uchar, short, short, run_cmp, dst, src1, src2, CMP_GE);
+ BINARY_(uchar, float, float, run_cmp, dst, src1, src2, CMP_GE);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpGT, cv::gapi::core::GCmpGT, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar, uchar , uchar , run_cmp, dst, src1, src2, CMP_GT);
+ BINARY_(uchar, short, short, run_cmp, dst, src1, src2, CMP_GT);
+ BINARY_(uchar, float, float, run_cmp, dst, src1, src2, CMP_GT);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpLE, cv::gapi::core::GCmpLE, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar, uchar , uchar , run_cmp, dst, src1, src2, CMP_LE);
+ BINARY_(uchar, short, short, run_cmp, dst, src1, src2, CMP_LE);
+ BINARY_(uchar, float, float, run_cmp, dst, src1, src2, CMP_LE);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpLT, cv::gapi::core::GCmpLT, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, Buffer &dst)
+ {
+ // DST SRC1 SRC2 OP __VA_ARGS__
+ BINARY_(uchar, uchar , uchar , run_cmp, dst, src1, src2, CMP_LT);
+ BINARY_(uchar, short, short, run_cmp, dst, src1, src2, CMP_LT);
+ BINARY_(uchar, float, float, run_cmp, dst, src1, src2, CMP_LT);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//---------------------
+//
+// Compare with GScalar
+//
+//---------------------
+
+template<typename DST, typename SRC, typename SCALAR=double>
+static void run_cmp(DST out[], const SRC in[], int length, Compare compare, SCALAR s)
+{
+ switch (compare)
+ {
+ case CMP_EQ:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] == s? 255: 0;
+ break;
+ case CMP_NE:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] != s? 255: 0;
+ break;
+ case CMP_GE:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] >= s? 255: 0;
+ break;
+ case CMP_LE:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] <= s? 255: 0;
+ break;
+ case CMP_GT:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] > s? 255: 0;
+ break;
+ case CMP_LT:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] < s? 255: 0;
+ break;
+ default:
+ CV_Error(cv::Error::StsBadArg, "unsupported compare operation");
+ }
+}
+
+template<typename DST, typename SRC>
+static void run_cmp(Buffer &dst, const View &src, Compare compare, const cv::Scalar &scalar)
+{
+ static_assert(std::is_same<DST, uchar>::value, "wrong types");
+
+ const auto *in = src.InLine<SRC>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ int length = width * chan;
+
+ // compute faster if scalar rounds to SRC
+ double d = scalar[0] ;
+ SRC s = static_cast<SRC>( scalar[0] );
+
+ if (s == d)
+ run_cmp(out, in, length, compare, s);
+ else
+ run_cmp(out, in, length, compare, d);
+}
+
+GAPI_FLUID_KERNEL(GFluidCmpEQScalar, cv::gapi::core::GCmpEQScalar, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &scalar, Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar, uchar , run_cmp, dst, src, CMP_EQ, scalar);
+ UNARY_(uchar, short, run_cmp, dst, src, CMP_EQ, scalar);
+ UNARY_(uchar, float, run_cmp, dst, src, CMP_EQ, scalar);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpNEScalar, cv::gapi::core::GCmpNEScalar, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &scalar, Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar, uchar , run_cmp, dst, src, CMP_NE, scalar);
+ UNARY_(uchar, short, run_cmp, dst, src, CMP_NE, scalar);
+ UNARY_(uchar, float, run_cmp, dst, src, CMP_NE, scalar);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpGEScalar, cv::gapi::core::GCmpGEScalar, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &scalar, Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar, uchar , run_cmp, dst, src, CMP_GE, scalar);
+ UNARY_(uchar, short, run_cmp, dst, src, CMP_GE, scalar);
+ UNARY_(uchar, float, run_cmp, dst, src, CMP_GE, scalar);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpGTScalar, cv::gapi::core::GCmpGTScalar, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &scalar, Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar, uchar , run_cmp, dst, src, CMP_GT, scalar);
+ UNARY_(uchar, short, run_cmp, dst, src, CMP_GT, scalar);
+ UNARY_(uchar, float, run_cmp, dst, src, CMP_GT, scalar);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpLEScalar, cv::gapi::core::GCmpLEScalar, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &scalar, Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar, uchar , run_cmp, dst, src, CMP_LE, scalar);
+ UNARY_(uchar, short, run_cmp, dst, src, CMP_LE, scalar);
+ UNARY_(uchar, float, run_cmp, dst, src, CMP_LE, scalar);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCmpLTScalar, cv::gapi::core::GCmpLTScalar, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &scalar, Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar, uchar , run_cmp, dst, src, CMP_LT, scalar);
+ UNARY_(uchar, short, run_cmp, dst, src, CMP_LT, scalar);
+ UNARY_(uchar, float, run_cmp, dst, src, CMP_LT, scalar);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//-------------------------
+//
+// Fluid kernels: threshold
+//
+//-------------------------
+
+template<typename DST, typename SRC>
+static void run_threshold(Buffer &dst, const View &src, const cv::Scalar &thresh,
+ const cv::Scalar &maxval,
+ int type)
+{
+ static_assert(std::is_same<DST, SRC>::value, "wrong types");
+
+ const auto *in = src.InLine<SRC>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ int length = width * chan;
+
+ DST thresh_ = saturate<DST>(thresh[0], floord);
+ DST threshd = saturate<DST>(thresh[0], roundd);
+ DST maxvald = saturate<DST>(maxval[0], roundd);
+
+ switch (type)
+ {
+ case cv::THRESH_BINARY:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] > thresh_? maxvald: 0;
+ break;
+ case cv::THRESH_BINARY_INV:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] > thresh_? 0: maxvald;
+ break;
+ case cv::THRESH_TRUNC:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] > thresh_? threshd: in[l];
+ break;
+ case cv::THRESH_TOZERO:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] > thresh_? in[l]: 0;
+ break;
+ case cv::THRESH_TOZERO_INV:
+ for (int l=0; l < length; l++)
+ out[l] = in[l] > thresh_? 0: in[l];
+ break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported threshold type");
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidThreshold, cv::gapi::core::GThreshold, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &thresh,
+ const cv::Scalar &maxval,
+ int type,
+ Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_threshold, dst, src, thresh, maxval, type);
+ UNARY_(ushort, ushort, run_threshold, dst, src, thresh, maxval, type);
+ UNARY_( short, short, run_threshold, dst, src, thresh, maxval, type);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//------------------------
+//
+// Fluid kernels: in-range
+//
+//------------------------
+
+static void run_inrange3(uchar out[], const uchar in[], int width,
+ const uchar lower[], const uchar upper[])
+{
+ int w = 0; // cycle index
+
+#if CV_SIMD128
+ for (; w <= width-16; w+=16)
+ {
+ v_uint8x16 i0, i1, i2;
+ v_load_deinterleave(&in[3*w], i0, i1, i2);
+
+ v_uint8x16 o;
+ o = (i0 >= v_setall_u8(lower[0])) & (i0 <= v_setall_u8(upper[0])) &
+ (i1 >= v_setall_u8(lower[1])) & (i1 <= v_setall_u8(upper[1])) &
+ (i2 >= v_setall_u8(lower[2])) & (i2 <= v_setall_u8(upper[2]));
+
+ v_store(&out[w], o);
+ }
+#endif
+
+ for (; w < width; w++)
+ {
+ out[w] = in[3*w ] >= lower[0] && in[3*w ] <= upper[0] &&
+ in[3*w+1] >= lower[1] && in[3*w+1] <= upper[1] &&
+ in[3*w+2] >= lower[2] && in[3*w+2] <= upper[2] ? 255: 0;
+ }
+}
+
+template<typename DST, typename SRC>
+static void run_inrange(Buffer &dst, const View &src, const cv::Scalar &upperb,
+ const cv::Scalar &lowerb)
+{
+ static_assert(std::is_same<DST, uchar>::value, "wrong types");
+
+ const auto *in = src.InLine<SRC>(0);
+ auto *out = dst.OutLine<DST>();
+
+ int width = src.length();
+ int chan = src.meta().chan;
+ GAPI_Assert(dst.meta().chan == 1);
+
+ SRC lower[4], upper[4];
+ for (int c=0; c < chan; c++)
+ {
+ if (std::is_integral<SRC>::value)
+ {
+ // for integral input, in[i] >= lower equals in[i] >= ceil(lower)
+ // so we can optimize compare operations by rounding lower/upper
+ lower[c] = saturate<SRC>(lowerb[c], ceild);
+ upper[c] = saturate<SRC>(upperb[c], floord);
+ }
+ else
+ {
+ // FIXME: now values used in comparison are floats (while they
+ // have double precision initially). Comparison float/float
+ // may differ from float/double (how it should work in this case)
+ //
+ // Example: threshold=1/3 (or 1/10)
+ lower[c] = static_cast<SRC>(lowerb[c]);
+ upper[c] = static_cast<SRC>(upperb[c]);
+ }
+ }
+
+ // manually SIMD for important case if RGB/BGR
+ if (std::is_same<SRC,uchar>::value && chan==3)
+ {
+ run_inrange3((uchar*)out, (const uchar*)in, width,
+ (const uchar*)lower, (const uchar*)upper);
+ return;
+ }
+
+ // TODO: please manually SIMD if multiple channels:
+ // modern compilers would perfectly vectorize this code if one channel,
+ // but may need help with de-interleaving channels if RGB/BGR image etc
+ switch (chan)
+ {
+ case 1:
+ for (int w=0; w < width; w++)
+ out[w] = in[w] >= lower[0] && in[w] <= upper[0]? 255: 0;
+ break;
+ case 2:
+ for (int w=0; w < width; w++)
+ out[w] = in[2*w ] >= lower[0] && in[2*w ] <= upper[0] &&
+ in[2*w+1] >= lower[1] && in[2*w+1] <= upper[1] ? 255: 0;
+ break;
+ case 3:
+ for (int w=0; w < width; w++)
+ out[w] = in[3*w ] >= lower[0] && in[3*w ] <= upper[0] &&
+ in[3*w+1] >= lower[1] && in[3*w+1] <= upper[1] &&
+ in[3*w+2] >= lower[2] && in[3*w+2] <= upper[2] ? 255: 0;
+ break;
+ case 4:
+ for (int w=0; w < width; w++)
+ out[w] = in[4*w ] >= lower[0] && in[4*w ] <= upper[0] &&
+ in[4*w+1] >= lower[1] && in[4*w+1] <= upper[1] &&
+ in[4*w+2] >= lower[2] && in[4*w+2] <= upper[2] &&
+ in[4*w+3] >= lower[3] && in[4*w+3] <= upper[3] ? 255: 0;
+ break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported number of channels");
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidInRange, cv::gapi::core::GInRange, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, const cv::Scalar &lowerb, const cv::Scalar& upperb,
+ Buffer &dst)
+ {
+ // DST SRC OP __VA_ARGS__
+ INRANGE_(uchar, uchar , run_inrange, dst, src, upperb, lowerb);
+ INRANGE_(uchar, ushort, run_inrange, dst, src, upperb, lowerb);
+ INRANGE_(uchar, short, run_inrange, dst, src, upperb, lowerb);
+ INRANGE_(uchar, float, run_inrange, dst, src, upperb, lowerb);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//----------------------
+//
+// Fluid kernels: select
+//
+//----------------------
+
+// manually vectored function for important case if RGB/BGR image
+static void run_select_row3(int width, uchar out[], uchar in1[], uchar in2[], uchar in3[])
+{
+ int w = 0; // cycle index
+
+#if CV_SIMD128
+ for (; w <= width-16; w+=16)
+ {
+ v_uint8x16 a1, b1, c1;
+ v_uint8x16 a2, b2, c2;
+ v_uint8x16 mask;
+ v_uint8x16 a, b, c;
+
+ v_load_deinterleave(&in1[3*w], a1, b1, c1);
+ v_load_deinterleave(&in2[3*w], a2, b2, c2);
+
+ mask = v_load(&in3[w]);
+ mask = mask != v_setzero_u8();
+
+ a = v_select(mask, a1, a2);
+ b = v_select(mask, b1, b2);
+ c = v_select(mask, c1, c2);
+
+ v_store_interleave(&out[3*w], a, b, c);
+ }
+#endif
+
+ for (; w < width; w++)
+ {
+ out[3*w ] = in3[w]? in1[3*w ]: in2[3*w ];
+ out[3*w + 1] = in3[w]? in1[3*w + 1]: in2[3*w + 1];
+ out[3*w + 2] = in3[w]? in1[3*w + 2]: in2[3*w + 2];
+ }
+}
+
+// parameter chan is compile-time known constant, normally chan=1..4
+template<int chan, typename DST, typename SRC1, typename SRC2, typename SRC3>
+static void run_select_row(int width, DST out[], SRC1 in1[], SRC2 in2[], SRC3 in3[])
+{
+ if (std::is_same<DST,uchar>::value && chan==3)
+ {
+ // manually vectored function for important case if RGB/BGR image
+ run_select_row3(width, (uchar*)out, (uchar*)in1, (uchar*)in2, (uchar*)in3);
+ return;
+ }
+
+ // because `chan` is template parameter, its value is known at compilation time,
+ // so that modern compilers would efficiently vectorize this cycle if chan==1
+ // (if chan>1, compilers may need help with de-interleaving of the channels)
+ for (int w=0; w < width; w++)
+ {
+ for (int c=0; c < chan; c++)
+ {
+ out[w*chan + c] = in3[w]? in1[w*chan + c]: in2[w*chan + c];
+ }
+ }
+}
+
+template<typename DST, typename SRC1, typename SRC2, typename SRC3>
+static void run_select(Buffer &dst, const View &src1, const View &src2, const View &src3)
+{
+ static_assert(std::is_same<DST , SRC1>::value, "wrong types");
+ static_assert(std::is_same<DST , SRC2>::value, "wrong types");
+ static_assert(std::is_same<uchar, SRC3>::value, "wrong types");
+
+ auto *out = dst.OutLine<DST>();
+
+ const auto *in1 = src1.InLine<SRC1>(0);
+ const auto *in2 = src2.InLine<SRC2>(0);
+ const auto *in3 = src3.InLine<SRC3>(0);
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ switch (chan)
+ {
+ case 1: run_select_row<1>(width, out, in1, in2, in3); break;
+ case 2: run_select_row<2>(width, out, in1, in2, in3); break;
+ case 3: run_select_row<3>(width, out, in1, in2, in3); break;
+ case 4: run_select_row<4>(width, out, in1, in2, in3); break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported number of channels");
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidSelect, cv::gapi::core::GSelect, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, const View &src3, Buffer &dst)
+ {
+ // DST SRC1 SRC2 SRC3 OP __VA_ARGS__
+ SELECT_(uchar , uchar , uchar , uchar, run_select, dst, src1, src2, src3);
+ SELECT_(ushort, ushort, ushort, uchar, run_select, dst, src1, src2, src3);
+ SELECT_( short, short, short, uchar, run_select, dst, src1, src2, src3);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+};
+
+//----------------------------------------------------
+//
+// Fluid kernels: split, merge, polat2cart, cart2polar
+//
+//----------------------------------------------------
+
+GAPI_FLUID_KERNEL(GFluidSplit3, cv::gapi::core::GSplit3, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, Buffer &dst1, Buffer &dst2, Buffer &dst3)
+ {
+ const auto *in = src.InLine<uchar>(0);
+ auto *out1 = dst1.OutLine<uchar>();
+ auto *out2 = dst2.OutLine<uchar>();
+ auto *out3 = dst3.OutLine<uchar>();
+
+ GAPI_Assert(3 == src.meta().chan);
+ int width = src.length();
+
+ int w = 0; // cycle counter
+
+ #if CV_SIMD128
+ for (; w <= width-16; w+=16)
+ {
+ v_uint8x16 a, b, c;
+ v_load_deinterleave(&in[3*w], a, b, c);
+ v_store(&out1[w], a);
+ v_store(&out2[w], b);
+ v_store(&out3[w], c);
+ }
+ #endif
+
+ for (; w < width; w++)
+ {
+ out1[w] = in[3*w ];
+ out2[w] = in[3*w + 1];
+ out3[w] = in[3*w + 2];
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidSplit4, cv::gapi::core::GSplit4, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, Buffer &dst1, Buffer &dst2, Buffer &dst3, Buffer &dst4)
+ {
+ const auto *in = src.InLine<uchar>(0);
+ auto *out1 = dst1.OutLine<uchar>();
+ auto *out2 = dst2.OutLine<uchar>();
+ auto *out3 = dst3.OutLine<uchar>();
+ auto *out4 = dst4.OutLine<uchar>();
+
+ GAPI_Assert(4 == src.meta().chan);
+ int width = src.length();
+
+ int w = 0; // cycle counter
+
+ #if CV_SIMD128
+ for (; w <= width-16; w+=16)
+ {
+ v_uint8x16 a, b, c, d;
+ v_load_deinterleave(&in[4*w], a, b, c, d);
+ v_store(&out1[w], a);
+ v_store(&out2[w], b);
+ v_store(&out3[w], c);
+ v_store(&out4[w], d);
+ }
+ #endif
+
+ for (; w < width; w++)
+ {
+ out1[w] = in[4*w ];
+ out2[w] = in[4*w + 1];
+ out3[w] = in[4*w + 2];
+ out4[w] = in[4*w + 3];
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidMerge3, cv::gapi::core::GMerge3, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, const View &src3, Buffer &dst)
+ {
+ const auto *in1 = src1.InLine<uchar>(0);
+ const auto *in2 = src2.InLine<uchar>(0);
+ const auto *in3 = src3.InLine<uchar>(0);
+ auto *out = dst.OutLine<uchar>();
+
+ GAPI_Assert(3 == dst.meta().chan);
+ int width = dst.length();
+
+ int w = 0; // cycle counter
+
+ #if CV_SIMD128
+ for (; w <= width-16; w+=16)
+ {
+ v_uint8x16 a, b, c;
+ a = v_load(&in1[w]);
+ b = v_load(&in2[w]);
+ c = v_load(&in3[w]);
+ v_store_interleave(&out[3*w], a, b, c);
+ }
+ #endif
+
+ for (; w < width; w++)
+ {
+ out[3*w ] = in1[w];
+ out[3*w + 1] = in2[w];
+ out[3*w + 2] = in3[w];
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidMerge4, cv::gapi::core::GMerge4, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, const View &src3, const View &src4,
+ Buffer &dst)
+ {
+ const auto *in1 = src1.InLine<uchar>(0);
+ const auto *in2 = src2.InLine<uchar>(0);
+ const auto *in3 = src3.InLine<uchar>(0);
+ const auto *in4 = src4.InLine<uchar>(0);
+ auto *out = dst.OutLine<uchar>();
+
+ GAPI_Assert(4 == dst.meta().chan);
+ int width = dst.length();
+
+ int w = 0; // cycle counter
+
+ #if CV_SIMD128
+ for (; w <= width-16; w+=16)
+ {
+ v_uint8x16 a, b, c, d;
+ a = v_load(&in1[w]);
+ b = v_load(&in2[w]);
+ c = v_load(&in3[w]);
+ d = v_load(&in4[w]);
+ v_store_interleave(&out[4*w], a, b, c, d);
+ }
+ #endif
+
+ for (; w < width; w++)
+ {
+ out[4*w ] = in1[w];
+ out[4*w + 1] = in2[w];
+ out[4*w + 2] = in3[w];
+ out[4*w + 3] = in4[w];
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidPolarToCart, cv::gapi::core::GPolarToCart, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, bool angleInDegrees,
+ Buffer &dst1, Buffer &dst2)
+ {
+ GAPI_Assert(src1.meta().depth == CV_32F);
+ GAPI_Assert(src2.meta().depth == CV_32F);
+ GAPI_Assert(dst1.meta().depth == CV_32F);
+ GAPI_Assert(dst2.meta().depth == CV_32F);
+
+ const auto * in1 = src1.InLine<float>(0);
+ const auto * in2 = src2.InLine<float>(0);
+ auto *out1 = dst1.OutLine<float>();
+ auto *out2 = dst2.OutLine<float>();
+
+ int width = src1.length();
+ int chan = src2.meta().chan;
+ int length = width * chan;
+
+ // SIMD: compiler vectoring!
+ for (int l=0; l < length; l++)
+ {
+ float angle = angleInDegrees?
+ in2[l] * static_cast<float>(CV_PI / 180):
+ in2[l];
+ float magnitude = in1[l];
+ float x = magnitude * std::cos(angle);
+ float y = magnitude * std::sin(angle);
+ out1[l] = x;
+ out2[l] = y;
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidCartToPolar, cv::gapi::core::GCartToPolar, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src1, const View &src2, bool angleInDegrees,
+ Buffer &dst1, Buffer &dst2)
+ {
+ GAPI_Assert(src1.meta().depth == CV_32F);
+ GAPI_Assert(src2.meta().depth == CV_32F);
+ GAPI_Assert(dst1.meta().depth == CV_32F);
+ GAPI_Assert(dst2.meta().depth == CV_32F);
+
+ const auto * in1 = src1.InLine<float>(0);
+ const auto * in2 = src2.InLine<float>(0);
+ auto *out1 = dst1.OutLine<float>();
+ auto *out2 = dst2.OutLine<float>();
+
+ int width = src1.length();
+ int chan = src2.meta().chan;
+ int length = width * chan;
+
+ // SIMD: compiler vectoring!
+ for (int l=0; l < length; l++)
+ {
+ float x = in1[l];
+ float y = in2[l];
+ float magnitude = std::hypot(y, x);
+ float angle_rad = std::atan2(y, x);
+ float angle = angleInDegrees?
+ angle_rad * static_cast<float>(180 / CV_PI):
+ angle_rad;
+ out1[l] = magnitude;
+ out2[l] = angle;
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidPhase, cv::gapi::core::GPhase, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src_x,
+ const View &src_y,
+ bool angleInDegrees,
+ Buffer &dst)
+ {
+ const auto w = dst.length() * dst.meta().chan;
+ if (src_x.meta().depth == CV_32F && src_y.meta().depth == CV_32F)
+ {
+ hal::fastAtan32f(src_y.InLine<float>(0),
+ src_x.InLine<float>(0),
+ dst.OutLine<float>(),
+ w,
+ angleInDegrees);
+ }
+ else if (src_x.meta().depth == CV_64F && src_y.meta().depth == CV_64F)
+ {
+ hal::fastAtan64f(src_y.InLine<double>(0),
+ src_x.InLine<double>(0),
+ dst.OutLine<double>(),
+ w,
+ angleInDegrees);
+ } else GAPI_Assert(false && !"Phase supports 32F/64F input only!");
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::core::GResize, true)
+{
+ static const int Window = 1;
+ static const auto Kind = GFluidKernel::Kind::Resize;
+
+ constexpr static const int INTER_RESIZE_COEF_BITS = 11;
+ constexpr static const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;
+ constexpr static const short ONE = INTER_RESIZE_COEF_SCALE;
+
+ struct ResizeUnit
+ {
+ short alpha0;
+ short alpha1;
+ int s0;
+ int s1;
+ };
+
+ static ResizeUnit map(double ratio, int start, int max, int outCoord)
+ {
+ float f = static_cast<float>((outCoord + 0.5f) * ratio - 0.5f);
+ int s = cvFloor(f);
+ f -= s;
+
+ ResizeUnit ru;
+
+ ru.s0 = std::max(s - start, 0);
+ ru.s1 = ((f == 0.0) || s + 1 >= max) ? s - start : s - start + 1;
+
+ ru.alpha0 = saturate_cast<short>((1.0f - f) * INTER_RESIZE_COEF_SCALE);
+ ru.alpha1 = saturate_cast<short>((f) * INTER_RESIZE_COEF_SCALE);
+
+ return ru;
+ }
+
+ static void initScratch(const cv::GMatDesc& in,
+ cv::Size outSz, double /*fx*/, double /*fy*/, int /*interp*/,
+ cv::gapi::fluid::Buffer &scratch)
+ {
+ CV_Assert(in.depth == CV_8U && in.chan == 3);
+
+ cv::Size scratch_size{static_cast<int>(outSz.width * sizeof(ResizeUnit)), 1};
+
+ cv::GMatDesc desc;
+ desc.chan = 1;
+ desc.depth = CV_8UC1;
+ desc.size = to_own(scratch_size);
+
+ cv::gapi::fluid::Buffer buffer(desc);
+ scratch = std::move(buffer);
+
+ ResizeUnit* mapX = scratch.OutLine<ResizeUnit>();
+ double hRatio = (double)in.size.width / outSz.width;
+
+ for (int x = 0, w = outSz.width; x < w; x++)
+ {
+ mapX[x] = map(hRatio, 0, in.size.width, x);
+ }
+ }
+
+ static void resetScratch(cv::gapi::fluid::Buffer& /*scratch*/)
+ {}
+
+ static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int /*interp*/,
+ cv::gapi::fluid::Buffer& out, cv::gapi::fluid::Buffer &scratch)
+ {
+ double vRatio = (double)in.meta().size.height / out.meta().size.height;
+ auto mapY = map(vRatio, in.y(), in.meta().size.height, out.y());
+
+ auto beta0 = mapY.alpha0;
+ auto beta1 = mapY.alpha1;
+
+ const auto src0 = in.InLine <unsigned char>(mapY.s0);
+ const auto src1 = in.InLine <unsigned char>(mapY.s1);
+
+ auto dst = out.OutLine<unsigned char>();
+
+ ResizeUnit* mapX = scratch.OutLine<ResizeUnit>();
+
+ for (int x = 0; x < out.length(); x++)
+ {
+ short alpha0 = mapX[x].alpha0;
+ short alpha1 = mapX[x].alpha1;
+ int sx0 = mapX[x].s0;
+ int sx1 = mapX[x].s1;
+
+ int res00 = src0[3*sx0 ]*alpha0 + src0[3*(sx1) ]*alpha1;
+ int res10 = src1[3*sx0 ]*alpha0 + src1[3*(sx1) ]*alpha1;
+
+ int res01 = src0[3*sx0 + 1]*alpha0 + src0[3*(sx1) + 1]*alpha1;
+ int res11 = src1[3*sx0 + 1]*alpha0 + src1[3*(sx1) + 1]*alpha1;
+
+ int res02 = src0[3*sx0 + 2]*alpha0 + src0[3*(sx1) + 2]*alpha1;
+ int res12 = src1[3*sx0 + 2]*alpha0 + src1[3*(sx1) + 2]*alpha1;
+
+ dst[3*x ] = uchar(( ((beta0 * (res00 >> 4)) >> 16) + ((beta1 * (res10 >> 4)) >> 16) + 2)>>2);
+ dst[3*x + 1] = uchar(( ((beta0 * (res01 >> 4)) >> 16) + ((beta1 * (res11 >> 4)) >> 16) + 2)>>2);
+ dst[3*x + 2] = uchar(( ((beta0 * (res02 >> 4)) >> 16) + ((beta1 * (res12 >> 4)) >> 16) + 2)>>2);
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidSqrt, cv::gapi::core::GSqrt, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &in, Buffer &out)
+ {
+ const auto w = out.length() * out.meta().chan;
+ if (in.meta().depth == CV_32F)
+ {
+ hal::sqrt32f(in.InLine<float>(0),
+ out.OutLine<float>(0),
+ w);
+ }
+ else if (in.meta().depth == CV_64F)
+ {
+ hal::sqrt64f(in.InLine<double>(0),
+ out.OutLine<double>(0),
+ w);
+ } else GAPI_Assert(false && !"Sqrt supports 32F/64F input only!");
+ }
+};
+
+} // namespace fliud
+} // namespace gapi
+} // namespace cv
+
+cv::gapi::GKernelPackage cv::gapi::core::fluid::kernels()
+{
+ using namespace cv::gapi::fluid;
+
+ return cv::gapi::kernels
+ < GFluidAdd
+ ,GFluidSub
+ ,GFluidMul
+ ,GFluidDiv
+ ,GFluidAbsDiff
+ ,GFluidAnd
+ ,GFluidOr
+ ,GFluidXor
+ ,GFluidMin
+ ,GFluidMax
+ ,GFluidCmpGT
+ ,GFluidCmpGE
+ ,GFluidCmpLE
+ ,GFluidCmpLT
+ ,GFluidCmpEQ
+ ,GFluidCmpNE
+ ,GFluidAddW
+ ,GFluidNot
+ ,GFluidLUT
+ ,GFluidConvertTo
+ ,GFluidSplit3
+ ,GFluidSplit4
+ ,GFluidMerge3
+ ,GFluidMerge4
+ ,GFluidSelect
+ ,GFluidPolarToCart
+ ,GFluidCartToPolar
+ ,GFluidPhase
+ ,GFluidAddC
+ ,GFluidSubC
+ ,GFluidSubRC
+ ,GFluidMulC
+ ,GFluidMulCOld
+ ,GFluidDivC
+ ,GFluidDivRC
+ ,GFluidAbsDiffC
+ ,GFluidCmpGTScalar
+ ,GFluidCmpGEScalar
+ ,GFluidCmpLEScalar
+ ,GFluidCmpLTScalar
+ ,GFluidCmpEQScalar
+ ,GFluidCmpNEScalar
+ ,GFluidThreshold
+ ,GFluidInRange
+ ,GFluidResize
+ ,GFluidSqrt
+ #if 0
+ ,GFluidMean -- not fluid
+ ,GFluidSum -- not fluid
+ ,GFluidNormL1 -- not fluid
+ ,GFluidNormL2 -- not fluid
+ ,GFluidNormInf -- not fluid
+ ,GFluidIntegral -- not fluid
+ ,GFluidThresholdOT -- not fluid
+ ,GFluidResize -- not fluid (?)
+ ,GFluidRemap -- not fluid
+ ,GFluidFlip -- not fluid
+ ,GFluidCrop -- not fluid
+ ,GFluidConcatHor
+ ,GFluidConcatVert -- not fluid
+ #endif
+ >();
+}
+
+#endif // !defined(GAPI_STANDALONE)
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc.cpp
new file mode 100644
index 000000000..e2e4c4f75
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc.cpp
@@ -0,0 +1,1338 @@
+// 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) 2018 Intel Corporation
+
+#if !defined(GAPI_STANDALONE)
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/own/assert.hpp"
+#include "opencv2/core/traits.hpp"
+#include "opencv2/imgproc/types_c.h"
+
+#include "opencv2/gapi/core.hpp"
+#include "opencv2/gapi/imgproc.hpp"
+
+#include "opencv2/gapi/own/types.hpp"
+
+#include "opencv2/gapi/fluid/gfluidbuffer.hpp"
+#include "opencv2/gapi/fluid/gfluidkernel.hpp"
+#include "opencv2/gapi/fluid/imgproc.hpp"
+
+#include "gfluidbuffer_priv.hpp"
+#include "gfluidbackend.hpp"
+#include "gfluidutils.hpp"
+
+#include "gfluidimgproc_func.hpp"
+
+#include "opencv2/imgproc/hal/hal.hpp"
+#include "opencv2/core/hal/intrin.hpp"
+
+#include <cmath>
+#include <cstdlib>
+
+namespace cv {
+namespace gapi {
+namespace fluid {
+
+//----------------------------------
+//
+// Fluid kernels: RGB2Gray, BGR2Gray
+//
+//----------------------------------
+
+// Y' = 0.299*R' + 0.587*G' + 0.114*B'
+// U' = (B' - Y')*0.492
+// V' = (R' - Y')*0.877
+static const float coef_rgb2yuv_bt601[5] = {0.299f, 0.587f, 0.114f, 0.492f, 0.877f};
+
+// R' = Y' + 1.140*V'
+// G' = Y' - 0.394*U' - 0.581*V'
+// B' = Y' + 2.032*U'
+static const float coef_yuv2rgb_bt601[4] = {1.140f, -0.394f, -0.581f, 2.032f};
+
+static void run_rgb2gray(Buffer &dst, const View &src, float coef_r, float coef_g, float coef_b)
+{
+ GAPI_Assert(src.meta().depth == CV_8U);
+ GAPI_Assert(dst.meta().depth == CV_8U);
+ GAPI_Assert(src.meta().chan == 3);
+ GAPI_Assert(dst.meta().chan == 1);
+ GAPI_Assert(src.length() == dst.length());
+
+ GAPI_Assert(coef_r < 1 && coef_g < 1 && coef_b < 1);
+ GAPI_Assert(std::abs(coef_r + coef_g + coef_b - 1) < 0.001);
+
+ const auto *in = src.InLine<uchar>(0);
+ auto *out = dst.OutLine<uchar>();
+
+ int width = dst.length();
+
+ run_rgb2gray_impl(out, in, width, coef_r, coef_g, coef_b);
+}
+
+GAPI_FLUID_KERNEL(GFluidRGB2GrayCustom, cv::gapi::imgproc::GRGB2GrayCustom, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, float coef_r, float coef_g, float coef_b, Buffer &dst)
+ {
+ run_rgb2gray(dst, src, coef_r, coef_g, coef_b);
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidRGB2Gray, cv::gapi::imgproc::GRGB2Gray, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, Buffer &dst)
+ {
+ float coef_r = coef_rgb2yuv_bt601[0];
+ float coef_g = coef_rgb2yuv_bt601[1];
+ float coef_b = coef_rgb2yuv_bt601[2];
+ run_rgb2gray(dst, src, coef_r, coef_g, coef_b);
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidBGR2Gray, cv::gapi::imgproc::GBGR2Gray, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, Buffer &dst)
+ {
+ float coef_r = coef_rgb2yuv_bt601[0];
+ float coef_g = coef_rgb2yuv_bt601[1];
+ float coef_b = coef_rgb2yuv_bt601[2];
+ run_rgb2gray(dst, src, coef_b, coef_g, coef_r);
+ }
+};
+
+//--------------------------------------
+//
+// Fluid kernels: RGB-to-YUV, YUV-to-RGB
+//
+//--------------------------------------
+
+static void run_rgb2yuv(Buffer &dst, const View &src, const float coef[5])
+{
+ GAPI_Assert(src.meta().depth == CV_8U);
+ GAPI_Assert(dst.meta().depth == CV_8U);
+ GAPI_Assert(src.meta().chan == 3);
+ GAPI_Assert(dst.meta().chan == 3);
+ GAPI_Assert(src.length() == dst.length());
+
+ const auto *in = src.InLine<uchar>(0);
+ auto *out = dst.OutLine<uchar>();
+
+ int width = dst.length();
+
+ run_rgb2yuv_impl(out, in, width, coef);
+}
+
+static void run_yuv2rgb(Buffer &dst, const View &src, const float coef[4])
+{
+ GAPI_Assert(src.meta().depth == CV_8U);
+ GAPI_Assert(dst.meta().depth == CV_8U);
+ GAPI_Assert(src.meta().chan == 3);
+ GAPI_Assert(dst.meta().chan == 3);
+ GAPI_Assert(src.length() == dst.length());
+
+ const auto *in = src.InLine<uchar>(0);
+ auto *out = dst.OutLine<uchar>();
+
+ int width = dst.length();
+
+ run_yuv2rgb_impl(out, in, width, coef);
+}
+
+GAPI_FLUID_KERNEL(GFluidRGB2YUV, cv::gapi::imgproc::GRGB2YUV, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, Buffer &dst)
+ {
+ run_rgb2yuv(dst, src, coef_rgb2yuv_bt601);
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidYUV2RGB, cv::gapi::imgproc::GYUV2RGB, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, Buffer &dst)
+ {
+ run_yuv2rgb(dst, src, coef_yuv2rgb_bt601);
+ }
+};
+
+//--------------------------------------
+//
+// Fluid kernels: RGB-to-Lab, BGR-to-LUV
+//
+//--------------------------------------
+
+enum LabLUV { LL_Lab, LL_LUV };
+
+#define LabLuv_reference 0 // 1=use reference code of RGB/BGR to LUV/Lab, 0=don't
+
+#if LabLuv_reference
+
+// gamma-correction (inverse) for sRGB, 1/gamma=2.4 for inverse, like for Mac OS (?)
+static inline float f_gamma(float x)
+{
+ return x <= 0.04045f ? x*(1.f/12.92f) : std::pow((x + 0.055f)*(1/1.055f), 2.4f);
+}
+
+// saturate into interval [0, 1]
+static inline float clip01(float value)
+{
+ return value < 0? 0:
+ value > 1? 1:
+ value;
+}
+
+static inline void f_rgb2xyz(float R, float G, float B,
+ float& X, float& Y, float& Z)
+{
+ X = clip01(0.412453f*R + 0.357580f*G + 0.180423f*B);
+ Y = clip01(0.212671f*R + 0.715160f*G + 0.072169f*B);
+ Z = clip01(0.019334f*R + 0.119193f*G + 0.950227f*B);
+}
+
+static inline void f_xyz2lab(float X, float Y, float Z,
+ float& L, float& a, float& b)
+{
+ // CIE XYZ values of reference white point for D65 illuminant
+ static const float Xn = 0.950456f, Yn = 1.f, Zn = 1.088754f;
+
+ // Other coefficients below:
+ // 7.787f = (29/3)^3/(29*4)
+ // 0.008856f = (6/29)^3
+ // 903.3 = (29/3)^3
+
+ float x = X/Xn, y = Y/Yn, z = Z/Zn;
+
+ auto f = [](float t){ return t>0.008856f? std::cbrt(t): (7.787f*t + 16.f/116.f); };
+
+ float fx = f(x), fy = f(y), fz = f(z);
+
+ L = y > 0.008856f ? (116.f*std::cbrt(y) - 16.f) : (903.3f * y);
+ a = 500.f * (fx - fy);
+ b = 200.f * (fy - fz);
+}
+
+static inline void f_xyz2luv(float X, float Y, float Z,
+ float& L, float& u, float& v)
+{
+ static const float un = 0.19793943f, vn = 0.46831096f;
+
+ float u1 = 4*X / (X + 15*Y + 3*Z);
+ float v1 = 9*Y / (X + 15*Y + 3*Z);
+
+ L = Y > 0.008856f ? (116.f*std::cbrt(Y) - 16.f) : (903.3f * Y);
+ u = 13*L * (u1 - un);
+ v = 13*L * (v1 - vn);
+}
+
+template<LabLUV labluv, int blue=0>
+static void run_rgb2labluv_reference(uchar out[], const uchar in[], int width)
+{
+ for (int w=0; w < width; w++)
+ {
+ float R, G, B;
+ B = in[3*w + blue ] / 255.f;
+ G = in[3*w + 1 ] / 255.f;
+ R = in[3*w + (2^blue)] / 255.f;
+
+ B = f_gamma( B );
+ G = f_gamma( G );
+ R = f_gamma( R );
+
+ float X, Y, Z;
+ f_rgb2xyz(R, G, B, X, Y, Z);
+
+ // compile-time `if`
+ if (LL_Lab == labluv)
+ {
+ float L, a, b;
+ f_xyz2lab(X, Y, Z, L, a, b);
+
+ out[3*w ] = saturate<uchar>(L * 255.f/100, roundf);
+ out[3*w + 1] = saturate<uchar>(a + 128, roundf);
+ out[3*w + 2] = saturate<uchar>(b + 128, roundf);
+ }
+ else if (LL_LUV == labluv)
+ {
+ float L, u, v;
+ f_xyz2luv(X, Y, Z, L, u, v);
+
+ out[3*w ] = saturate<uchar>( L * 255.f/100, roundf);
+ out[3*w + 1] = saturate<uchar>((u + 134) * 255.f/354, roundf);
+ out[3*w + 2] = saturate<uchar>((v + 140) * 255.f/262, roundf);
+ }
+ else
+ CV_Error(cv::Error::StsBadArg, "unsupported color conversion");;
+ }
+}
+
+#endif // LabLuv_reference
+
+// compile-time parameters: output format (Lab/LUV),
+// and position of blue channel in BGR/RGB (0 or 2)
+template<LabLUV labluv, int blue=0>
+static void run_rgb2labluv(Buffer &dst, const View &src)
+{
+ GAPI_Assert(src.meta().depth == CV_8U);
+ GAPI_Assert(dst.meta().depth == CV_8U);
+ GAPI_Assert(src.meta().chan == 3);
+ GAPI_Assert(dst.meta().chan == 3);
+ GAPI_Assert(src.length() == dst.length());
+
+ const auto *in = src.InLine<uchar>(0);
+ auto *out = dst.OutLine<uchar>();
+
+ int width = dst.length();
+
+#if LabLuv_reference
+ run_rgb2labluv_reference<labluv, blue>(out, in, width);
+#else
+ uchar *dst_data = out;
+ const uchar *src_data = in;
+ size_t src_step = width;
+ size_t dst_step = width;
+ int height = 1;
+ int depth = CV_8U;
+ int scn = 3;
+ bool swapBlue = (blue == 2);
+ bool isLab = (LL_Lab == labluv);
+ bool srgb = true;
+ cv::hal::cvtBGRtoLab(src_data, src_step, dst_data, dst_step,
+ width, height, depth, scn, swapBlue, isLab, srgb);
+#endif
+}
+
+GAPI_FLUID_KERNEL(GFluidRGB2Lab, cv::gapi::imgproc::GRGB2Lab, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, Buffer &dst)
+ {
+ static const int blue = 2; // RGB: 0=red, 1=green, 2=blue
+ run_rgb2labluv<LL_Lab, blue>(dst, src);
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidBGR2LUV, cv::gapi::imgproc::GBGR2LUV, false)
+{
+ static const int Window = 1;
+
+ static void run(const View &src, Buffer &dst)
+ {
+ static const int blue = 0; // BGR: 0=blue, 1=green, 2=red
+ run_rgb2labluv<LL_LUV, blue>(dst, src);
+ }
+};
+
+//-------------------------------
+//
+// Fluid kernels: blur, boxFilter
+//
+//-------------------------------
+
+static const int maxKernelSize = 9;
+
+template<typename DST, typename SRC>
+static void run_boxfilter(Buffer &dst, const View &src, const cv::Size &kernelSize,
+ const cv::Point& /* anchor */, bool normalize)
+{
+ GAPI_Assert(kernelSize.width <= maxKernelSize);
+ GAPI_Assert(kernelSize.width == kernelSize.height);
+
+ int kernel = kernelSize.width;
+ int border = (kernel - 1) / 2;
+
+ const SRC *in[ maxKernelSize ];
+ DST *out;
+
+ for (int i=0; i < kernel; i++)
+ {
+ in[i] = src.InLine<SRC>(i - border);
+ }
+
+ out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ GAPI_DbgAssert(chan <= 4);
+
+ for (int w=0; w < width; w++)
+ {
+ float sum[4] = {0, 0, 0, 0};
+
+ for (int i=0; i < kernel; i++)
+ {
+ for (int j=0; j < kernel; j++)
+ {
+ for (int c=0; c < chan; c++)
+ sum[c] += in[i][(w + j - border)*chan + c];
+ }
+ }
+
+ for (int c=0; c < chan; c++)
+ {
+ float result = normalize? sum[c]/(kernel * kernel) : sum[c];
+
+ out[w*chan + c] = saturate<DST>(result, rintf);
+ }
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidBlur, cv::gapi::imgproc::GBlur, false)
+{
+ static const int Window = 3;
+
+ static void run(const View &src, const cv::Size& kernelSize, const cv::Point& anchor,
+ int /* borderType */, const cv::Scalar& /* borderValue */, Buffer &dst)
+ {
+ // TODO: support sizes 3, 5, 7, 9, ...
+ GAPI_Assert(kernelSize.width == 3 && kernelSize.height == 3);
+
+ // TODO: suport non-trivial anchor
+ GAPI_Assert(anchor.x == -1 && anchor.y == -1);
+
+ static const bool normalize = true;
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_boxfilter, dst, src, kernelSize, anchor, normalize);
+ UNARY_(ushort, ushort, run_boxfilter, dst, src, kernelSize, anchor, normalize);
+ UNARY_( short, short, run_boxfilter, dst, src, kernelSize, anchor, normalize);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+
+ static Border getBorder(const cv::GMatDesc& /* src */,
+ const cv::Size & /* kernelSize */,
+ const cv::Point & /* anchor */,
+ int borderType,
+ const cv::Scalar & borderValue)
+ {
+ return { borderType, borderValue};
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidBoxFilter, cv::gapi::imgproc::GBoxFilter, false)
+{
+ static const int Window = 3;
+
+ static void run(const View & src,
+ int /* ddepth */,
+ const cv::Size & kernelSize,
+ const cv::Point & anchor,
+ bool normalize,
+ int /* borderType */,
+ const cv::Scalar& /* borderValue */,
+ Buffer& dst)
+ {
+ // TODO: support sizes 3, 5, 7, 9, ...
+ GAPI_Assert(kernelSize.width == 3 && kernelSize.height == 3);
+
+ // TODO: suport non-trivial anchor
+ GAPI_Assert(anchor.x == -1 && anchor.y == -1);
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_boxfilter, dst, src, kernelSize, anchor, normalize);
+ UNARY_(ushort, ushort, run_boxfilter, dst, src, kernelSize, anchor, normalize);
+ UNARY_( short, short, run_boxfilter, dst, src, kernelSize, anchor, normalize);
+ UNARY_( float, uchar , run_boxfilter, dst, src, kernelSize, anchor, normalize);
+ UNARY_( float, ushort, run_boxfilter, dst, src, kernelSize, anchor, normalize);
+ UNARY_( float, short, run_boxfilter, dst, src, kernelSize, anchor, normalize);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+
+ static Border getBorder(const cv::GMatDesc& /* src */,
+ int /* ddepth */,
+ const cv::Size & /* kernelSize */,
+ const cv::Point & /* anchor */,
+ bool /* normalize */,
+ int borderType,
+ const cv::Scalar & borderValue)
+ {
+ return { borderType, borderValue};
+ }
+};
+
+//-------------------------
+//
+// Fluid kernels: sepFilter
+//
+//-------------------------
+
+template<typename T>
+static void getKernel(T k[], const cv::Mat& kernel)
+{
+ GAPI_Assert(kernel.channels() == 1);
+
+ int depth = CV_MAT_DEPTH(kernel.type());
+ int cols = kernel.cols;
+ int rows = kernel.rows;
+
+ switch ( depth )
+ {
+ case CV_8U:
+ for (int h=0; h < rows; h++)
+ for (int w=0; w < cols; w++)
+ k[h*cols + w] = static_cast<T>( kernel.at<uchar>(h, w) );
+ break;
+ case CV_16U:
+ for (int h=0; h < rows; h++)
+ for (int w=0; w < cols; w++)
+ k[h*cols + w] = static_cast<T>( kernel.at<ushort>(h, w) );
+ break;
+ case CV_16S:
+ for (int h=0; h < rows; h++)
+ for (int w=0; w < cols; w++)
+ k[h*cols + w] = static_cast<T>( kernel.at<short>(h, w) );
+ break;
+ case CV_32F:
+ for (int h=0; h < rows; h++)
+ for (int w=0; w < cols; w++)
+ k[h*cols + w] = static_cast<T>( kernel.at<float>(h, w) );
+ break;
+ default: CV_Error(cv::Error::StsBadArg, "unsupported kernel type");
+ }
+}
+
+template<typename DST, typename SRC>
+static void run_sepfilter(Buffer& dst, const View& src,
+ const float kx[], int kxLen,
+ const float ky[], int kyLen,
+ const cv::Point& /* anchor */,
+ float delta=0)
+{
+ static const int maxLines = 9;
+ GAPI_Assert(kyLen <= maxLines);
+
+ const SRC *in[ maxLines ];
+ DST *out;
+
+ int border = (kyLen - 1) / 2;
+ for (int i=0; i < kyLen; i++)
+ {
+ in[i] = src.InLine<SRC>(i - border);
+ }
+
+ out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ for (int w=0; w < width; w++)
+ {
+ // TODO: make this cycle innermost
+ for (int c=0; c < chan; c++)
+ {
+ float sum=0;
+
+ for (int i=0; i < kyLen; i++)
+ {
+ float sumi=0;
+
+ for (int j=0; j < kxLen; j++)
+ {
+ sumi += in[i][(w + j - border)*chan + c] * kx[j];
+ }
+
+ sum += sumi * ky[i];
+ }
+
+ float result = sum + delta;
+
+ out[w*chan + c] = saturate<DST>(result, rintf);
+ }
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidSepFilter, cv::gapi::imgproc::GSepFilter, true)
+{
+ static const int Window = 3;
+
+ static void run(const View& src,
+ int /* ddepth */,
+ const cv::Mat& kernX,
+ const cv::Mat& kernY,
+ const cv::Point& anchor,
+ const cv::Scalar& delta_,
+ int /* borderType */,
+ const cv::Scalar& /* borderValue */,
+ Buffer& dst,
+ Buffer& scratch)
+ {
+ // TODO: support non-trivial anchors
+ GAPI_Assert(anchor.x == -1 && anchor.y == -1);
+
+ // TODO: support kernel heights 3, 5, 7, 9, ...
+ GAPI_Assert((kernY.rows == 1 || kernY.cols == 1) && (kernY.cols * kernY.rows == 3));
+ GAPI_Assert((kernX.rows == 1 || kernX.cols == 1));
+
+ int kxLen = kernX.rows * kernX.cols;
+ int kyLen = kernY.rows * kernY.cols;
+
+ float *kx = scratch.OutLine<float>();
+ float *ky = kx + kxLen;
+
+ float delta = static_cast<float>(delta_[0]);
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_sepfilter, dst, src, kx, kxLen, ky, kyLen, anchor, delta);
+ UNARY_(ushort, ushort, run_sepfilter, dst, src, kx, kxLen, ky, kyLen, anchor, delta);
+ UNARY_( short, short, run_sepfilter, dst, src, kx, kxLen, ky, kyLen, anchor, delta);
+ UNARY_( float, float, run_sepfilter, dst, src, kx, kxLen, ky, kyLen, anchor, delta);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+
+ static void initScratch(const GMatDesc& /* in */,
+ int /* ddepth */,
+ const Mat & kernX,
+ const Mat & kernY,
+ const Point & /* anchor */,
+ const Scalar & /* delta */,
+ int /* borderType */,
+ const Scalar & /* borderValue */,
+ Buffer & scratch)
+ {
+ int kxLen = kernX.rows * kernX.cols;
+ int kyLen = kernY.rows * kernY.cols;
+
+ cv::gapi::own::Size bufsize(kxLen + kyLen, 1);
+ GMatDesc bufdesc = {CV_32F, 1, bufsize};
+ Buffer buffer(bufdesc);
+ scratch = std::move(buffer);
+
+ // FIXME: move to resetScratch stage ?
+ float *kx = scratch.OutLine<float>();
+ float *ky = kx + kxLen;
+ getKernel(kx, kernX);
+ getKernel(ky, kernY);
+ }
+
+ static void resetScratch(Buffer& /* scratch */)
+ {
+ }
+
+ static Border getBorder(const cv::GMatDesc& /* src */,
+ int /* ddepth */,
+ const cv::Mat& /* kernX */,
+ const cv::Mat& /* kernY */,
+ const cv::Point& /* anchor */,
+ const cv::Scalar& /* delta */,
+ int borderType,
+ const cv::Scalar& borderValue)
+ {
+ return { borderType, borderValue};
+ }
+};
+
+//----------------------------
+//
+// Fluid kernels: gaussianBlur
+//
+//----------------------------
+
+GAPI_FLUID_KERNEL(GFluidGaussBlur, cv::gapi::imgproc::GGaussBlur, true)
+{
+ // TODO: support kernel height 3, 5, 7, 9, ...
+ static const int Window = 3;
+
+ static void run(const View & src,
+ const cv::Size & ksize,
+ double /* sigmaX */,
+ double /* sigmaY */,
+ int /* borderType */,
+ const cv::Scalar& /* borderValue */,
+ Buffer& dst,
+ Buffer& scratch)
+ {
+ GAPI_Assert(ksize.height == 3);
+
+ int kxsize = ksize.width;
+ int kysize = ksize.height;
+
+ auto *kx = scratch.OutLine<float>(); // cached kernX data
+ auto *ky = kx + kxsize; // cached kernY data
+
+ auto anchor = cv::Point(-1, -1);
+ float delta = 0.f;
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_sepfilter, dst, src, kx, kxsize, ky, kysize, anchor, delta);
+ UNARY_(ushort, ushort, run_sepfilter, dst, src, kx, kxsize, ky, kysize, anchor, delta);
+ UNARY_( short, short, run_sepfilter, dst, src, kx, kxsize, ky, kysize, anchor, delta);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+
+ static void initScratch(const GMatDesc& /* in */,
+ const cv::Size & ksize,
+ double sigmaX,
+ double sigmaY,
+ int /* borderType */,
+ const cv::Scalar & /* borderValue */,
+ Buffer & scratch)
+ {
+ int kxsize = ksize.width;
+ int kysize = ksize.height;
+
+ cv::gapi::own::Size bufsize(kxsize + kysize, 1);
+ GMatDesc bufdesc = {CV_32F, 1, bufsize};
+ Buffer buffer(bufdesc);
+ scratch = std::move(buffer);
+
+ // FIXME: fill buffer at resetScratch stage?
+
+ if (sigmaX == 0)
+ sigmaX = 0.3 * ((kxsize - 1)/2. - 1) + 0.8;
+
+ if (sigmaY == 0)
+ sigmaY = sigmaX;
+
+ Mat kernX = getGaussianKernel(kxsize, sigmaX, CV_32F);
+
+ Mat kernY = kernX;
+ if (sigmaY != sigmaX)
+ kernY = getGaussianKernel(kysize, sigmaY, CV_32F);
+
+ auto *kx = scratch.OutLine<float>();
+ auto *ky = kx + kxsize;
+
+ getKernel(kx, kernX);
+ getKernel(ky, kernY);
+ }
+
+ static void resetScratch(Buffer& /* scratch */)
+ {
+ }
+
+ static Border getBorder(const cv::GMatDesc& /* src */,
+ const cv::Size & /* ksize */,
+ double /* sigmaX */,
+ double /* sigmaY */,
+ int borderType,
+ const cv::Scalar & borderValue)
+ {
+ return { borderType, borderValue};
+ }
+};
+
+//---------------------
+//
+// Fluid kernels: Sobel
+//
+//---------------------
+
+template<typename DST, typename SRC>
+static void run_sobel(Buffer& dst,
+ const View & src,
+ const float kx[],
+ const float ky[],
+ int ksize,
+ float scale, // default: 1
+ float delta, // default: 0
+ float *buf[])
+{
+ static const int kmax = 11;
+ GAPI_Assert(ksize <= kmax);
+
+ const SRC *in[ kmax ];
+ DST *out;
+
+ int border = (ksize - 1) / 2;
+ for (int i=0; i < ksize; i++)
+ {
+ in[i] = src.InLine<SRC>(i - border);
+ }
+
+ out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ GAPI_DbgAssert(ksize == 3);
+// float buf[3][width * chan];
+
+ int y = dst.y();
+ int y0 = dst.priv().writeStart();
+// int y1 = dst.priv().writeEnd();
+
+ run_sobel_row(out, in, width, chan, kx, ky, border, scale, delta, buf, y, y0);
+}
+
+GAPI_FLUID_KERNEL(GFluidSobel, cv::gapi::imgproc::GSobel, true)
+{
+ static const int Window = 3;
+
+ static void run(const View & src,
+ int /* ddepth */,
+ int /* dx */,
+ int /* dy */,
+ int ksize,
+ double _scale,
+ double _delta,
+ int /* borderType */,
+ const cv::Scalar& /* borderValue */,
+ Buffer& dst,
+ Buffer& scratch)
+ {
+ // TODO: support kernel height 3, 5, 7, 9, ...
+ GAPI_Assert(ksize == 3 || ksize == FILTER_SCHARR);
+
+ int ksz = (ksize == FILTER_SCHARR)? 3: ksize;
+
+ auto *kx = scratch.OutLine<float>();
+ auto *ky = kx + ksz;
+
+ int width = dst.meta().size.width;
+ int chan = dst.meta().chan;
+
+ float *buf[3];
+ buf[0] = ky + ksz;
+ buf[1] = buf[0] + width*chan;
+ buf[2] = buf[1] + width*chan;
+
+ auto scale = static_cast<float>(_scale);
+ auto delta = static_cast<float>(_delta);
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_sobel, dst, src, kx, ky, ksz, scale, delta, buf);
+ UNARY_(ushort, ushort, run_sobel, dst, src, kx, ky, ksz, scale, delta, buf);
+ UNARY_( short, uchar , run_sobel, dst, src, kx, ky, ksz, scale, delta, buf);
+ UNARY_( short, ushort, run_sobel, dst, src, kx, ky, ksz, scale, delta, buf);
+ UNARY_( short, short, run_sobel, dst, src, kx, ky, ksz, scale, delta, buf);
+ UNARY_( float, uchar , run_sobel, dst, src, kx, ky, ksz, scale, delta, buf);
+ UNARY_( float, ushort, run_sobel, dst, src, kx, ky, ksz, scale, delta, buf);
+ UNARY_( float, short, run_sobel, dst, src, kx, ky, ksz, scale, delta, buf);
+ UNARY_( float, float, run_sobel, dst, src, kx, ky, ksz, scale, delta, buf);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+
+ static void initScratch(const GMatDesc& in,
+ int /* ddepth */,
+ int dx,
+ int dy,
+ int ksize,
+ double /* scale */,
+ double /* delta */,
+ int /* borderType */,
+ const Scalar & /* borderValue */,
+ Buffer & scratch)
+ {
+ // TODO: support kernel height 3, 5, 7, 9, ...
+ GAPI_Assert(ksize == 3 || ksize == FILTER_SCHARR);
+ int ksz = (ksize == FILTER_SCHARR) ? 3 : ksize;
+
+ int width = in.size.width;
+ int chan = in.chan;
+
+ int buflen = ksz + ksz // kernels: kx, ky
+ + ksz * width * chan; // working buffers
+
+ cv::gapi::own::Size bufsize(buflen, 1);
+ GMatDesc bufdesc = {CV_32F, 1, bufsize};
+ Buffer buffer(bufdesc);
+ scratch = std::move(buffer);
+
+ auto *kx = scratch.OutLine<float>();
+ auto *ky = kx + ksz;
+
+ Mat kxmat(1, ksize, CV_32FC1, kx);
+ Mat kymat(ksize, 1, CV_32FC1, ky);
+ getDerivKernels(kxmat, kymat, dx, dy, ksize);
+ }
+
+ static void resetScratch(Buffer& /* scratch */)
+ {
+ }
+
+ static Border getBorder(const cv::GMatDesc& /* src */,
+ int /* ddepth */,
+ int /* dx */,
+ int /* dy */,
+ int /* ksize */,
+ double /* scale */,
+ double /* delta */,
+ int borderType,
+ const cv::Scalar & borderValue)
+ {
+ return {borderType, borderValue};
+ }
+};
+
+//------------------------
+//
+// Fluid kernels: filter2D
+//
+//------------------------
+
+template<typename DST, typename SRC>
+static void run_filter2d(Buffer& dst, const View& src,
+ const float k[], int k_rows, int k_cols,
+ const cv::Point& /* anchor */,
+ float delta=0)
+{
+ static const int maxLines = 9;
+ GAPI_Assert(k_rows <= maxLines);
+
+ const SRC *in[ maxLines ];
+ DST *out;
+
+ int border_x = (k_cols - 1) / 2;
+ int border_y = (k_rows - 1) / 2;
+
+ for (int i=0; i < k_rows; i++)
+ {
+ in[i] = src.InLine<SRC>(i - border_y);
+ }
+
+ out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ for (int w=0; w < width; w++)
+ {
+ // TODO: make this cycle innermost
+ for (int c=0; c < chan; c++)
+ {
+ float sum = 0;
+
+ for (int i=0; i < k_rows; i++)
+ for (int j=0; j < k_cols; j++)
+ {
+ sum += in[i][(w + j - border_x)*chan + c] * k[k_cols*i + j];
+ }
+
+ float result = sum + delta;
+
+ out[w*chan + c] = saturate<DST>(result, rintf);
+ }
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidFilter2D, cv::gapi::imgproc::GFilter2D, true)
+{
+ static const int Window = 3;
+
+ static void run(const View & src,
+ int /* ddepth */,
+ const cv::Mat & kernel,
+ const cv::Point & anchor,
+ const cv::Scalar& delta_,
+ int /* borderType */,
+ const cv::Scalar& /* borderValue */,
+ Buffer& dst,
+ Buffer& scratch)
+ {
+ // TODO: support non-trivial anchors
+ GAPI_Assert(anchor.x == -1 && anchor.y == -1);
+
+ // TODO: support kernel heights 3, 5, 7, 9, ...
+ GAPI_Assert(kernel.rows == 3 && kernel.cols == 3);
+
+ float delta = static_cast<float>(delta_[0]);
+
+ int k_rows = kernel.rows;
+ int k_cols = kernel.cols;
+ const float *k = scratch.OutLine<float>(); // copy of kernel.data
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_filter2d, dst, src, k, k_rows, k_cols, anchor, delta);
+ UNARY_(ushort, ushort, run_filter2d, dst, src, k, k_rows, k_cols, anchor, delta);
+ UNARY_( short, short, run_filter2d, dst, src, k, k_rows, k_cols, anchor, delta);
+ UNARY_( float, uchar , run_filter2d, dst, src, k, k_rows, k_cols, anchor, delta);
+ UNARY_( float, ushort, run_filter2d, dst, src, k, k_rows, k_cols, anchor, delta);
+ UNARY_( float, short, run_filter2d, dst, src, k, k_rows, k_cols, anchor, delta);
+ UNARY_( float, float, run_filter2d, dst, src, k, k_rows, k_cols, anchor, delta);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+
+ static void initScratch(const cv::GMatDesc& /* in */,
+ int /* ddepth */,
+ const cv::Mat & kernel,
+ const cv::Point & /* anchor */,
+ const cv::Scalar & /* delta */,
+ int /* borderType */,
+ const cv::Scalar & /* borderValue */,
+ Buffer & scratch)
+ {
+ cv::gapi::own::Size bufsize(kernel.rows * kernel.cols, 1);
+ GMatDesc bufdesc = {CV_32F, 1, bufsize};
+ Buffer buffer(bufdesc);
+ scratch = std::move(buffer);
+
+ // FIXME: move to resetScratch stage ?
+ float *data = scratch.OutLine<float>();
+ getKernel(data, kernel);
+ }
+
+ static void resetScratch(Buffer& /* scratch */)
+ {
+ }
+
+ static Border getBorder(const cv::GMatDesc& /* src */,
+ int /* ddepth */,
+ const cv::Mat& /* kernel */,
+ const cv::Point& /* anchor */,
+ const cv::Scalar& /* delta */,
+ int borderType,
+ const cv::Scalar& borderValue)
+ {
+ return { borderType, borderValue};
+ }
+};
+
+//-----------------------------
+//
+// Fluid kernels: erode, dilate
+//
+//-----------------------------
+
+enum Morphology { M_ERODE, M_DILATE };
+
+template<typename DST, typename SRC>
+static void run_morphology( Buffer& dst,
+ const View & src,
+ const uchar k[],
+ int k_rows,
+ int k_cols,
+ const cv::Point & /* anchor */,
+ Morphology morphology)
+{
+ static const int maxLines = 9;
+ GAPI_Assert(k_rows <= maxLines);
+
+ const SRC *in[ maxLines ];
+ DST *out;
+
+ int border_x = (k_cols - 1) / 2;
+ int border_y = (k_rows - 1) / 2;
+
+ for (int i=0; i < k_rows; i++)
+ {
+ in[i] = src.InLine<SRC>(i - border_y);
+ }
+
+ out = dst.OutLine<DST>();
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ for (int w=0; w < width; w++)
+ {
+ // TODO: make this cycle innermost
+ for (int c=0; c < chan; c++)
+ {
+ SRC result=0;
+ if (M_ERODE == morphology)
+ {
+ result = std::numeric_limits<SRC>::max();
+ }
+ else if (M_DILATE == morphology)
+ {
+ result = std::numeric_limits<SRC>::min();
+ }
+ else
+ CV_Error(cv::Error::StsBadArg, "unsupported morphology operation");
+
+ for (int i=0; i < k_rows; i++)
+ for (int j=0; j < k_cols; j++)
+ {
+ if ( k[k_cols*i + j] )
+ {
+ if (M_ERODE == morphology)
+ {
+ result = std::min(result, in[i][(w + j - border_x)*chan + c]);
+ }
+ else if (M_DILATE == morphology)
+ {
+ result = std::max(result, in[i][(w + j - border_x)*chan + c]);
+ }
+ else
+ CV_Error(cv::Error::StsBadArg, "unsupported morphology operation");
+ }
+ }
+
+ out[w*chan + c] = saturate<DST>(result, rintf);
+ }
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidErode, cv::gapi::imgproc::GErode, true)
+{
+ static const int Window = 3;
+
+ static void run(const View & src,
+ const cv::Mat & kernel,
+ const cv::Point & anchor,
+ int iterations,
+ int /* borderType */,
+ const cv::Scalar& /* borderValue */,
+ Buffer& dst,
+ Buffer& scratch)
+ {
+ // TODO: support non-trivial anchors
+ GAPI_Assert(anchor.x == -1 && anchor.y == -1);
+
+ // TODO: support kernel heights 3, 5, 7, 9, ...
+ GAPI_Assert(kernel.rows == 3 && kernel.cols == 3);
+
+ // TODO: support iterations > 1
+ GAPI_Assert(iterations == 1);
+
+ int k_rows = kernel.rows;
+ int k_cols = kernel.cols;
+
+ auto *k = scratch.OutLine<uchar>(); // copy of kernel.data
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_morphology, dst, src, k, k_rows, k_cols, anchor, M_ERODE);
+ UNARY_(ushort, ushort, run_morphology, dst, src, k, k_rows, k_cols, anchor, M_ERODE);
+ UNARY_( short, short, run_morphology, dst, src, k, k_rows, k_cols, anchor, M_ERODE);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+
+ static void initScratch(const GMatDesc& /* in */,
+ const Mat & kernel,
+ const Point & /* anchor */,
+ int /* iterations */,
+ int /* borderType */,
+ const cv::Scalar & /* borderValue */,
+ Buffer & scratch)
+ {
+ int k_rows = kernel.rows;
+ int k_cols = kernel.cols;
+
+ cv::gapi::own::Size bufsize(k_rows * k_cols, 1);
+ GMatDesc bufdesc = {CV_8U, 1, bufsize};
+ Buffer buffer(bufdesc);
+ scratch = std::move(buffer);
+
+ // FIXME: move to resetScratch stage ?
+ auto *k = scratch.OutLine<uchar>();
+ getKernel(k, kernel);
+ }
+
+ static void resetScratch(Buffer& /* scratch */)
+ {
+ }
+
+ static Border getBorder(const cv::GMatDesc& /* src */,
+ const cv::Mat & /* kernel */,
+ const cv::Point & /* anchor */,
+ int /* iterations */,
+ int borderType,
+ const cv::Scalar& borderValue)
+ {
+ #if 1
+ // TODO: saturate borderValue to image type in general case (not only maximal border)
+ GAPI_Assert(borderType == cv::BORDER_CONSTANT && borderValue[0] == DBL_MAX);
+ return { borderType, cv::gapi::own::Scalar::all(INT_MAX) };
+ #else
+ return { borderType, borderValue };
+ #endif
+ }
+};
+
+GAPI_FLUID_KERNEL(GFluidDilate, cv::gapi::imgproc::GDilate, true)
+{
+ static const int Window = 3;
+
+ static void run(const View & src,
+ const cv::Mat & kernel,
+ const cv::Point & anchor,
+ int iterations,
+ int /* borderType */,
+ const cv::Scalar& /* borderValue */,
+ Buffer& dst,
+ Buffer& scratch)
+ {
+ // TODO: support non-trivial anchors
+ GAPI_Assert(anchor.x == -1 && anchor.y == -1);
+
+ // TODO: support kernel heights 3, 5, 7, 9, ...
+ GAPI_Assert(kernel.rows == 3 && kernel.cols == 3);
+
+ // TODO: support iterations > 1
+ GAPI_Assert(iterations == 1);
+
+ int k_rows = kernel.rows;
+ int k_cols = kernel.cols;
+
+ auto *k = scratch.OutLine<uchar>(); // copy of kernel.data
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_morphology, dst, src, k, k_rows, k_cols, anchor, M_DILATE);
+ UNARY_(ushort, ushort, run_morphology, dst, src, k, k_rows, k_cols, anchor, M_DILATE);
+ UNARY_( short, short, run_morphology, dst, src, k, k_rows, k_cols, anchor, M_DILATE);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+
+ static void initScratch(const GMatDesc& /* in */,
+ const Mat & kernel,
+ const Point & /* anchor */,
+ int /* iterations */,
+ int /* borderType */,
+ const cv::Scalar & /* borderValue */,
+ Buffer & scratch)
+ {
+ int k_rows = kernel.rows;
+ int k_cols = kernel.cols;
+
+ cv::gapi::own::Size bufsize(k_rows * k_cols, 1);
+ GMatDesc bufdesc = {CV_8U, 1, bufsize};
+ Buffer buffer(bufdesc);
+ scratch = std::move(buffer);
+
+ // FIXME: move to resetScratch stage ?
+ auto *k = scratch.OutLine<uchar>();
+ getKernel(k, kernel);
+ }
+
+ static void resetScratch(Buffer& /* scratch */)
+ {
+ }
+
+ static Border getBorder(const cv::GMatDesc& /* src */,
+ const cv::Mat & /* kernel */,
+ const cv::Point & /* anchor */,
+ int /* iterations */,
+ int borderType,
+ const cv::Scalar& borderValue)
+ {
+ #if 1
+ // TODO: fix borderValue for Dilate in general case (not only minimal border)
+ GAPI_Assert(borderType == cv::BORDER_CONSTANT && borderValue[0] == DBL_MAX);
+ return { borderType, cv::gapi::own::Scalar::all(INT_MIN) };
+ #else
+ return { borderType, borderValue };
+ #endif
+ }
+};
+
+//--------------------------
+//
+// Fluid kernels: medianBlur
+//
+//--------------------------
+
+template<typename DST, typename SRC>
+static void run_medianblur( Buffer& dst,
+ const View & src,
+ int ksize)
+{
+ static const int kmax = 9;
+ GAPI_Assert(ksize <= kmax);
+
+ const SRC *in[ kmax ];
+ DST *out;
+
+ int border = (ksize - 1) / 2;
+
+ for (int i=0; i < ksize; i++)
+ {
+ in[i] = src.InLine<SRC>(i - border);
+ }
+
+ out = dst.OutLine<DST>(0);
+
+ int width = dst.length();
+ int chan = dst.meta().chan;
+
+ for (int w=0; w < width; w++)
+ {
+ // TODO: make this cycle innermost
+ for (int c=0; c < chan; c++)
+ {
+ SRC neighbours[kmax * kmax];
+
+ for (int i=0; i < ksize; i++)
+ for (int j=0; j < ksize; j++)
+ {
+ neighbours[i*ksize + j] = in[i][(w + j - border)*chan + c];
+ }
+
+ int length = ksize * ksize;
+ std::nth_element(neighbours, neighbours + length/2, neighbours + length);
+
+ out[w*chan + c] = saturate<DST>(neighbours[length/2], rintf);
+ }
+ }
+}
+
+GAPI_FLUID_KERNEL(GFluidMedianBlur, cv::gapi::imgproc::GMedianBlur, false)
+{
+ static const int Window = 3;
+
+ static void run(const View & src,
+ int ksize,
+ Buffer& dst)
+ {
+ // TODO: support kernel sizes: 3, 5, 7, 9, ...
+ GAPI_Assert(ksize == 3);
+
+ // DST SRC OP __VA_ARGS__
+ UNARY_(uchar , uchar , run_medianblur, dst, src, ksize);
+ UNARY_(ushort, ushort, run_medianblur, dst, src, ksize);
+ UNARY_( short, short, run_medianblur, dst, src, ksize);
+
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
+ }
+
+ static Border getBorder(const cv::GMatDesc& /* src */,
+ int /* ksize */)
+ {
+ int borderType = cv::BORDER_REPLICATE;
+ auto borderValue = cv::Scalar();
+ return { borderType, borderValue };
+ }
+};
+
+} // namespace fliud
+} // namespace gapi
+} // namespace cv
+
+cv::gapi::GKernelPackage cv::gapi::imgproc::fluid::kernels()
+{
+ using namespace cv::gapi::fluid;
+
+ return cv::gapi::kernels
+ < GFluidBGR2Gray
+ , GFluidRGB2Gray
+ , GFluidRGB2GrayCustom
+ , GFluidRGB2YUV
+ , GFluidYUV2RGB
+ , GFluidRGB2Lab
+ , GFluidBGR2LUV
+ , GFluidBlur
+ , GFluidSepFilter
+ , GFluidBoxFilter
+ , GFluidFilter2D
+ , GFluidErode
+ , GFluidDilate
+ , GFluidMedianBlur
+ , GFluidGaussBlur
+ , GFluidSobel
+ #if 0
+ , GFluidCanny -- not fluid (?)
+ , GFluidEqualizeHist -- not fluid
+ #endif
+ >();
+}
+
+#endif // !defined(GAPI_STANDALONE)
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.dispatch.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.dispatch.cpp
new file mode 100644
index 000000000..9b217903e
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.dispatch.cpp
@@ -0,0 +1,93 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+#if !defined(GAPI_STANDALONE)
+
+#include "gfluidimgproc_func.hpp"
+#include "gfluidimgproc_func.simd.hpp"
+#include "backends/fluid/gfluidimgproc_func.simd_declarations.hpp"
+
+#include "gfluidutils.hpp"
+
+#include "opencv2/core/cvdef.h"
+#include "opencv2/core/hal/intrin.hpp"
+
+#include <cmath>
+#include <cstdlib>
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wstrict-overflow"
+#endif
+
+namespace cv {
+namespace gapi {
+namespace fluid {
+
+//----------------------------------
+//
+// Fluid kernels: RGB2Gray, BGR2Gray
+//
+//----------------------------------
+
+void run_rgb2gray_impl(uchar out[], const uchar in[], int width,
+ float coef_r, float coef_g, float coef_b)
+{
+ CV_CPU_DISPATCH(run_rgb2gray_impl,
+ (out, in, width, coef_r, coef_g, coef_b),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+//--------------------------------------
+//
+// Fluid kernels: RGB-to-YUV, YUV-to-RGB
+//
+//--------------------------------------
+
+void run_rgb2yuv_impl(uchar out[], const uchar in[], int width, const float coef[5])
+{
+ CV_CPU_DISPATCH(run_rgb2yuv_impl, (out, in, width, coef), CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void run_yuv2rgb_impl(uchar out[], const uchar in[], int width, const float coef[4])
+{
+ CV_CPU_DISPATCH(run_yuv2rgb_impl, (out, in, width, coef), CV_CPU_DISPATCH_MODES_ALL);
+}
+
+//---------------------
+//
+// Fluid kernels: Sobel
+//
+//---------------------
+
+#define RUN_SOBEL_ROW(DST, SRC) \
+void run_sobel_row(DST out[], const SRC *in[], int width, int chan, \
+ const float kx[], const float ky[], int border, \
+ float scale, float delta, float *buf[], \
+ int y, int y0) \
+{ \
+ CV_CPU_DISPATCH(run_sobel_row, \
+ (out, in, width, chan, kx, ky, border, scale, delta, buf,y, y0), \
+ CV_CPU_DISPATCH_MODES_ALL); \
+}
+
+RUN_SOBEL_ROW(uchar , uchar )
+RUN_SOBEL_ROW(ushort, ushort)
+RUN_SOBEL_ROW( short, uchar )
+RUN_SOBEL_ROW( short, ushort)
+RUN_SOBEL_ROW( short, short)
+RUN_SOBEL_ROW( float, uchar )
+RUN_SOBEL_ROW( float, ushort)
+RUN_SOBEL_ROW( float, short)
+RUN_SOBEL_ROW( float, float)
+
+#undef RUN_SOBEL_ROW
+
+} // namespace fliud
+} // namespace gapi
+} // namespace cv
+
+#endif // !defined(GAPI_STANDALONE)
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.hpp
new file mode 100644
index 000000000..1b6f1b8c0
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.hpp
@@ -0,0 +1,64 @@
+// 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) 2018 Intel Corporation
+
+#pragma once
+
+#if !defined(GAPI_STANDALONE)
+
+#include "opencv2/core.hpp"
+
+namespace cv {
+namespace gapi {
+namespace fluid {
+
+//----------------------------------
+//
+// Fluid kernels: RGB2Gray, BGR2Gray
+//
+//----------------------------------
+
+void run_rgb2gray_impl(uchar out[], const uchar in[], int width,
+ float coef_r, float coef_g, float coef_b);
+
+//--------------------------------------
+//
+// Fluid kernels: RGB-to-YUV, YUV-to-RGB
+//
+//--------------------------------------
+
+void run_rgb2yuv_impl(uchar out[], const uchar in[], int width, const float coef[5]);
+
+void run_yuv2rgb_impl(uchar out[], const uchar in[], int width, const float coef[4]);
+
+//---------------------
+//
+// Fluid kernels: Sobel
+//
+//---------------------
+
+#define RUN_SOBEL_ROW(DST, SRC) \
+void run_sobel_row(DST out[], const SRC *in[], int width, int chan, \
+ const float kx[], const float ky[], int border, \
+ float scale, float delta, float *buf[], \
+ int y, int y0);
+
+RUN_SOBEL_ROW(uchar , uchar )
+RUN_SOBEL_ROW(ushort, ushort)
+RUN_SOBEL_ROW( short, uchar )
+RUN_SOBEL_ROW( short, ushort)
+RUN_SOBEL_ROW( short, short)
+RUN_SOBEL_ROW( float, uchar )
+RUN_SOBEL_ROW( float, ushort)
+RUN_SOBEL_ROW( float, short)
+RUN_SOBEL_ROW( float, float)
+
+#undef RUN_SOBEL_ROW
+
+} // namespace fluid
+} // namespace gapi
+} // namespace cv
+
+#endif // !defined(GAPI_STANDALONE)
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.simd.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.simd.hpp
new file mode 100644
index 000000000..c87be085a
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidimgproc_func.simd.hpp
@@ -0,0 +1,562 @@
+// 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) 2018 Intel Corporation
+
+// NB: allow including this *.hpp several times!
+// #pragma once -- don't: this file is NOT once!
+
+#if !defined(GAPI_STANDALONE)
+
+#include "opencv2/gapi/own/saturate.hpp"
+
+#include "opencv2/core.hpp"
+#include "opencv2/core/hal/intrin.hpp"
+
+#include <cstdint>
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wstrict-overflow"
+#endif
+
+using cv::gapi::own::saturate;
+
+namespace cv {
+namespace gapi {
+namespace fluid {
+
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+
+//----------------------------------
+//
+// Fluid kernels: RGB2Gray, BGR2Gray
+//
+//----------------------------------
+
+void run_rgb2gray_impl(uchar out[], const uchar in[], int width,
+ float coef_r, float coef_g, float coef_b);
+
+//--------------------------------------
+//
+// Fluid kernels: RGB-to-YUV, YUV-to-RGB
+//
+//--------------------------------------
+
+void run_rgb2yuv_impl(uchar out[], const uchar in[], int width, const float coef[5]);
+
+void run_yuv2rgb_impl(uchar out[], const uchar in[], int width, const float coef[4]);
+
+//---------------------
+//
+// Fluid kernels: Sobel
+//
+//---------------------
+
+#define RUN_SOBEL_ROW(DST, SRC) \
+void run_sobel_row(DST out[], const SRC *in[], int width, int chan, \
+ const float kx[], const float ky[], int border, \
+ float scale, float delta, float *buf[], \
+ int y, int y0);
+
+RUN_SOBEL_ROW(uchar , uchar )
+RUN_SOBEL_ROW(ushort, ushort)
+RUN_SOBEL_ROW( short, uchar )
+RUN_SOBEL_ROW( short, ushort)
+RUN_SOBEL_ROW( short, short)
+RUN_SOBEL_ROW( float, uchar )
+RUN_SOBEL_ROW( float, ushort)
+RUN_SOBEL_ROW( float, short)
+RUN_SOBEL_ROW( float, float)
+
+#undef RUN_SOBEL_ROW
+
+//----------------------------------------------------------------------
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+//----------------------------------
+//
+// Fluid kernels: RGB2Gray, BGR2Gray
+//
+//----------------------------------
+
+void run_rgb2gray_impl(uchar out[], const uchar in[], int width,
+ float coef_r, float coef_g, float coef_b)
+{
+ // assume:
+ // - coefficients are less than 1
+ // - and their sum equals 1
+
+ constexpr int unity = 1 << 16; // Q0.0.16 inside ushort:
+ ushort rc = static_cast<ushort>(coef_r * unity + 0.5f);
+ ushort gc = static_cast<ushort>(coef_g * unity + 0.5f);
+ ushort bc = static_cast<ushort>(coef_b * unity + 0.5f);
+
+ GAPI_Assert(rc + gc + bc <= unity);
+ GAPI_Assert(rc + gc + bc >= USHRT_MAX);
+
+#if CV_SIMD
+ constexpr int nlanes = v_uint8::nlanes;
+ if (width >= nlanes)
+ {
+ for (int w=0; w < width; )
+ {
+ // process main part of pixels row
+ for ( ; w <= width - nlanes; w += nlanes)
+ {
+ v_uint8 r, g, b;
+ v_load_deinterleave(&in[3*w], r, g, b);
+
+ v_uint16 r0, r1, g0, g1, b0, b1;
+ v_expand(r, r0, r1);
+ v_expand(g, g0, g1);
+ v_expand(b, b0, b1);
+
+ v_uint16 y0, y1;
+ static const ushort half = 1 << 7; // Q0.8.8
+ y0 = (v_mul_hi(r0 << 8, vx_setall_u16(rc)) +
+ v_mul_hi(g0 << 8, vx_setall_u16(gc)) +
+ v_mul_hi(b0 << 8, vx_setall_u16(bc)) +
+ vx_setall_u16(half)) >> 8;
+ y1 = (v_mul_hi(r1 << 8, vx_setall_u16(rc)) +
+ v_mul_hi(g1 << 8, vx_setall_u16(gc)) +
+ v_mul_hi(b1 << 8, vx_setall_u16(bc)) +
+ vx_setall_u16(half)) >> 8;
+
+ v_uint8 y;
+ y = v_pack(y0, y1);
+ v_store(&out[w], y);
+ }
+
+ // process tail (if any)
+ if (w < width)
+ {
+ GAPI_DbgAssert(width - nlanes >= 0);
+ w = width - nlanes;
+ }
+ }
+
+ return;
+ }
+#endif
+
+ for (int w=0; w < width; w++)
+ {
+ uchar r = in[3*w ];
+ uchar g = in[3*w + 1];
+ uchar b = in[3*w + 2];
+
+ static const int half = 1 << 15; // Q0.0.16
+ ushort y = (r*rc + b*bc + g*gc + half) >> 16;
+ out[w] = static_cast<uchar>(y);
+ }
+}
+
+//--------------------------------------
+//
+// Fluid kernels: RGB-to-YUV, YUV-to-RGB
+//
+//--------------------------------------
+
+void run_rgb2yuv_impl(uchar out[], const uchar in[], int width, const float coef[5])
+{
+ ushort c0 = static_cast<ushort>(coef[0]*(1 << 16) + 0.5f); // Q0.0.16 un-signed
+ ushort c1 = static_cast<ushort>(coef[1]*(1 << 16) + 0.5f);
+ ushort c2 = static_cast<ushort>(coef[2]*(1 << 16) + 0.5f);
+ short c3 = static_cast<short>(coef[3]*(1 << 12) + 0.5f); // Q1.0.12 signed
+ short c4 = static_cast<short>(coef[4]*(1 << 12) + 0.5f);
+
+ int w = 0;
+
+#if CV_SIMD
+ static const int nlanes = v_uint8::nlanes;
+ for ( ; w <= width - nlanes; w += nlanes)
+ {
+ v_uint8 r, g, b;
+ v_load_deinterleave(&in[3*w], r, g, b);
+
+ v_uint16 _r0, _r1, _g0, _g1, _b0, _b1;
+ v_expand(r, _r0, _r1);
+ v_expand(g, _g0, _g1);
+ v_expand(b, _b0, _b1);
+
+ _r0 = _r0 << 7; // Q0.9.7 un-signed
+ _r1 = _r1 << 7;
+ _g0 = _g0 << 7;
+ _g1 = _g1 << 7;
+ _b0 = _b0 << 7;
+ _b1 = _b1 << 7;
+
+ v_uint16 _y0, _y1;
+ _y0 = v_mul_hi(vx_setall_u16(c0), _r0) // Q0.9.7
+ + v_mul_hi(vx_setall_u16(c1), _g0)
+ + v_mul_hi(vx_setall_u16(c2), _b0);
+ _y1 = v_mul_hi(vx_setall_u16(c0), _r1)
+ + v_mul_hi(vx_setall_u16(c1), _g1)
+ + v_mul_hi(vx_setall_u16(c2), _b1);
+
+ v_int16 r0, r1, b0, b1, y0, y1;
+ r0 = v_reinterpret_as_s16(_r0); // Q1.8.7 signed
+ r1 = v_reinterpret_as_s16(_r1);
+ b0 = v_reinterpret_as_s16(_b0);
+ b1 = v_reinterpret_as_s16(_b1);
+ y0 = v_reinterpret_as_s16(_y0);
+ y1 = v_reinterpret_as_s16(_y1);
+
+ v_int16 u0, u1, v0, v1;
+ u0 = v_mul_hi(vx_setall_s16(c3), b0 - y0); // Q1.12.3
+ u1 = v_mul_hi(vx_setall_s16(c3), b1 - y1);
+ v0 = v_mul_hi(vx_setall_s16(c4), r0 - y0);
+ v1 = v_mul_hi(vx_setall_s16(c4), r1 - y1);
+
+ v_uint8 y, u, v;
+ y = v_pack((_y0 + vx_setall_u16(1 << 6)) >> 7,
+ (_y1 + vx_setall_u16(1 << 6)) >> 7);
+ u = v_pack_u((u0 + vx_setall_s16(257 << 2)) >> 3, // 257 << 2 = 128.5 * (1 << 3)
+ (u1 + vx_setall_s16(257 << 2)) >> 3);
+ v = v_pack_u((v0 + vx_setall_s16(257 << 2)) >> 3,
+ (v1 + vx_setall_s16(257 << 2)) >> 3);
+
+ v_store_interleave(&out[3*w], y, u, v);
+ }
+#endif
+
+ for ( ; w < width; w++)
+ {
+ short r = in[3*w ] << 7; // Q1.8.7 signed
+ short g = in[3*w + 1] << 7;
+ short b = in[3*w + 2] << 7;
+ short y = (c0*r + c1*g + c2*b) >> 16; // Q1.8.7
+ short u = c3*(b - y) >> 16; // Q1.12.3
+ short v = c4*(r - y) >> 16;
+ out[3*w ] = static_cast<uchar>((y + (1 << 6)) >> 7);
+ out[3*w + 1] = saturate<uchar>((u + (128 << 3) + (1 << 2)) >> 3);
+ out[3*w + 2] = saturate<uchar>((v + (128 << 3) + (1 << 2)) >> 3);
+ }
+}
+
+void run_yuv2rgb_impl(uchar out[], const uchar in[], int width, const float coef[4])
+{
+ short c0 = static_cast<short>(coef[0] * (1 << 12) + 0.5f); // Q1.3.12
+ short c1 = static_cast<short>(coef[1] * (1 << 12) + 0.5f);
+ short c2 = static_cast<short>(coef[2] * (1 << 12) + 0.5f);
+ short c3 = static_cast<short>(coef[3] * (1 << 12) + 0.5f);
+
+ int w = 0;
+
+#if CV_SIMD
+ static const int nlanes = v_uint8::nlanes;
+ for ( ; w <= width - nlanes; w += nlanes)
+ {
+ v_uint8 y, u, v;
+ v_load_deinterleave(&in[3*w], y, u, v);
+
+ v_uint16 _y0, _y1, _u0, _u1, _v0, _v1;
+ v_expand(y, _y0, _y1);
+ v_expand(u, _u0, _u1);
+ v_expand(v, _v0, _v1);
+
+ v_int16 y0, y1, u0, u1, v0, v1;
+ y0 = v_reinterpret_as_s16(_y0);
+ y1 = v_reinterpret_as_s16(_y1);
+ u0 = v_reinterpret_as_s16(_u0);
+ u1 = v_reinterpret_as_s16(_u1);
+ v0 = v_reinterpret_as_s16(_v0);
+ v1 = v_reinterpret_as_s16(_v1);
+
+ y0 = y0 << 3; // Q1.12.3
+ y1 = y1 << 3;
+ u0 = (u0 - vx_setall_s16(128)) << 7; // Q1.8.7
+ u1 = (u1 - vx_setall_s16(128)) << 7;
+ v0 = (v0 - vx_setall_s16(128)) << 7;
+ v1 = (v1 - vx_setall_s16(128)) << 7;
+
+ v_int16 r0, r1, g0, g1, b0, b1;
+ r0 = y0 + v_mul_hi(vx_setall_s16(c0), v0); // Q1.12.3
+ r1 = y1 + v_mul_hi(vx_setall_s16(c0), v1);
+ g0 = y0 + v_mul_hi(vx_setall_s16(c1), u0)
+ + v_mul_hi(vx_setall_s16(c2), v0);
+ g1 = y1 + v_mul_hi(vx_setall_s16(c1), u1)
+ + v_mul_hi(vx_setall_s16(c2), v1);
+ b0 = y0 + v_mul_hi(vx_setall_s16(c3), u0);
+ b1 = y1 + v_mul_hi(vx_setall_s16(c3), u1);
+
+ v_uint8 r, g, b;
+ r = v_pack_u((r0 + vx_setall_s16(1 << 2)) >> 3,
+ (r1 + vx_setall_s16(1 << 2)) >> 3);
+ g = v_pack_u((g0 + vx_setall_s16(1 << 2)) >> 3,
+ (g1 + vx_setall_s16(1 << 2)) >> 3);
+ b = v_pack_u((b0 + vx_setall_s16(1 << 2)) >> 3,
+ (b1 + vx_setall_s16(1 << 2)) >> 3);
+
+ v_store_interleave(&out[3*w], r, g, b);
+ }
+#endif
+
+ for ( ; w < width; w++)
+ {
+ short y = in[3*w ] << 3; // Q1.12.3
+ short u = (in[3*w + 1] - 128) << 7; // Q1.8.7
+ short v = (in[3*w + 2] - 128) << 7;
+ short r = y + ( c0*v >> 16); // Q1.12.3
+ short g = y + ((c1*u + c2*v) >> 16);
+ short b = y + ((c3*u ) >> 16);
+ out[3*w ] = saturate<uchar>((r + (1 << 2)) >> 3);
+ out[3*w + 1] = saturate<uchar>((g + (1 << 2)) >> 3);
+ out[3*w + 2] = saturate<uchar>((b + (1 << 2)) >> 3);
+ }
+}
+
+//---------------------
+//
+// Fluid kernels: Sobel
+//
+//---------------------
+
+// Sobel 3x3: vertical pass
+template<bool noscale, typename DST>
+static void run_sobel3x3_vert(DST out[], int length, const float ky[],
+ float scale, float delta, const int r[], float *buf[])
+{
+ float ky0 = ky[0],
+ ky1 = ky[1],
+ ky2 = ky[2];
+
+ int r0 = r[0],
+ r1 = r[1],
+ r2 = r[2];
+
+#if CV_SIMD
+ // for floating-point output,
+ // manual vectoring may be not better than compiler's optimization
+#define EXPLICIT_SIMD_32F 0 // 1=vectorize 32f case explicitly, 0=don't
+#if EXPLICIT_SIMD_32F
+ if (std::is_same<DST, float>::value && length >= v_int16::nlanes)
+ {
+ constexpr static int nlanes = v_float32::nlanes;
+
+ for (int l=0; l < length; )
+ {
+ for (; l <= length - nlanes; l += nlanes)
+ {
+ v_float32 sum = vx_load(&buf[r0][l]) * vx_setall_f32(ky0);
+ sum = v_fma(vx_load(&buf[r1][l]), vx_setall_f32(ky1), sum);
+ sum = v_fma(vx_load(&buf[r2][l]), vx_setall_f32(ky2), sum);
+
+ if (!noscale)
+ {
+ sum = v_fma(sum, vx_setall_f32(scale), vx_setall_f32(delta));
+ }
+
+ v_store(reinterpret_cast<float*>(&out[l]), sum);
+ }
+
+ if (l < length)
+ {
+ // tail: recalculate last pixels
+ GAPI_DbgAssert(length >= nlanes);
+ l = length - nlanes;
+ }
+ }
+
+ return;
+ }
+#endif
+
+ if ((std::is_same<DST, short>::value || std::is_same<DST, ushort>::value)
+ && length >= v_int16::nlanes)
+ {
+ constexpr static int nlanes = v_int16::nlanes;
+
+ for (int l=0; l < length; )
+ {
+ for (; l <= length - nlanes; l += nlanes)
+ {
+ v_float32 sum0 = vx_load(&buf[r0][l]) * vx_setall_f32(ky0);
+ sum0 = v_fma(vx_load(&buf[r1][l]), vx_setall_f32(ky1), sum0);
+ sum0 = v_fma(vx_load(&buf[r2][l]), vx_setall_f32(ky2), sum0);
+
+ v_float32 sum1 = vx_load(&buf[r0][l + nlanes/2]) * vx_setall_f32(ky0);
+ sum1 = v_fma(vx_load(&buf[r1][l + nlanes/2]), vx_setall_f32(ky1), sum1);
+ sum1 = v_fma(vx_load(&buf[r2][l + nlanes/2]), vx_setall_f32(ky2), sum1);
+
+ if (!noscale)
+ {
+ sum0 = v_fma(sum0, vx_setall_f32(scale), vx_setall_f32(delta));
+ sum1 = v_fma(sum1, vx_setall_f32(scale), vx_setall_f32(delta));
+ }
+
+ v_int32 isum0 = v_round(sum0),
+ isum1 = v_round(sum1);
+
+ if (std::is_same<DST, short>::value)
+ {
+ // signed short
+ v_int16 res = v_pack(isum0, isum1);
+ v_store(reinterpret_cast<short*>(&out[l]), res);
+ } else
+ {
+ // unsigned short
+ v_uint16 res = v_pack_u(isum0, isum1);
+ v_store(reinterpret_cast<ushort*>(&out[l]), res);
+ }
+ }
+
+ if (l < length)
+ {
+ // tail: recalculate last pixels
+ GAPI_DbgAssert(length >= nlanes);
+ l = length - nlanes;
+ }
+ }
+
+ return;
+ }
+
+ if (std::is_same<DST, uchar>::value && length >= v_uint8::nlanes)
+ {
+ constexpr static int nlanes = v_uint8::nlanes;
+
+ for (int l=0; l < length; )
+ {
+ for (; l <= length - nlanes; l += nlanes)
+ {
+ v_float32 sum0 = vx_load(&buf[r0][l]) * vx_setall_f32(ky0);
+ sum0 = v_fma(vx_load(&buf[r1][l]), vx_setall_f32(ky1), sum0);
+ sum0 = v_fma(vx_load(&buf[r2][l]), vx_setall_f32(ky2), sum0);
+
+ v_float32 sum1 = vx_load(&buf[r0][l + nlanes/4]) * vx_setall_f32(ky0);
+ sum1 = v_fma(vx_load(&buf[r1][l + nlanes/4]), vx_setall_f32(ky1), sum1);
+ sum1 = v_fma(vx_load(&buf[r2][l + nlanes/4]), vx_setall_f32(ky2), sum1);
+
+ v_float32 sum2 = vx_load(&buf[r0][l + 2*nlanes/4]) * vx_setall_f32(ky0);
+ sum2 = v_fma(vx_load(&buf[r1][l + 2*nlanes/4]), vx_setall_f32(ky1), sum2);
+ sum2 = v_fma(vx_load(&buf[r2][l + 2*nlanes/4]), vx_setall_f32(ky2), sum2);
+
+ v_float32 sum3 = vx_load(&buf[r0][l + 3*nlanes/4]) * vx_setall_f32(ky0);
+ sum3 = v_fma(vx_load(&buf[r1][l + 3*nlanes/4]), vx_setall_f32(ky1), sum3);
+ sum3 = v_fma(vx_load(&buf[r2][l + 3*nlanes/4]), vx_setall_f32(ky2), sum3);
+
+ if (!noscale)
+ {
+ sum0 = v_fma(sum0, vx_setall_f32(scale), vx_setall_f32(delta));
+ sum1 = v_fma(sum1, vx_setall_f32(scale), vx_setall_f32(delta));
+ sum2 = v_fma(sum2, vx_setall_f32(scale), vx_setall_f32(delta));
+ sum3 = v_fma(sum3, vx_setall_f32(scale), vx_setall_f32(delta));
+ }
+
+ v_int32 isum0 = v_round(sum0),
+ isum1 = v_round(sum1),
+ isum2 = v_round(sum2),
+ isum3 = v_round(sum3);
+
+ v_int16 ires0 = v_pack(isum0, isum1),
+ ires1 = v_pack(isum2, isum3);
+
+ v_uint8 res = v_pack_u(ires0, ires1);
+ v_store(reinterpret_cast<uchar*>(&out[l]), res);
+ }
+
+ if (l < length)
+ {
+ // tail: recalculate last pixels
+ GAPI_DbgAssert(length >= nlanes);
+ l = length - nlanes;
+ }
+ }
+
+ return;
+ }
+#endif
+
+ // reference code
+ for (int l=0; l < length; l++)
+ {
+ float sum = buf[r0][l]*ky0 + buf[r1][l]*ky1 + buf[r2][l]*ky2;
+
+ if (!noscale)
+ {
+ sum = sum*scale + delta;
+ }
+
+ out[l] = cv::gapi::own::saturate<DST>(sum, rintf);
+ }
+}
+
+template<typename DST, typename SRC>
+static void run_sobel_impl(DST out[], const SRC *in[], int width, int chan,
+ const float kx[], const float ky[], int border,
+ float scale, float delta, float *buf[],
+ int y, int y0)
+{
+ int r[3];
+ r[0] = (y - y0) % 3; // buf[r[0]]: previous
+ r[1] = (y - y0 + 1) % 3; // this
+ r[2] = (y - y0 + 2) % 3; // next row
+
+ int length = width * chan;
+
+ // horizontal pass
+
+ // full horizontal pass is needed only if very 1st row in ROI;
+ // for 2nd and further rows, it is enough to convolve only the
+ // "next" row - as we can reuse buffers from previous calls to
+ // this kernel (note that Fluid processes rows consequently)
+ int k0 = (y == y0)? 0: 2;
+
+ for (int k = k0; k < 3; k++)
+ {
+ // previous, this , next pixel
+ const SRC *s[3] = {in[k] - border*chan , in[k], in[k] + border*chan};
+
+ // rely on compiler vectoring
+ for (int l=0; l < length; l++)
+ {
+ buf[r[k]][l] = s[0][l]*kx[0] + s[1][l]*kx[1] + s[2][l]*kx[2];
+ }
+ }
+
+ // vertical pass
+ if (scale == 1 && delta == 0)
+ {
+ constexpr static bool noscale = true; // omit scaling
+ run_sobel3x3_vert<noscale, DST>(out, length, ky, scale, delta, r, buf);
+ } else
+ {
+ constexpr static bool noscale = false; // do scaling
+ run_sobel3x3_vert<noscale, DST>(out, length, ky, scale, delta, r, buf);
+ }
+}
+
+#define RUN_SOBEL_ROW(DST, SRC) \
+void run_sobel_row(DST out[], const SRC *in[], int width, int chan, \
+ const float kx[], const float ky[], int border, \
+ float scale, float delta, float *buf[], \
+ int y, int y0) \
+{ \
+ run_sobel_impl(out, in, width, chan, kx, ky, border, scale, delta, buf,y, y0); \
+}
+
+RUN_SOBEL_ROW(uchar , uchar )
+RUN_SOBEL_ROW(ushort, ushort)
+RUN_SOBEL_ROW( short, uchar )
+RUN_SOBEL_ROW( short, ushort)
+RUN_SOBEL_ROW( short, short)
+RUN_SOBEL_ROW( float, uchar )
+RUN_SOBEL_ROW( float, ushort)
+RUN_SOBEL_ROW( float, short)
+RUN_SOBEL_ROW( float, float)
+
+#undef RUN_SOBEL_ROW
+
+#endif // CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+
+} // namespace fluid
+} // namespace gapi
+} // namespace cv
+
+#endif // !defined(GAPI_STANDALONE)
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidutils.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidutils.hpp
new file mode 100644
index 000000000..a38b2f132
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/fluid/gfluidutils.hpp
@@ -0,0 +1,93 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef GFLUIDUTILS_HPP
+#define GFLUIDUTILS_HPP
+
+#include <limits>
+#include <type_traits>
+#include <opencv2/gapi/util/compiler_hints.hpp> //UNUSED
+#include <opencv2/gapi/own/saturate.hpp>
+
+namespace cv {
+namespace gapi {
+namespace fluid {
+
+using cv::gapi::own::saturate;
+using cv::gapi::own::ceild;
+using cv::gapi::own::floord;
+using cv::gapi::own::roundd;
+using cv::gapi::own::rintd;
+
+//--------------------------------
+//
+// Macros for mappig of data types
+//
+//--------------------------------
+
+#define UNARY_(DST, SRC, OP, ...) \
+ if (cv::DataType<DST>::depth == dst.meta().depth && \
+ cv::DataType<SRC>::depth == src.meta().depth) \
+ { \
+ GAPI_DbgAssert(dst.length() == src.length()); \
+ GAPI_DbgAssert(dst.meta().chan == src.meta().chan); \
+ \
+ OP<DST, SRC>(__VA_ARGS__); \
+ return; \
+ }
+
+// especial unary operation: dst is always 8UC1 image
+#define INRANGE_(DST, SRC, OP, ...) \
+ if (cv::DataType<DST>::depth == dst.meta().depth && \
+ cv::DataType<SRC>::depth == src.meta().depth) \
+ { \
+ GAPI_DbgAssert(dst.length() == src.length()); \
+ GAPI_DbgAssert(dst.meta().chan == 1); \
+ \
+ OP<DST, SRC>(__VA_ARGS__); \
+ return; \
+ }
+
+#define BINARY_(DST, SRC1, SRC2, OP, ...) \
+ if (cv::DataType<DST>::depth == dst.meta().depth && \
+ cv::DataType<SRC1>::depth == src1.meta().depth && \
+ cv::DataType<SRC2>::depth == src2.meta().depth) \
+ { \
+ GAPI_DbgAssert(dst.length() == src1.length()); \
+ GAPI_DbgAssert(dst.length() == src2.length()); \
+ \
+ GAPI_DbgAssert(dst.meta().chan == src1.meta().chan); \
+ GAPI_DbgAssert(dst.meta().chan == src2.meta().chan); \
+ \
+ OP<DST, SRC1, SRC2>(__VA_ARGS__); \
+ return; \
+ }
+
+// especial ternary operation: src3 has only one channel
+#define SELECT_(DST, SRC1, SRC2, SRC3, OP, ...) \
+ if (cv::DataType<DST>::depth == dst.meta().depth && \
+ cv::DataType<SRC1>::depth == src1.meta().depth && \
+ cv::DataType<SRC2>::depth == src2.meta().depth && \
+ cv::DataType<SRC3>::depth == src3.meta().depth) \
+ { \
+ GAPI_DbgAssert(dst.length() == src1.length()); \
+ GAPI_DbgAssert(dst.length() == src2.length()); \
+ GAPI_DbgAssert(dst.length() == src3.length()); \
+ \
+ GAPI_DbgAssert(dst.meta().chan == src1.meta().chan); \
+ GAPI_DbgAssert(dst.meta().chan == src2.meta().chan); \
+ GAPI_DbgAssert( 1 == src3.meta().chan); \
+ \
+ OP<DST, SRC1, SRC2, SRC3>(__VA_ARGS__); \
+ return; \
+ }
+
+} // namespace fluid
+} // namespace gapi
+} // namespace cv
+
+#endif // GFLUIDUTILS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpubackend.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpubackend.cpp
new file mode 100644
index 000000000..eda6a5fd7
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpubackend.cpp
@@ -0,0 +1,226 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <functional>
+#include <unordered_set>
+
+#include <ade/util/algorithm.hpp>
+
+#include <ade/util/range.hpp>
+#include <ade/util/zip_range.hpp>
+#include <ade/util/chain_range.hpp>
+
+#include <ade/typed_graph.hpp>
+
+#include "opencv2/gapi/gcommon.hpp"
+#include "opencv2/gapi/util/any.hpp"
+#include "opencv2/gapi/gtype_traits.hpp"
+
+#include "compiler/gobjref.hpp"
+#include "compiler/gmodel.hpp"
+
+#include "backends/gpu/ggpubackend.hpp"
+#include "backends/gpu/ggpuimgproc.hpp"
+#include "backends/gpu/ggpucore.hpp"
+
+#include "api/gbackend_priv.hpp" // FIXME: Make it part of Backend SDK!
+
+// FIXME: Is there a way to take a typed graph (our GModel),
+// and create a new typed graph _ATOP_ of that (by extending with a couple of
+// new types?).
+// Alternatively, is there a way to compose types graphs?
+//
+// If not, we need to introduce that!
+using GGPUModel = ade::TypedGraph
+ < cv::gimpl::Unit
+ , cv::gimpl::Protocol
+ >;
+
+// FIXME: Same issue with Typed and ConstTyped
+using GConstGGPUModel = ade::ConstTypedGraph
+ < cv::gimpl::Unit
+ , cv::gimpl::Protocol
+ >;
+
+namespace
+{
+ class GGPUBackendImpl final: public cv::gapi::GBackend::Priv
+ {
+ virtual void unpackKernel(ade::Graph &graph,
+ const ade::NodeHandle &op_node,
+ const cv::GKernelImpl &impl) override
+ {
+ GGPUModel gm(graph);
+ auto gpu_impl = cv::util::any_cast<cv::GGPUKernel>(impl.opaque);
+ gm.metadata(op_node).set(cv::gimpl::Unit{gpu_impl});
+ }
+
+ virtual EPtr compile(const ade::Graph &graph,
+ const cv::GCompileArgs &,
+ const std::vector<ade::NodeHandle> &nodes) const override
+ {
+ return EPtr{new cv::gimpl::GGPUExecutable(graph, nodes)};
+ }
+ };
+}
+
+cv::gapi::GBackend cv::gapi::gpu::backend()
+{
+ static cv::gapi::GBackend this_backend(std::make_shared<GGPUBackendImpl>());
+ return this_backend;
+}
+
+// GGPUExcecutable implementation //////////////////////////////////////////////
+cv::gimpl::GGPUExecutable::GGPUExecutable(const ade::Graph &g,
+ const std::vector<ade::NodeHandle> &nodes)
+ : m_g(g), m_gm(m_g)
+{
+ // Convert list of operations (which is topologically sorted already)
+ // into an execution script.
+ for (auto &nh : nodes)
+ {
+ switch (m_gm.metadata(nh).get<NodeType>().t)
+ {
+ case NodeType::OP: m_script.push_back({nh, GModel::collectOutputMeta(m_gm, nh)}); break;
+ case NodeType::DATA:
+ {
+ m_dataNodes.push_back(nh);
+ const auto &desc = m_gm.metadata(nh).get<Data>();
+ if (desc.storage == Data::Storage::CONST)
+ {
+ auto rc = RcDesc{desc.rc, desc.shape, desc.ctor};
+ magazine::bindInArg(m_res, rc, m_gm.metadata(nh).get<ConstValue>().arg);
+ }
+ //preallocate internal Mats in advance
+ if (desc.storage == Data::Storage::INTERNAL && desc.shape == GShape::GMAT)
+ {
+ const auto mat_desc = util::get<cv::GMatDesc>(desc.meta);
+ const auto type = CV_MAKETYPE(mat_desc.depth, mat_desc.chan);
+ m_res.slot<cv::UMat>()[desc.rc].create(mat_desc.size.width, mat_desc.size.height, type);
+ }
+ break;
+ }
+ default: util::throw_error(std::logic_error("Unsupported NodeType type"));
+ }
+ }
+}
+
+// FIXME: Document what it does
+cv::GArg cv::gimpl::GGPUExecutable::packArg(const GArg &arg)
+{
+ // No API placeholders allowed at this point
+ // FIXME: this check has to be done somewhere in compilation stage.
+ GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT
+ && arg.kind != cv::detail::ArgKind::GSCALAR
+ && arg.kind != cv::detail::ArgKind::GARRAY);
+
+ if (arg.kind != cv::detail::ArgKind::GOBJREF)
+ {
+ // All other cases - pass as-is, with no transformations to GArg contents.
+ return arg;
+ }
+ GAPI_Assert(arg.kind == cv::detail::ArgKind::GOBJREF);
+
+ // Wrap associated CPU object (either host or an internal one)
+ // FIXME: object can be moved out!!! GExecutor faced that.
+ const cv::gimpl::RcDesc &ref = arg.get<cv::gimpl::RcDesc>();
+ switch (ref.shape)
+ {
+ case GShape::GMAT: return GArg(m_res.slot<cv::UMat>()[ref.id]);
+ case GShape::GSCALAR: return GArg(m_res.slot<cv::gapi::own::Scalar>()[ref.id]);
+ // Note: .at() is intentional for GArray as object MUST be already there
+ // (and constructed by either bindIn/Out or resetInternal)
+ case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id));
+ default:
+ util::throw_error(std::logic_error("Unsupported GShape type"));
+ break;
+ }
+}
+
+void cv::gimpl::GGPUExecutable::run(std::vector<InObj> &&input_objs,
+ std::vector<OutObj> &&output_objs)
+{
+ // Update resources with run-time information - what this Island
+ // has received from user (or from another Island, or mix...)
+ // FIXME: Check input/output objects against GIsland protocol
+
+ for (auto& it : input_objs) magazine::bindInArg (m_res, it.first, it.second, true);
+ for (auto& it : output_objs) magazine::bindOutArg(m_res, it.first, it.second, true);
+
+ // Initialize (reset) internal data nodes with user structures
+ // before processing a frame (no need to do it for external data structures)
+ GModel::ConstGraph gm(m_g);
+ for (auto nh : m_dataNodes)
+ {
+ const auto &desc = gm.metadata(nh).get<Data>();
+
+ if ( desc.storage == Data::Storage::INTERNAL
+ && !util::holds_alternative<util::monostate>(desc.ctor))
+ {
+ // FIXME: Note that compile-time constant data objects (like
+ // a value-initialized GArray<T>) also satisfy this condition
+ // and should be excluded, but now we just don't support it
+ magazine::resetInternalData(m_res, desc);
+ }
+ }
+
+ // OpenCV backend execution is not a rocket science at all.
+ // Simply invoke our kernels in the proper order.
+ GConstGGPUModel gcm(m_g);
+ for (auto &op_info : m_script)
+ {
+ const auto &op = m_gm.metadata(op_info.nh).get<Op>();
+
+ // Obtain our real execution unit
+ // TODO: Should kernels be copyable?
+ GGPUKernel k = gcm.metadata(op_info.nh).get<Unit>().k;
+
+ // Initialize kernel's execution context:
+ // - Input parameters
+ GGPUContext context;
+ context.m_args.reserve(op.args.size());
+
+ using namespace std::placeholders;
+ ade::util::transform(op.args,
+ std::back_inserter(context.m_args),
+ std::bind(&GGPUExecutable::packArg, this, _1));
+
+ // - Output parameters.
+ // FIXME: pre-allocate internal Mats, etc, according to the known meta
+ for (const auto &out_it : ade::util::indexed(op.outs))
+ {
+ // FIXME: Can the same GArg type resolution mechanism be reused here?
+ const auto out_port = ade::util::index(out_it);
+ const auto out_desc = ade::util::value(out_it);
+ context.m_results[out_port] = magazine::getObjPtr(m_res, out_desc, true);
+ }
+
+ // Now trigger the executable unit
+ k.apply(context);
+
+ for (const auto &out_it : ade::util::indexed(op_info.expected_out_metas))
+ {
+ const auto out_index = ade::util::index(out_it);
+ const auto expected_meta = ade::util::value(out_it);
+ const auto out_meta = descr_of(context.m_results[out_index]);
+
+ if (expected_meta != out_meta)
+ {
+ util::throw_error
+ (std::logic_error
+ ("Output meta doesn't "
+ "coincide with the generated meta\n"
+ "Expected: " + ade::util::to_string(expected_meta) + "\n"
+ "Actual : " + ade::util::to_string(out_meta)));
+ }
+ }
+ } // for(m_script)
+
+ for (auto &it : output_objs) magazine::writeBack(m_res, it.first, it.second, true);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpubackend.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpubackend.hpp
new file mode 100644
index 000000000..1fb128d5f
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpubackend.hpp
@@ -0,0 +1,72 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GGPUBACKEND_HPP
+#define OPENCV_GAPI_GGPUBACKEND_HPP
+
+#include <map> // map
+#include <unordered_map> // unordered_map
+#include <tuple> // tuple
+#include <ade/util/algorithm.hpp> // type_list_index
+
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gproto.hpp"
+#include "opencv2/gapi/gpu/ggpukernel.hpp"
+
+
+#include "api/gapi_priv.hpp"
+#include "backends/common/gbackend.hpp"
+#include "compiler/gislandmodel.hpp"
+
+namespace cv { namespace gimpl {
+
+struct Unit
+{
+ static const char *name() { return "GPUKernel"; }
+ GGPUKernel k;
+};
+
+class GGPUExecutable final: public GIslandExecutable
+{
+ const ade::Graph &m_g;
+ GModel::ConstGraph m_gm;
+
+ struct OperationInfo
+ {
+ ade::NodeHandle nh;
+ GMetaArgs expected_out_metas;
+ };
+
+ // Execution script, currently absolutely naive
+ std::vector<OperationInfo> m_script;
+ // List of all resources in graph (both internal and external)
+ std::vector<ade::NodeHandle> m_dataNodes;
+
+ // Actual data of all resources in graph (both internal and external)
+ Mag m_res;
+ GArg packArg(const GArg &arg);
+
+public:
+ GGPUExecutable(const ade::Graph &graph,
+ const std::vector<ade::NodeHandle> &nodes);
+
+ virtual inline bool canReshape() const override { return false; }
+ virtual inline void reshape(ade::Graph&, const GCompileArgs&) override
+ {
+ // FIXME: GPU plugin is in fact reshapeable (as it was initially,
+ // even before outMeta() has been introduced), so this limitation
+ // should be dropped.
+ util::throw_error(std::logic_error("GGPUExecutable::reshape() should never be called"));
+ }
+
+ virtual void run(std::vector<InObj> &&input_objs,
+ std::vector<OutObj> &&output_objs) override;
+};
+
+}}
+
+#endif // OPENCV_GAPI_GGPUBACKEND_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpucore.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpucore.cpp
new file mode 100644
index 000000000..a1ee6a113
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpucore.cpp
@@ -0,0 +1,582 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/core.hpp"
+#include "opencv2/gapi/gpu/core.hpp"
+#include "backends/gpu/ggpucore.hpp"
+
+GAPI_GPU_KERNEL(GGPUAdd, cv::gapi::core::GAdd)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, int dtype, cv::UMat& out)
+ {
+ cv::add(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUAddC, cv::gapi::core::GAddC)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, int dtype, cv::UMat& out)
+ {
+ cv::add(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUSub, cv::gapi::core::GSub)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, int dtype, cv::UMat& out)
+ {
+ cv::subtract(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUSubC, cv::gapi::core::GSubC)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, int dtype, cv::UMat& out)
+ {
+ cv::subtract(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUSubRC, cv::gapi::core::GSubRC)
+{
+ static void run(const cv::Scalar& a, const cv::UMat& b, int dtype, cv::UMat& out)
+ {
+ cv::subtract(a, b, out, cv::noArray(), dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUMul, cv::gapi::core::GMul)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, double scale, int dtype, cv::UMat& out)
+ {
+ cv::multiply(a, b, out, scale, dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUMulCOld, cv::gapi::core::GMulCOld)
+{
+ static void run(const cv::UMat& a, double b, int dtype, cv::UMat& out)
+ {
+ cv::multiply(a, b, out, 1, dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUMulC, cv::gapi::core::GMulC)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, int dtype, cv::UMat& out)
+ {
+ cv::multiply(a, b, out, 1, dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUDiv, cv::gapi::core::GDiv)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, double scale, int dtype, cv::UMat& out)
+ {
+ cv::divide(a, b, out, scale, dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUDivC, cv::gapi::core::GDivC)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, double scale, int dtype, cv::UMat& out)
+ {
+ cv::divide(a, b, out, scale, dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUDivRC, cv::gapi::core::GDivRC)
+{
+ static void run(const cv::Scalar& a, const cv::UMat& b, double scale, int dtype, cv::UMat& out)
+ {
+ cv::divide(a, b, out, scale, dtype);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUMask, cv::gapi::core::GMask)
+{
+ static void run(const cv::UMat& in, const cv::UMat& mask, cv::UMat& out)
+ {
+ out = cv::UMat::zeros(in.size(), in.type());
+ in.copyTo(out, mask);
+ }
+};
+
+
+GAPI_GPU_KERNEL(GGPUMean, cv::gapi::core::GMean)
+{
+ static void run(const cv::UMat& in, cv::Scalar& out)
+ {
+ out = cv::mean(in);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUPolarToCart, cv::gapi::core::GPolarToCart)
+{
+ static void run(const cv::UMat& magn, const cv::UMat& angle, bool angleInDegrees, cv::UMat& outx, cv::UMat& outy)
+ {
+ cv::polarToCart(magn, angle, outx, outy, angleInDegrees);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCartToPolar, cv::gapi::core::GCartToPolar)
+{
+ static void run(const cv::UMat& x, const cv::UMat& y, bool angleInDegrees, cv::UMat& outmagn, cv::UMat& outangle)
+ {
+ cv::cartToPolar(x, y, outmagn, outangle, angleInDegrees);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpGT, cv::gapi::core::GCmpGT)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_GT);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpGE, cv::gapi::core::GCmpGE)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_GE);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpLE, cv::gapi::core::GCmpLE)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_LE);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpLT, cv::gapi::core::GCmpLT)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_LT);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpEQ, cv::gapi::core::GCmpEQ)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_EQ);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpNE, cv::gapi::core::GCmpNE)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_NE);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpGTScalar, cv::gapi::core::GCmpGTScalar)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_GT);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpGEScalar, cv::gapi::core::GCmpGEScalar)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_GE);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpLEScalar, cv::gapi::core::GCmpLEScalar)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_LE);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpLTScalar, cv::gapi::core::GCmpLTScalar)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_LT);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpEQScalar, cv::gapi::core::GCmpEQScalar)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_EQ);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCmpNEScalar, cv::gapi::core::GCmpNEScalar)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
+ {
+ cv::compare(a, b, out, cv::CMP_NE);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUAnd, cv::gapi::core::GAnd)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
+ {
+ cv::bitwise_and(a, b, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUAndS, cv::gapi::core::GAndS)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
+ {
+ cv::bitwise_and(a, b, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUOr, cv::gapi::core::GOr)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
+ {
+ cv::bitwise_or(a, b, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUOrS, cv::gapi::core::GOrS)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
+ {
+ cv::bitwise_or(a, b, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUXor, cv::gapi::core::GXor)
+{
+ static void run(const cv::UMat& a, const cv::UMat& b, cv::UMat& out)
+ {
+ cv::bitwise_xor(a, b, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUXorS, cv::gapi::core::GXorS)
+{
+ static void run(const cv::UMat& a, const cv::Scalar& b, cv::UMat& out)
+ {
+ cv::bitwise_xor(a, b, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUNot, cv::gapi::core::GNot)
+{
+ static void run(const cv::UMat& a, cv::UMat& out)
+ {
+ cv::bitwise_not(a, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUSelect, cv::gapi::core::GSelect)
+{
+ static void run(const cv::UMat& src1, const cv::UMat& src2, const cv::UMat& mask, cv::UMat& out)
+ {
+ src2.copyTo(out);
+ src1.copyTo(out, mask);
+ }
+};
+
+////TODO: doesn't compiled with UMat
+//GAPI_GPU_KERNEL(GGPUMin, cv::gapi::core::GMin)
+//{
+// static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
+// {
+// out = cv::min(in1, in2);
+// }
+//};
+//
+////TODO: doesn't compiled with UMat
+//GAPI_GPU_KERNEL(GGPUMax, cv::gapi::core::GMax)
+//{
+// static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
+// {
+// out = cv::max(in1, in2);
+// }
+//};
+
+
+GAPI_GPU_KERNEL(GGPUAbsDiff, cv::gapi::core::GAbsDiff)
+{
+ static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
+ {
+ cv::absdiff(in1, in2, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUAbsDiffC, cv::gapi::core::GAbsDiffC)
+{
+ static void run(const cv::UMat& in1, const cv::Scalar& in2, cv::UMat& out)
+ {
+ cv::absdiff(in1, in2, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUSum, cv::gapi::core::GSum)
+{
+ static void run(const cv::UMat& in, cv::Scalar& out)
+ {
+ out = cv::sum(in);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUAddW, cv::gapi::core::GAddW)
+{
+ static void run(const cv::UMat& in1, double alpha, const cv::UMat& in2, double beta, double gamma, int dtype, cv::UMat& out)
+ {
+ cv::addWeighted(in1, alpha, in2, beta, gamma, out, dtype);
+ }
+};
+
+
+GAPI_GPU_KERNEL(GGPUNormL1, cv::gapi::core::GNormL1)
+{
+ static void run(const cv::UMat& in, cv::Scalar& out)
+ {
+ out = cv::norm(in, cv::NORM_L1);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUNormL2, cv::gapi::core::GNormL2)
+{
+ static void run(const cv::UMat& in, cv::Scalar& out)
+ {
+ out = cv::norm(in, cv::NORM_L2);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUNormInf, cv::gapi::core::GNormInf)
+{
+ static void run(const cv::UMat& in, cv::Scalar& out)
+ {
+ out = cv::norm(in, cv::NORM_INF);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUIntegral, cv::gapi::core::GIntegral)
+{
+ static void run(const cv::UMat& in, int sdepth, int sqdepth, cv::UMat& out, cv::UMat& outSq)
+ {
+ cv::integral(in, out, outSq, sdepth, sqdepth);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUThreshold, cv::gapi::core::GThreshold)
+{
+ static void run(const cv::UMat& in, const cv::Scalar& a, const cv::Scalar& b, int type, cv::UMat& out)
+ {
+ cv::threshold(in, out, a.val[0], b.val[0], type);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUThresholdOT, cv::gapi::core::GThresholdOT)
+{
+ static void run(const cv::UMat& in, const cv::Scalar& b, int type, cv::UMat& out, cv::Scalar& outScalar)
+ {
+ outScalar = cv::threshold(in, out, b.val[0], b.val[0], type);
+ }
+};
+
+
+GAPI_GPU_KERNEL(GGPUInRange, cv::gapi::core::GInRange)
+{
+ static void run(const cv::UMat& in, const cv::Scalar& low, const cv::Scalar& up, cv::UMat& out)
+ {
+ cv::inRange(in, low, up, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUSplit3, cv::gapi::core::GSplit3)
+{
+ static void run(const cv::UMat& in, cv::UMat &m1, cv::UMat &m2, cv::UMat &m3)
+ {
+ std::vector<cv::UMat> outMats = {m1, m2, m3};
+ cv::split(in, outMats);
+
+ // Write back FIXME: Write a helper or avoid this nonsence completely!
+ m1 = outMats[0];
+ m2 = outMats[1];
+ m3 = outMats[2];
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUSplit4, cv::gapi::core::GSplit4)
+{
+ static void run(const cv::UMat& in, cv::UMat &m1, cv::UMat &m2, cv::UMat &m3, cv::UMat &m4)
+ {
+ std::vector<cv::UMat> outMats = {m1, m2, m3, m4};
+ cv::split(in, outMats);
+
+ // Write back FIXME: Write a helper or avoid this nonsence completely!
+ m1 = outMats[0];
+ m2 = outMats[1];
+ m3 = outMats[2];
+ m4 = outMats[3];
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUMerge3, cv::gapi::core::GMerge3)
+{
+ static void run(const cv::UMat& in1, const cv::UMat& in2, const cv::UMat& in3, cv::UMat &out)
+ {
+ std::vector<cv::UMat> inMats = {in1, in2, in3};
+ cv::merge(inMats, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUMerge4, cv::gapi::core::GMerge4)
+{
+ static void run(const cv::UMat& in1, const cv::UMat& in2, const cv::UMat& in3, const cv::UMat& in4, cv::UMat &out)
+ {
+ std::vector<cv::UMat> inMats = {in1, in2, in3, in4};
+ cv::merge(inMats, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUResize, cv::gapi::core::GResize)
+{
+ static void run(const cv::UMat& in, cv::Size sz, double fx, double fy, int interp, cv::UMat &out)
+ {
+ cv::resize(in, out, sz, fx, fy, interp);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPURemap, cv::gapi::core::GRemap)
+{
+ static void run(const cv::UMat& in, const cv::Mat& x, const cv::Mat& y, int a, int b, cv::Scalar s, cv::UMat& out)
+ {
+ cv::remap(in, out, x, y, a, b, s);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUFlip, cv::gapi::core::GFlip)
+{
+ static void run(const cv::UMat& in, int code, cv::UMat& out)
+ {
+ cv::flip(in, out, code);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCrop, cv::gapi::core::GCrop)
+{
+ static void run(const cv::UMat& in, cv::Rect rect, cv::UMat& out)
+ {
+ cv::UMat(in, rect).copyTo(out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUConcatHor, cv::gapi::core::GConcatHor)
+{
+ static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
+ {
+ cv::hconcat(in1, in2, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUConcatVert, cv::gapi::core::GConcatVert)
+{
+ static void run(const cv::UMat& in1, const cv::UMat& in2, cv::UMat& out)
+ {
+ cv::vconcat(in1, in2, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPULUT, cv::gapi::core::GLUT)
+{
+ static void run(const cv::UMat& in, const cv::Mat& lut, cv::UMat& out)
+ {
+ cv::LUT(in, lut, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUConvertTo, cv::gapi::core::GConvertTo)
+{
+ static void run(const cv::UMat& in, int rtype, double alpha, double beta, cv::UMat& out)
+ {
+ in.convertTo(out, rtype, alpha, beta);
+ }
+};
+
+cv::gapi::GKernelPackage cv::gapi::core::gpu::kernels()
+{
+ static auto pkg = cv::gapi::kernels
+ < GGPUAdd
+ , GGPUAddC
+ , GGPUSub
+ , GGPUSubC
+ , GGPUSubRC
+ , GGPUMul
+ , GGPUMulC
+ , GGPUMulCOld
+ , GGPUDiv
+ , GGPUDivC
+ , GGPUDivRC
+ , GGPUMean
+ , GGPUMask
+ , GGPUPolarToCart
+ , GGPUCartToPolar
+ , GGPUCmpGT
+ , GGPUCmpGE
+ , GGPUCmpLE
+ , GGPUCmpLT
+ , GGPUCmpEQ
+ , GGPUCmpNE
+ , GGPUCmpGTScalar
+ , GGPUCmpGEScalar
+ , GGPUCmpLEScalar
+ , GGPUCmpLTScalar
+ , GGPUCmpEQScalar
+ , GGPUCmpNEScalar
+ , GGPUAnd
+ , GGPUAndS
+ , GGPUOr
+ , GGPUOrS
+ , GGPUXor
+ , GGPUXorS
+ , GGPUNot
+ , GGPUSelect
+ //, GGPUMin
+ //, GGPUMax
+ , GGPUAbsDiff
+ , GGPUAbsDiffC
+ , GGPUSum
+ , GGPUAddW
+ , GGPUNormL1
+ , GGPUNormL2
+ , GGPUNormInf
+ , GGPUIntegral
+ , GGPUThreshold
+ , GGPUThresholdOT
+ , GGPUInRange
+ , GGPUSplit3
+ , GGPUSplit4
+ , GGPUResize
+ , GGPUMerge3
+ , GGPUMerge4
+ , GGPURemap
+ , GGPUFlip
+ , GGPUCrop
+ , GGPUConcatHor
+ , GGPUConcatVert
+ , GGPULUT
+ , GGPUConvertTo
+ >();
+ return pkg;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpucore.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpucore.hpp
new file mode 100644
index 000000000..47cbfa6bd
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpucore.hpp
@@ -0,0 +1,24 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GGPUCORE_HPP
+#define OPENCV_GAPI_GGPUCORE_HPP
+
+#include <map>
+#include <string>
+
+#include "opencv2/gapi/gpu/ggpukernel.hpp"
+
+namespace cv { namespace gimpl {
+
+// NB: This is what a "Kernel Package" from the original Wiki doc should be.
+void loadGPUCore(std::map<std::string, cv::GGPUKernel> &kmap);
+
+}
+}
+
+#endif // OPENCV_GAPI_GGPUCORE_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpuimgproc.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpuimgproc.cpp
new file mode 100644
index 000000000..9b7aca1a2
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpuimgproc.cpp
@@ -0,0 +1,277 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include "opencv2/gapi/imgproc.hpp"
+#include "opencv2/gapi/gpu/imgproc.hpp"
+#include "backends/gpu/ggpuimgproc.hpp"
+
+
+GAPI_GPU_KERNEL(GGPUSepFilter, cv::gapi::imgproc::GSepFilter)
+{
+ static void run(const cv::UMat& in, int ddepth, const cv::Mat& kernX, const cv::Mat& kernY, const cv::Point& anchor, const cv::Scalar& delta,
+ int border, const cv::Scalar& bordVal, cv::UMat &out)
+ {
+ if( border == cv::BORDER_CONSTANT )
+ {
+ cv::UMat temp_in;
+ int width_add = (kernY.cols - 1) / 2;
+ int height_add = (kernX.rows - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, border, bordVal);
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::sepFilter2D(temp_in(rect), out, ddepth, kernX, kernY, anchor, delta.val[0], border);
+ }
+ else
+ cv::sepFilter2D(in, out, ddepth, kernX, kernY, anchor, delta.val[0], border);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUBoxFilter, cv::gapi::imgproc::GBoxFilter)
+{
+ static void run(const cv::UMat& in, int ddepth, const cv::Size& ksize, const cv::Point& anchor, bool normalize, int borderType, const cv::Scalar& bordVal, cv::UMat &out)
+ {
+ if( borderType == cv::BORDER_CONSTANT )
+ {
+ cv::UMat temp_in;
+ int width_add = (ksize.width - 1) / 2;
+ int height_add = (ksize.height - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, borderType, bordVal);
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::boxFilter(temp_in(rect), out, ddepth, ksize, anchor, normalize, borderType);
+ }
+ else
+ cv::boxFilter(in, out, ddepth, ksize, anchor, normalize, borderType);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUBlur, cv::gapi::imgproc::GBlur)
+{
+ static void run(const cv::UMat& in, const cv::Size& ksize, const cv::Point& anchor, int borderType, const cv::Scalar& bordVal, cv::UMat &out)
+ {
+ if( borderType == cv::BORDER_CONSTANT )
+ {
+ cv::UMat temp_in;
+ int width_add = (ksize.width - 1) / 2;
+ int height_add = (ksize.height - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, borderType, bordVal);
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::blur(temp_in(rect), out, ksize, anchor, borderType);
+ }
+ else
+ cv::blur(in, out, ksize, anchor, borderType);
+ }
+};
+
+
+GAPI_GPU_KERNEL(GGPUFilter2D, cv::gapi::imgproc::GFilter2D)
+{
+ static void run(const cv::UMat& in, int ddepth, const cv::Mat& k, const cv::Point& anchor, const cv::Scalar& delta, int border,
+ const cv::Scalar& bordVal, cv::UMat &out)
+ {
+ if( border == cv::BORDER_CONSTANT )
+ {
+ cv::UMat temp_in;
+ int width_add = (k.cols - 1) / 2;
+ int height_add = (k.rows - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, border, bordVal );
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::filter2D(temp_in(rect), out, ddepth, k, anchor, delta.val[0], border);
+ }
+ else
+ cv::filter2D(in, out, ddepth, k, anchor, delta.val[0], border);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUGaussBlur, cv::gapi::imgproc::GGaussBlur)
+{
+ static void run(const cv::UMat& in, const cv::Size& ksize, double sigmaX, double sigmaY, int borderType, const cv::Scalar& bordVal, cv::UMat &out)
+ {
+ if( borderType == cv::BORDER_CONSTANT )
+ {
+ cv::UMat temp_in;
+ int width_add = (ksize.width - 1) / 2;
+ int height_add = (ksize.height - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, height_add, height_add, width_add, width_add, borderType, bordVal );
+ cv::Rect rect = cv::Rect(height_add, width_add, in.cols, in.rows);
+ cv::GaussianBlur(temp_in(rect), out, ksize, sigmaX, sigmaY, borderType);
+ }
+ else
+ cv::GaussianBlur(in, out, ksize, sigmaX, sigmaY, borderType);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUMedianBlur, cv::gapi::imgproc::GMedianBlur)
+{
+ static void run(const cv::UMat& in, int ksize, cv::UMat &out)
+ {
+ cv::medianBlur(in, out, ksize);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUErode, cv::gapi::imgproc::GErode)
+{
+ static void run(const cv::UMat& in, const cv::Mat& kernel, const cv::Point& anchor, int iterations, int borderType, const cv::Scalar& borderValue, cv::UMat &out)
+ {
+ cv::erode(in, out, kernel, anchor, iterations, borderType, borderValue);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUDilate, cv::gapi::imgproc::GDilate)
+{
+ static void run(const cv::UMat& in, const cv::Mat& kernel, const cv::Point& anchor, int iterations, int borderType, const cv::Scalar& borderValue, cv::UMat &out)
+ {
+ cv::dilate(in, out, kernel, anchor, iterations, borderType, borderValue);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUSobel, cv::gapi::imgproc::GSobel)
+{
+ static void run(const cv::UMat& in, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType,
+ const cv::Scalar& bordVal, cv::UMat &out)
+ {
+ if( borderType == cv::BORDER_CONSTANT )
+ {
+ cv::UMat temp_in;
+ int add = (ksize - 1) / 2;
+ cv::copyMakeBorder(in, temp_in, add, add, add, add, borderType, bordVal );
+ cv::Rect rect = cv::Rect(add, add, in.cols, in.rows);
+ cv::Sobel(temp_in(rect), out, ddepth, dx, dy, ksize, scale, delta, borderType);
+ }
+ else
+ cv::Sobel(in, out, ddepth, dx, dy, ksize, scale, delta, borderType);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUEqualizeHist, cv::gapi::imgproc::GEqHist)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::equalizeHist(in, out);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUCanny, cv::gapi::imgproc::GCanny)
+{
+ static void run(const cv::UMat& in, double thr1, double thr2, int apSize, bool l2gradient, cv::UMat &out)
+ {
+ cv::Canny(in, out, thr1, thr2, apSize, l2gradient);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPURGB2YUV, cv::gapi::imgproc::GRGB2YUV)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_RGB2YUV);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUYUV2RGB, cv::gapi::imgproc::GYUV2RGB)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_YUV2RGB);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPURGB2Lab, cv::gapi::imgproc::GRGB2Lab)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_RGB2Lab);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUBGR2LUV, cv::gapi::imgproc::GBGR2LUV)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_BGR2Luv);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUBGR2YUV, cv::gapi::imgproc::GBGR2YUV)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_BGR2YUV);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPULUV2BGR, cv::gapi::imgproc::GLUV2BGR)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_Luv2BGR);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUYUV2BGR, cv::gapi::imgproc::GYUV2BGR)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_YUV2BGR);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPURGB2Gray, cv::gapi::imgproc::GRGB2Gray)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_RGB2GRAY);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPUBGR2Gray, cv::gapi::imgproc::GBGR2Gray)
+{
+ static void run(const cv::UMat& in, cv::UMat &out)
+ {
+ cv::cvtColor(in, out, cv::COLOR_BGR2GRAY);
+ }
+};
+
+GAPI_GPU_KERNEL(GGPURGB2GrayCustom, cv::gapi::imgproc::GRGB2GrayCustom)
+{
+ //TODO: avoid copy
+ static void run(const cv::UMat& in, float rY, float bY, float gY, cv::UMat &out)
+ {
+ cv::Mat planes[3];
+ cv::split(in.getMat(cv::ACCESS_READ), planes);
+ cv::Mat tmp_out = (planes[0]*rY + planes[1]*bY + planes[2]*gY);
+ tmp_out.copyTo(out);
+ }
+};
+
+
+cv::gapi::GKernelPackage cv::gapi::imgproc::gpu::kernels()
+{
+ static auto pkg = cv::gapi::kernels
+ < GGPUFilter2D
+ , GGPUSepFilter
+ , GGPUBoxFilter
+ , GGPUBlur
+ , GGPUGaussBlur
+ , GGPUMedianBlur
+ , GGPUErode
+ , GGPUDilate
+ , GGPUSobel
+ , GGPUCanny
+ , GGPUEqualizeHist
+ , GGPURGB2YUV
+ , GGPUYUV2RGB
+ , GGPURGB2Lab
+ , GGPUBGR2LUV
+ , GGPUBGR2YUV
+ , GGPUYUV2BGR
+ , GGPULUV2BGR
+ , GGPUBGR2Gray
+ , GGPURGB2Gray
+ , GGPURGB2GrayCustom
+ >();
+ return pkg;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpuimgproc.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpuimgproc.hpp
new file mode 100644
index 000000000..cd2e324e6
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpuimgproc.hpp
@@ -0,0 +1,23 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GGPUIMGPROC_HPP
+#define OPENCV_GAPI_GGPUIMGPROC_HPP
+
+#include <map>
+#include <string>
+
+#include "opencv2/gapi/gpu/ggpukernel.hpp"
+
+namespace cv { namespace gimpl {
+
+// NB: This is what a "Kernel Package" from the origianl Wiki doc should be.
+void loadGPUImgProc(std::map<std::string, cv::GGPUKernel> &kmap);
+
+}}
+
+#endif // OPENCV_GAPI_GGPUIMGPROC_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpukernel.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpukernel.cpp
new file mode 100644
index 000000000..87e2aa97e
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/backends/gpu/ggpukernel.cpp
@@ -0,0 +1,50 @@
+// 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) 2018 Intel Corporation
+
+
+#include <cassert>
+
+#include "opencv2/gapi/gpu/ggpukernel.hpp"
+
+const cv::UMat& cv::GGPUContext::inMat(int input)
+{
+ return (inArg<cv::UMat>(input));
+}
+
+cv::UMat& cv::GGPUContext::outMatR(int output)
+{
+ return (*(util::get<cv::UMat*>(m_results.at(output))));
+}
+
+const cv::gapi::own::Scalar& cv::GGPUContext::inVal(int input)
+{
+ return inArg<cv::gapi::own::Scalar>(input);
+}
+
+cv::gapi::own::Scalar& cv::GGPUContext::outValR(int output)
+{
+ return *util::get<cv::gapi::own::Scalar*>(m_results.at(output));
+}
+
+cv::detail::VectorRef& cv::GGPUContext::outVecRef(int output)
+{
+ return util::get<cv::detail::VectorRef>(m_results.at(output));
+}
+
+cv::GGPUKernel::GGPUKernel()
+{
+}
+
+cv::GGPUKernel::GGPUKernel(const GGPUKernel::F &f)
+ : m_f(f)
+{
+}
+
+void cv::GGPUKernel::apply(GGPUContext &ctx)
+{
+ CV_Assert(m_f);
+ m_f(ctx);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/README.md b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/README.md
new file mode 100644
index 000000000..995aa3977
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/README.md
@@ -0,0 +1 @@
+This directory contains G-API graph compiler logic. \ No newline at end of file
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled.cpp
new file mode 100644
index 000000000..876575d94
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled.cpp
@@ -0,0 +1,157 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <ade/graph.hpp>
+
+#include "opencv2/gapi/gproto.hpp" // descr_of
+#include "opencv2/gapi/gcompiled.hpp"
+
+#include "compiler/gcompiled_priv.hpp"
+#include "backends/common/gbackend.hpp"
+
+// GCompiled private implementation ////////////////////////////////////////////
+void cv::GCompiled::Priv::setup(const GMetaArgs &_metaArgs,
+ const GMetaArgs &_outMetas,
+ std::unique_ptr<cv::gimpl::GExecutor> &&_pE)
+{
+ m_metas = _metaArgs;
+ m_outMetas = _outMetas;
+ m_exec = std::move(_pE);
+}
+
+bool cv::GCompiled::Priv::isEmpty() const
+{
+ return !m_exec;
+}
+
+void cv::GCompiled::Priv::run(cv::gimpl::GRuntimeArgs &&args)
+{
+ // Strip away types since ADE knows nothing about that
+ // args will be taken by specific GBackendExecutables
+ checkArgs(args);
+ m_exec->run(std::move(args));
+}
+
+const cv::GMetaArgs& cv::GCompiled::Priv::metas() const
+{
+ return m_metas;
+}
+
+const cv::GMetaArgs& cv::GCompiled::Priv::outMetas() const
+{
+ return m_outMetas;
+}
+
+void cv::GCompiled::Priv::checkArgs(const cv::gimpl::GRuntimeArgs &args) const
+{
+ const auto runtime_metas = descr_of(args.inObjs);
+ if (runtime_metas != m_metas)
+ {
+ util::throw_error(std::logic_error("This object was compiled "
+ "for different metadata!"));
+ // FIXME: Add details on what is actually wrong
+ }
+}
+
+bool cv::GCompiled::Priv::canReshape() const
+{
+ GAPI_Assert(m_exec);
+ return m_exec->canReshape();
+}
+
+void cv::GCompiled::Priv::reshape(const GMetaArgs& inMetas, const GCompileArgs& args)
+{
+ GAPI_Assert(m_exec);
+ m_exec->reshape(inMetas, args);
+ m_metas = inMetas;
+}
+
+const cv::gimpl::GModel::Graph& cv::GCompiled::Priv::model() const
+{
+ GAPI_Assert(nullptr != m_exec);
+ return m_exec->model();
+}
+
+// GCompiled public implementation /////////////////////////////////////////////
+cv::GCompiled::GCompiled()
+ : m_priv(new Priv())
+{
+}
+
+cv::GCompiled::operator bool() const
+{
+ return !m_priv->isEmpty();
+}
+
+void cv::GCompiled::operator() (GRunArgs &&ins, GRunArgsP &&outs)
+{
+ // FIXME: Check that <outs> matches the protocol
+ m_priv->run(cv::gimpl::GRuntimeArgs{std::move(ins),std::move(outs)});
+}
+
+#if !defined(GAPI_STANDALONE)
+void cv::GCompiled::operator ()(cv::Mat in, cv::Mat &out)
+{
+ (*this)(cv::gin(in), cv::gout(out));
+}
+
+void cv::GCompiled::operator() (cv::Mat in, cv::Scalar &out)
+{
+ (*this)(cv::gin(in), cv::gout(out));
+}
+
+void cv::GCompiled::operator() (cv::Mat in1, cv::Mat in2, cv::Mat &out)
+{
+ (*this)(cv::gin(in1, in2), cv::gout(out));
+}
+
+void cv::GCompiled::operator() (cv::Mat in1, cv::Mat in2, cv::Scalar &out)
+{
+ (*this)(cv::gin(in1, in2), cv::gout(out));
+}
+
+void cv::GCompiled::operator ()(const std::vector<cv::Mat> &ins,
+ const std::vector<cv::Mat> &outs)
+{
+ GRunArgs call_ins;
+ GRunArgsP call_outs;
+
+ // Make a temporary copy of vector outs - cv::Mats are copies anyway
+ auto tmp = outs;
+ for (const cv::Mat &m : ins) { call_ins.emplace_back(m); }
+ for ( cv::Mat &m : tmp) { call_outs.emplace_back(&m); }
+
+ (*this)(std::move(call_ins), std::move(call_outs));
+}
+#endif // !defined(GAPI_STANDALONE)
+
+const cv::GMetaArgs& cv::GCompiled::metas() const
+{
+ return m_priv->metas();
+}
+
+const cv::GMetaArgs& cv::GCompiled::outMetas() const
+{
+ return m_priv->outMetas();
+}
+
+cv::GCompiled::Priv& cv::GCompiled::priv()
+{
+ return *m_priv;
+}
+
+bool cv::GCompiled::canReshape() const
+{
+ return m_priv->canReshape();
+}
+
+void cv::GCompiled::reshape(const GMetaArgs& inMetas, const GCompileArgs& args)
+{
+ m_priv->reshape(inMetas, args);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled_priv.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled_priv.hpp
new file mode 100644
index 000000000..e616b2bb7
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiled_priv.hpp
@@ -0,0 +1,61 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCOMPILED_PRIV_HPP
+#define OPENCV_GAPI_GCOMPILED_PRIV_HPP
+
+#include <memory> // unique_ptr
+
+#include "opencv2/gapi/util/optional.hpp"
+#include "compiler/gmodel.hpp"
+#include "executor/gexecutor.hpp"
+
+// NB: BTW, GCompiled is the only "public API" class which
+// private part (implementaion) is hosted in the "compiler/" module.
+//
+// This file is here just to keep ADE hidden from the top-level APIs.
+//
+// As the thing becomes more complex, appropriate API and implementation
+// part will be placed to api/ and compiler/ modules respectively.
+
+namespace cv {
+
+namespace gimpl
+{
+ struct GRuntimeArgs;
+};
+
+// FIXME: GAPI_EXPORTS is here only due to tests and Windows linker issues
+class GAPI_EXPORTS GCompiled::Priv
+{
+ // NB: For now, a GCompiled keeps the original ade::Graph alive.
+ // If we want to go autonomous, we might to do something with this.
+ GMetaArgs m_metas; // passed by user
+ GMetaArgs m_outMetas; // inferred by compiler
+ std::unique_ptr<cv::gimpl::GExecutor> m_exec;
+
+ void checkArgs(const cv::gimpl::GRuntimeArgs &args) const;
+
+public:
+ void setup(const GMetaArgs &metaArgs,
+ const GMetaArgs &outMetas,
+ std::unique_ptr<cv::gimpl::GExecutor> &&pE);
+ bool isEmpty() const;
+
+ bool canReshape() const;
+ void reshape(const GMetaArgs& inMetas, const GCompileArgs &args);
+
+ void run(cv::gimpl::GRuntimeArgs &&args);
+ const GMetaArgs& metas() const;
+ const GMetaArgs& outMetas() const;
+
+ const cv::gimpl::GModel::Graph& model() const;
+};
+
+}
+
+#endif // OPENCV_GAPI_GCOMPILED_PRIV_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.cpp
new file mode 100644
index 000000000..32ce8e38f
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.cpp
@@ -0,0 +1,281 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <vector>
+#include <stack>
+#include <unordered_map>
+
+#include <ade/util/algorithm.hpp> // any_of
+#include <ade/util/zip_range.hpp> // zip_range, indexed
+
+#include <ade/graph.hpp>
+#include <ade/passes/check_cycles.hpp>
+
+#include "api/gcomputation_priv.hpp"
+#include "api/gnode_priv.hpp" // FIXME: why it is here?
+#include "api/gproto_priv.hpp" // FIXME: why it is here?
+#include "api/gcall_priv.hpp" // FIXME: why it is here?
+#include "api/gapi_priv.hpp" // FIXME: why it is here?
+#include "api/gbackend_priv.hpp" // Backend basic API (newInstance, etc)
+
+#include "compiler/gmodel.hpp"
+#include "compiler/gmodelbuilder.hpp"
+#include "compiler/gcompiler.hpp"
+#include "compiler/gcompiled_priv.hpp"
+#include "compiler/passes/passes.hpp"
+
+#include "executor/gexecutor.hpp"
+#include "backends/common/gbackend.hpp"
+
+// <FIXME:>
+#if !defined(GAPI_STANDALONE)
+#include "opencv2/gapi/cpu/core.hpp" // Also directly refer to Core
+#include "opencv2/gapi/cpu/imgproc.hpp" // ...and Imgproc kernel implementations
+#endif // !defined(GAPI_STANDALONE)
+// </FIXME:>
+
+#include "opencv2/gapi/gcompoundkernel.hpp" // compound::backend()
+
+#include "logger.hpp"
+
+namespace
+{
+ cv::gapi::GKernelPackage getKernelPackage(cv::GCompileArgs &args)
+ {
+ static auto ocv_pkg =
+#if !defined(GAPI_STANDALONE)
+ combine(cv::gapi::core::cpu::kernels(),
+ cv::gapi::imgproc::cpu::kernels(),
+ cv::unite_policy::KEEP);
+#else
+ cv::gapi::GKernelPackage();
+#endif // !defined(GAPI_STANDALONE)
+ auto user_pkg = cv::gimpl::getCompileArg<cv::gapi::GKernelPackage>(args);
+ return combine(ocv_pkg, user_pkg.value_or(cv::gapi::GKernelPackage{}), cv::unite_policy::REPLACE);
+ }
+
+ cv::util::optional<std::string> getGraphDumpDirectory(cv::GCompileArgs& args)
+ {
+ auto dump_info = cv::gimpl::getCompileArg<cv::graph_dump_path>(args);
+ if (!dump_info.has_value())
+ {
+ const char* path = std::getenv("GRAPH_DUMP_PATH");
+ return path
+ ? cv::util::make_optional(std::string(path))
+ : cv::util::optional<std::string>();
+ }
+ else
+ {
+ return cv::util::make_optional(dump_info.value().m_dump_path);
+ }
+ }
+} // anonymous namespace
+
+
+// GCompiler implementation ////////////////////////////////////////////////////
+
+cv::gimpl::GCompiler::GCompiler(const cv::GComputation &c,
+ GMetaArgs &&metas,
+ GCompileArgs &&args)
+ : m_c(c), m_metas(std::move(metas)), m_args(std::move(args))
+{
+ using namespace std::placeholders;
+ m_all_kernels = getKernelPackage(m_args);
+ auto lookup_order = getCompileArg<gapi::GLookupOrder>(m_args).value_or(gapi::GLookupOrder());
+ auto dump_path = getGraphDumpDirectory(m_args);
+
+ m_e.addPassStage("init");
+ m_e.addPass("init", "check_cycles", ade::passes::CheckCycles());
+ m_e.addPass("init", "expand_kernels", std::bind(passes::expandKernels, _1,
+ m_all_kernels)); // NB: package is copied
+ m_e.addPass("init", "topo_sort", ade::passes::TopologicalSort());
+ m_e.addPass("init", "init_islands", passes::initIslands);
+ m_e.addPass("init", "check_islands", passes::checkIslands);
+ // TODO:
+ // - Check basic graph validity (i.e., all inputs are connected)
+ // - Complex dependencies (i.e. parent-child) unrolling
+ // - etc, etc, etc
+
+ // Remove GCompoundBackend to avoid calling setupBackend() with it in the list
+ m_all_kernels.remove(cv::gapi::compound::backend());
+ m_e.addPass("init", "resolve_kernels", std::bind(passes::resolveKernels, _1,
+ std::ref(m_all_kernels), // NB: and not copied here
+ lookup_order));
+
+ m_e.addPass("init", "check_islands_content", passes::checkIslandsContent);
+ m_e.addPassStage("meta");
+ m_e.addPass("meta", "initialize", std::bind(passes::initMeta, _1, std::ref(m_metas)));
+ m_e.addPass("meta", "propagate", std::bind(passes::inferMeta, _1, false));
+ m_e.addPass("meta", "finalize", passes::storeResultingMeta);
+ // moved to another stage, FIXME: two dumps?
+ // m_e.addPass("meta", "dump_dot", passes::dumpDotStdout);
+
+ // Special stage for backend-specific transformations
+ // FIXME: document passes hierarchy and order for backend developers
+ m_e.addPassStage("transform");
+
+ m_e.addPassStage("exec");
+ m_e.addPass("exec", "fuse_islands", passes::fuseIslands);
+ m_e.addPass("exec", "sync_islands", passes::syncIslandTags);
+
+ if (dump_path.has_value())
+ {
+ m_e.addPass("exec", "dump_dot", std::bind(passes::dumpGraph, _1,
+ dump_path.value()));
+ }
+
+ // Process backends at the last moment (after all G-API passes are added).
+ ade::ExecutionEngineSetupContext ectx(m_e);
+ auto backends = m_all_kernels.backends();
+ for (auto &b : backends)
+ {
+ b.priv().addBackendPasses(ectx);
+ }
+}
+
+void cv::gimpl::GCompiler::validateInputMeta()
+{
+ if (m_metas.size() != m_c.priv().m_ins.size())
+ {
+ util::throw_error(std::logic_error
+ ("COMPILE: GComputation interface / metadata mismatch! "
+ "(expected " + std::to_string(m_c.priv().m_ins.size()) + ", "
+ "got " + std::to_string(m_metas.size()) + " meta arguments)"));
+ }
+
+ const auto meta_matches = [](const GMetaArg &meta, const GProtoArg &proto) {
+ switch (proto.index())
+ {
+ // FIXME: Auto-generate methods like this from traits:
+ case GProtoArg::index_of<cv::GMat>():
+ return util::holds_alternative<cv::GMatDesc>(meta);
+
+ case GProtoArg::index_of<cv::GScalar>():
+ return util::holds_alternative<cv::GScalarDesc>(meta);
+
+ case GProtoArg::index_of<cv::detail::GArrayU>():
+ return util::holds_alternative<cv::GArrayDesc>(meta);
+
+ default:
+ GAPI_Assert(false);
+ }
+ return false; // should never happen
+ };
+
+ for (const auto &meta_arg_idx : ade::util::indexed(ade::util::zip(m_metas, m_c.priv().m_ins)))
+ {
+ const auto &meta = std::get<0>(ade::util::value(meta_arg_idx));
+ const auto &proto = std::get<1>(ade::util::value(meta_arg_idx));
+
+ if (!meta_matches(meta, proto))
+ {
+ const auto index = ade::util::index(meta_arg_idx);
+ util::throw_error(std::logic_error
+ ("GComputation object type / metadata descriptor mismatch "
+ "(argument " + std::to_string(index) + ")"));
+ // FIXME: report what we've got and what we've expected
+ }
+ }
+ // All checks are ok
+}
+
+void cv::gimpl::GCompiler::validateOutProtoArgs()
+{
+ for (const auto &out_pos : ade::util::indexed(m_c.priv().m_outs))
+ {
+ const auto &node = proto::origin_of(ade::util::value(out_pos)).node;
+ if (node.shape() != cv::GNode::NodeShape::CALL)
+ {
+ auto pos = ade::util::index(out_pos);
+ util::throw_error(std::logic_error
+ ("Computation output " + std::to_string(pos) +
+ " is not a result of any operation"));
+ }
+ }
+}
+
+cv::gimpl::GCompiler::GPtr cv::gimpl::GCompiler::generateGraph()
+{
+ validateInputMeta();
+ validateOutProtoArgs();
+
+ // Generate ADE graph from expression-based computation
+ std::unique_ptr<ade::Graph> pG(new ade::Graph);
+ ade::Graph& g = *pG;
+
+ GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ cv::gimpl::GModelBuilder builder(g);
+ auto proto_slots = builder.put(m_c.priv().m_ins, m_c.priv().m_outs);
+ GAPI_LOG_INFO(NULL, "Generated graph: " << g.nodes().size() << " nodes" << std::endl);
+
+ // Store Computation's protocol in metadata
+ Protocol p;
+ std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
+ gm.metadata().set(p);
+
+ return pG;
+}
+
+void cv::gimpl::GCompiler::runPasses(ade::Graph &g)
+{
+ m_e.runPasses(g);
+ GAPI_LOG_INFO(NULL, "All compiler passes are successful");
+}
+
+void cv::gimpl::GCompiler::compileIslands(ade::Graph &g)
+{
+ GModel::Graph gm(g);
+ std::shared_ptr<ade::Graph> gptr(gm.metadata().get<IslandModel>().model);
+ GIslandModel::Graph gim(*gptr);
+
+ // Run topological sort on GIslandModel first
+ auto pass_ctx = ade::passes::PassContext{*gptr};
+ ade::passes::TopologicalSort{}(pass_ctx);
+
+ // Now compile islands
+ GIslandModel::compileIslands(gim, g, m_args);
+}
+
+cv::GCompiled cv::gimpl::GCompiler::produceCompiled(GPtr &&pg)
+{
+ // This is the final compilation step. Here:
+ // - An instance of GExecutor is created. Depening on the platform,
+ // build configuration, etc, a GExecutor may be:
+ // - a naive single-thread graph interpreter;
+ // - a std::thread-based thing
+ // - a TBB-based thing, etc.
+ // - All this stuff is wrapped into a GCompiled object and returned
+ // to user.
+
+ // Note: this happens in the last pass ("compile_islands"):
+ // - Each GIsland of GIslandModel instantiates its own,
+ // backend-specific executable object
+ // - Every backend gets a subgraph to execute, and builds
+ // an execution plan for it (backend-specific execution)
+ // ...before call to produceCompiled();
+
+ const auto &outMetas = GModel::ConstGraph(*pg).metadata()
+ .get<OutputMeta>().outMeta;
+ std::unique_ptr<GExecutor> pE(new GExecutor(std::move(pg)));
+ // FIXME: select which executor will be actually used,
+ // make GExecutor abstract.
+
+ GCompiled compiled;
+ compiled.priv().setup(m_metas, outMetas, std::move(pE));
+ return compiled;
+}
+
+cv::GCompiled cv::gimpl::GCompiler::compile()
+{
+ std::unique_ptr<ade::Graph> pG = generateGraph();
+ runPasses(*pG);
+ compileIslands(*pG);
+ return produceCompiled(std::move(pG));
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.hpp
new file mode 100644
index 000000000..b369c14d1
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gcompiler.hpp
@@ -0,0 +1,51 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GCOMPILER_HPP
+#define OPENCV_GAPI_GCOMPILER_HPP
+
+
+#include "opencv2/gapi/gcommon.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+#include "opencv2/gapi/gcomputation.hpp"
+
+#include <ade/execution_engine/execution_engine.hpp>
+
+namespace cv { namespace gimpl {
+
+// FIXME: exported for internal tests only!
+class GAPI_EXPORTS GCompiler
+{
+ const GComputation& m_c;
+ const GMetaArgs m_metas;
+ GCompileArgs m_args;
+ ade::ExecutionEngine m_e;
+
+ cv::gapi::GKernelPackage m_all_kernels;
+
+ void validateInputMeta();
+ void validateOutProtoArgs();
+
+public:
+ explicit GCompiler(const GComputation &c,
+ GMetaArgs &&metas,
+ GCompileArgs &&args);
+
+ // The method which does everything...
+ GCompiled compile();
+
+ // But is actually composed of this:
+ using GPtr = std::unique_ptr<ade::Graph>;
+ GPtr generateGraph(); // Unroll GComputation into a GModel
+ void runPasses(ade::Graph &g); // Apply all G-API passes on a GModel
+ void compileIslands(ade::Graph &g); // Instantiate GIslandExecutables in GIslandModel
+ GCompiled produceCompiled(GPtr &&pg); // Produce GCompiled from processed GModel
+};
+
+}}
+
+#endif // OPENCV_GAPI_GCOMPILER_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.cpp
new file mode 100644
index 000000000..8e20302a3
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.cpp
@@ -0,0 +1,289 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <sstream>
+#include <unordered_set>
+#include <unordered_map>
+
+#include <ade/util/checked_cast.hpp>
+
+#include "api/gbackend_priv.hpp" // GBackend::Priv().compile()
+#include "compiler/gmodel.hpp"
+#include "compiler/gislandmodel.hpp"
+#include "logger.hpp" // GAPI_LOG
+
+namespace cv { namespace gimpl {
+
+GIsland::GIsland(const gapi::GBackend &bknd,
+ ade::NodeHandle op,
+ util::optional<std::string> &&user_tag)
+ : m_backend(bknd)
+ , m_user_tag(std::move(user_tag))
+{
+ m_all.insert(op);
+ m_in_ops.insert(op);
+ m_out_ops.insert(op);
+}
+
+// _ because of gcc4.8 wanings on ARM
+GIsland::GIsland(const gapi::GBackend &_bknd,
+ node_set &&_all,
+ node_set &&_in_ops,
+ node_set &&_out_ops,
+ util::optional<std::string> &&_user_tag)
+ : m_backend(_bknd)
+ , m_all(std::move(_all))
+ , m_in_ops(std::move(_in_ops))
+ , m_out_ops(std::move(_out_ops))
+ , m_user_tag(std::move(_user_tag))
+{
+}
+
+const GIsland::node_set& GIsland::contents() const
+{
+ return m_all;
+}
+
+const GIsland::node_set& GIsland::in_ops() const
+{
+ return m_in_ops;
+}
+
+const GIsland::node_set& GIsland::out_ops() const
+{
+ return m_out_ops;
+}
+
+gapi::GBackend GIsland::backend() const
+{
+ return m_backend;
+}
+
+bool GIsland::is_user_specified() const
+{
+ return m_user_tag.has_value();
+}
+
+void GIsland::debug() const
+{
+ std::stringstream stream;
+ stream << name() << " {{\n input ops: ";
+ for (const auto& nh : m_in_ops) stream << nh << "; ";
+ stream << "\n output ops: ";
+ for (const auto& nh : m_out_ops) stream << nh << "; ";
+ stream << "\n contents: ";
+ for (const auto& nh : m_all) stream << nh << "; ";
+ stream << "\n}}" << std::endl;
+ GAPI_LOG_INFO(NULL, stream.str());
+}
+
+GIsland::node_set GIsland::consumers(const ade::Graph &g,
+ const ade::NodeHandle &slot_nh) const
+{
+ GIslandModel::ConstGraph gim(g);
+ auto data_nh = gim.metadata(slot_nh).get<DataSlot>().original_data_node;
+ GIsland::node_set result;
+ for (const auto& in_op : m_in_ops)
+ {
+ auto it = std::find(in_op->inNodes().begin(),
+ in_op->inNodes().end(),
+ data_nh);
+ if (it != in_op->inNodes().end())
+ result.insert(in_op);
+ }
+ return result;
+}
+
+ade::NodeHandle GIsland::producer(const ade::Graph &g,
+ const ade::NodeHandle &slot_nh) const
+{
+ GIslandModel::ConstGraph gim(g);
+ auto data_nh = gim.metadata(slot_nh).get<DataSlot>().original_data_node;
+ for (const auto& out_op : m_out_ops)
+ {
+ auto it = std::find(out_op->outNodes().begin(),
+ out_op->outNodes().end(),
+ data_nh);
+ if (it != out_op->outNodes().end())
+ return out_op;
+ }
+ // Consistency: A GIsland requested for producer() of slot_nh should
+ // always had the appropriate GModel node handle in its m_out_ops vector.
+ GAPI_Assert(false);
+ return ade::NodeHandle();
+}
+
+std::string GIsland::name() const
+{
+ if (is_user_specified())
+ return m_user_tag.value();
+
+ std::stringstream ss;
+ ss << "island_#" << std::hex << static_cast<const void*>(this);
+ return ss.str();
+}
+
+void GIslandModel::generateInitial(GIslandModel::Graph &g,
+ const ade::Graph &src_graph)
+{
+ const GModel::ConstGraph src_g(src_graph);
+
+ // Initially GIslandModel is a 1:1 projection from GModel:
+ // 1) Every GModel::OP becomes a separate GIslandModel::FusedIsland;
+ // 2) Every GModel::DATA becomes GIslandModel::DataSlot;
+ // 3) Single-operation FusedIslands are connected with DataSlots in the
+ // same way as OPs and DATA (edges with the same metadata)
+
+ using node_set = std::unordered_set
+ < ade::NodeHandle
+ , ade::HandleHasher<ade::Node>
+ >;
+ using node_map = std::unordered_map
+ < ade::NodeHandle
+ , ade::NodeHandle
+ , ade::HandleHasher<ade::Node>
+ >;
+
+ node_set all_operations;
+ node_map data_to_slot;
+
+ // First, list all operations and build create DataSlots in <g>
+ for (auto src_nh : src_g.nodes())
+ {
+ switch (src_g.metadata(src_nh).get<NodeType>().t)
+ {
+ case NodeType::OP: all_operations.insert(src_nh); break;
+ case NodeType::DATA: data_to_slot[src_nh] = mkSlotNode(g, src_nh); break;
+ default: GAPI_Assert(false); break;
+ }
+ } // for (src_g.nodes)
+
+ // Now put single-op islands and connect it with DataSlots
+ for (auto src_op_nh : all_operations)
+ {
+ auto nh = mkIslandNode(g, src_g.metadata(src_op_nh).get<Op>().backend, src_op_nh, src_graph);
+ for (auto in_edge : src_op_nh->inEdges())
+ {
+ auto src_data_nh = in_edge->srcNode();
+ auto isl_slot_nh = data_to_slot.at(src_data_nh);
+ g.link(isl_slot_nh, nh); // no other data stored yet
+ }
+ for (auto out_edge : src_op_nh->outEdges())
+ {
+ auto dst_data_nh = out_edge->dstNode();
+ auto isl_slot_nh = data_to_slot.at(dst_data_nh);
+ g.link(nh, isl_slot_nh);
+ }
+ } // for(all_operations)
+}
+
+ade::NodeHandle GIslandModel::mkSlotNode(Graph &g, const ade::NodeHandle &data_nh)
+{
+ auto nh = g.createNode();
+ g.metadata(nh).set(DataSlot{data_nh});
+ g.metadata(nh).set(NodeKind{NodeKind::SLOT});
+ return nh;
+}
+
+ade::NodeHandle GIslandModel::mkIslandNode(Graph &g, const gapi::GBackend& bknd, const ade::NodeHandle &op_nh, const ade::Graph &orig_g)
+{
+ const GModel::ConstGraph src_g(orig_g);
+ util::optional<std::string> user_tag;
+ if (src_g.metadata(op_nh).contains<Island>())
+ {
+ user_tag = util::make_optional(src_g.metadata(op_nh).get<Island>().island);
+ }
+
+ auto nh = g.createNode();
+ std::shared_ptr<GIsland> island(new GIsland(bknd, op_nh, std::move(user_tag)));
+ g.metadata(nh).set(FusedIsland{std::move(island)});
+ g.metadata(nh).set(NodeKind{NodeKind::ISLAND});
+ return nh;
+}
+
+ade::NodeHandle GIslandModel::mkIslandNode(Graph &g, std::shared_ptr<GIsland>&& isl)
+{
+ ade::NodeHandle nh = g.createNode();
+ g.metadata(nh).set(cv::gimpl::NodeKind{cv::gimpl::NodeKind::ISLAND});
+ g.metadata(nh).set<cv::gimpl::FusedIsland>({std::move(isl)});
+ return nh;
+}
+
+void GIslandModel::syncIslandTags(Graph &g, ade::Graph &orig_g)
+{
+ GModel::Graph gm(orig_g);
+ for (auto nh : g.nodes())
+ {
+ if (NodeKind::ISLAND == g.metadata(nh).get<NodeKind>().k)
+ {
+ auto island = g.metadata(nh).get<FusedIsland>().object;
+ auto isl_tag = island->name();
+ for (const auto& orig_nh_inside : island->contents())
+ {
+ gm.metadata(orig_nh_inside).set(Island{isl_tag});
+ }
+ }
+ }
+}
+
+void GIslandModel::compileIslands(Graph &g, const ade::Graph &orig_g, const GCompileArgs &args)
+{
+ GModel::ConstGraph gm(orig_g);
+
+ auto original_sorted = gm.metadata().get<ade::passes::TopologicalSortData>();
+ for (auto nh : g.nodes())
+ {
+ if (NodeKind::ISLAND == g.metadata(nh).get<NodeKind>().k)
+ {
+ auto island_obj = g.metadata(nh).get<FusedIsland>().object;
+ auto island_ops = island_obj->contents();
+
+ std::vector<ade::NodeHandle> topo_sorted_list;
+ ade::util::copy_if(original_sorted.nodes(),
+ std::back_inserter(topo_sorted_list),
+ [&](ade::NodeHandle sorted_nh) {
+ return ade::util::contains(island_ops, sorted_nh);
+ });
+
+ auto island_exe = island_obj->backend().priv()
+ .compile(orig_g, args, topo_sorted_list);
+ GAPI_Assert(nullptr != island_exe);
+ g.metadata(nh).set(IslandExec{std::move(island_exe)});
+ }
+ }
+}
+
+ade::NodeHandle GIslandModel::producerOf(const ConstGraph &g, ade::NodeHandle &data_nh)
+{
+ for (auto nh : g.nodes())
+ {
+ // find a data slot...
+ if (NodeKind::SLOT == g.metadata(nh).get<NodeKind>().k)
+ {
+ // which is associated with the given data object...
+ if (data_nh == g.metadata(nh).get<DataSlot>().original_data_node)
+ {
+ // which probably has a produrer...
+ if (0u != nh->inNodes().size())
+ {
+ // ...then the answer is that producer
+ return nh->inNodes().front();
+ }
+ else return ade::NodeHandle(); // input data object?
+ // return empty to break the cycle
+ }
+ }
+ }
+ // No appropriate data slot found - probably, the object has been
+ // optimized out during fusion
+ return ade::NodeHandle();
+}
+
+} // namespace cv
+} // namespace gimpl
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.hpp
new file mode 100644
index 000000000..03b42ff38
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gislandmodel.hpp
@@ -0,0 +1,187 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GISLANDMODEL_HPP
+#define OPENCV_GAPI_GISLANDMODEL_HPP
+
+#include <unordered_set>
+#include <memory> // shared_ptr
+
+#include <ade/graph.hpp>
+#include <ade/typed_graph.hpp>
+#include <ade/passes/topological_sort.hpp>
+
+#include "opencv2/gapi/util/optional.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+
+#include "compiler/gobjref.hpp"
+
+namespace cv { namespace gimpl {
+
+
+// FIXME: GAPI_EXPORTS only because of tests!
+class GAPI_EXPORTS GIsland
+{
+public:
+ using node_set = std::unordered_set
+ < ade::NodeHandle
+ , ade::HandleHasher<ade::Node>
+ >;
+
+ // Initial constructor (constructs a single-op Island)
+ GIsland(const gapi::GBackend &bknd,
+ ade::NodeHandle op,
+ util::optional<std::string>&& user_tag);
+
+ // Merged constructor
+ GIsland(const gapi::GBackend &bknd,
+ node_set &&all,
+ node_set &&in_ops,
+ node_set &&out_ops,
+ util::optional<std::string>&& user_tag);
+
+ const node_set& contents() const;
+ const node_set& in_ops() const;
+ const node_set& out_ops() const;
+
+ std::string name() const;
+ gapi::GBackend backend() const;
+
+ /**
+ * Returns all GModel operation node handles which are _reading_
+ * from a GModel data object associated (wrapped in) the given
+ * Slot object.
+ *
+ * @param g an ade::Graph with GIslandModel information inside
+ * @param slot_nh Slot object node handle of interest
+ * @return a set of GModel operation node handles
+ */
+ node_set consumers(const ade::Graph &g,
+ const ade::NodeHandle &slot_nh) const;
+
+ /**
+ * Returns a GModel operation node handle which is _writing_
+ * to a GModel data object associated (wrapped in) the given
+ * Slot object.
+ *
+ * @param g an ade::Graph with GIslandModel information inside
+ * @param slot_nh Slot object node handle of interest
+ * @return a node handle of original GModel
+ */
+ ade::NodeHandle producer(const ade::Graph &g,
+ const ade::NodeHandle &slot_nh) const;
+
+ void debug() const;
+ bool is_user_specified() const;
+
+protected:
+ gapi::GBackend m_backend; // backend which handles this Island execution
+
+ node_set m_all; // everything (data + operations) within an island
+ node_set m_in_ops; // operations island begins with
+ node_set m_out_ops; // operations island ends with
+
+ // has island name IF specified by user. Empty for internal (inferred) islands
+ util::optional<std::string> m_user_tag;
+};
+
+
+
+// GIslandExecutable - a backend-specific thing which executes
+// contents of an Island
+// * Is instantiated by the last step of the Islands fusion procedure;
+// * Is orchestrated by a GExecutor instance.
+//
+class GIslandExecutable
+{
+public:
+ using InObj = std::pair<RcDesc, cv::GRunArg>;
+ using OutObj = std::pair<RcDesc, cv::GRunArgP>;
+
+ // FIXME: now run() requires full input vector to be available.
+ // actually, parts of subgraph may execute even if there's no all data
+ // slots in place.
+ // TODO: Add partial execution capabilities
+ virtual void run(std::vector<InObj> &&input_objs,
+ std::vector<OutObj> &&output_objs) = 0;
+
+ virtual bool canReshape() const = 0;
+ virtual void reshape(ade::Graph& g, const GCompileArgs& args) = 0;
+
+ virtual ~GIslandExecutable() = default;
+};
+
+
+
+// Couldn't reuse NodeType here - FIXME unify (move meta to a shared place)
+struct NodeKind
+{
+ static const char *name() { return "NodeKind"; }
+ enum { ISLAND, SLOT} k;
+};
+
+// FIXME: Rename to Island (as soon as current GModel::Island is renamed
+// to IslandTag).
+struct FusedIsland
+{
+ static const char *name() { return "FusedIsland"; }
+ std::shared_ptr<GIsland> object;
+};
+
+struct DataSlot
+{
+ static const char *name() { return "DataSlot"; }
+ ade::NodeHandle original_data_node; // direct link to GModel
+};
+
+struct IslandExec
+{
+ static const char *name() { return "IslandExecutable"; }
+ std::shared_ptr<GIslandExecutable> object;
+};
+
+namespace GIslandModel
+{
+ using Graph = ade::TypedGraph
+ < NodeKind
+ , FusedIsland
+ , DataSlot
+ , IslandExec
+ , ade::passes::TopologicalSortData
+ >;
+
+ // FIXME: derive from TypedGraph
+ using ConstGraph = ade::ConstTypedGraph
+ < NodeKind
+ , FusedIsland
+ , DataSlot
+ , IslandExec
+ , ade::passes::TopologicalSortData
+ >;
+
+ // Top-level function
+ void generateInitial(Graph &g, const ade::Graph &src_g);
+ // "Building blocks"
+ ade::NodeHandle mkSlotNode(Graph &g, const ade::NodeHandle &data_nh);
+ ade::NodeHandle mkIslandNode(Graph &g, const gapi::GBackend &bknd, const ade::NodeHandle &op_nh, const ade::Graph &orig_g);
+ ade::NodeHandle mkIslandNode(Graph &g, std::shared_ptr<GIsland>&& isl);
+
+ // GIslandModel API
+ void syncIslandTags(Graph &g, ade::Graph &orig_g);
+ void compileIslands(Graph &g, const ade::Graph &orig_g, const GCompileArgs &args);
+
+ // Debug routines
+ // producerOf - returns an Island handle which produces given data object
+ // from the original model (! don't mix with DataSlot)
+ // FIXME: GAPI_EXPORTS because of tests only!
+ ade::NodeHandle GAPI_EXPORTS producerOf(const ConstGraph &g, ade::NodeHandle &data_nh);
+
+} // namespace GIslandModel
+
+}} // namespace cv::gimpl
+
+#endif // OPENCV_GAPI_GISLANDMODEL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.cpp
new file mode 100644
index 000000000..4b2455219
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.cpp
@@ -0,0 +1,247 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <string>
+#include <sstream> // used in GModel::log
+
+
+#include <ade/util/zip_range.hpp> // util::indexed
+#include <ade/util/checked_cast.hpp>
+
+#include "opencv2/gapi/gproto.hpp"
+#include "api/gnode_priv.hpp"
+#include "compiler/gobjref.hpp"
+#include "compiler/gmodel.hpp"
+
+namespace cv { namespace gimpl {
+
+ade::NodeHandle GModel::mkOpNode(GModel::Graph &g, const GKernel &k, const std::vector<GArg> &args, const std::string &island)
+{
+ ade::NodeHandle op_h = g.createNode();
+ g.metadata(op_h).set(NodeType{NodeType::OP});
+ //These extra empty {} are to please GCC (-Wmissing-field-initializers)
+ g.metadata(op_h).set(Op{k, args, {}, {}, {}});
+ if (!island.empty())
+ g.metadata(op_h).set(Island{island});
+ return op_h;
+}
+
+ade::NodeHandle GModel::mkDataNode(GModel::Graph &g, const GOrigin& origin)
+{
+ ade::NodeHandle op_h = g.createNode();
+ const auto id = g.metadata().get<DataObjectCounter>().GetNewId(origin.shape);
+ g.metadata(op_h).set(NodeType{NodeType::DATA});
+
+ GMetaArg meta;
+ Data::Storage storage = Data::Storage::INTERNAL; // By default, all objects are marked INTERNAL
+
+ if (origin.node.shape() == GNode::NodeShape::CONST_BOUNDED)
+ {
+ auto value = value_of(origin);
+ meta = descr_of(value);
+ storage = Data::Storage::CONST;
+ g.metadata(op_h).set(ConstValue{value});
+ }
+ g.metadata(op_h).set(Data{origin.shape, id, meta, origin.ctor, storage});
+ return op_h;
+}
+
+void GModel::linkIn(Graph &g, ade::NodeHandle opH, ade::NodeHandle objH, std::size_t in_port)
+{
+ // Check if input is already connected
+ for (const auto& in_e : opH->inEdges())
+ {
+ GAPI_Assert(g.metadata(in_e).get<Input>().port != in_port);
+ }
+
+ auto &op = g.metadata(opH).get<Op>();
+ auto &gm = g.metadata(objH).get<Data>();
+
+ // FIXME: check validity using kernel prototype
+ GAPI_Assert(in_port < op.args.size());
+
+ ade::EdgeHandle eh = g.link(objH, opH);
+ g.metadata(eh).set(Input{in_port});
+
+ // Replace an API object with a REF (G* -> GOBJREF)
+ op.args[in_port] = cv::GArg(RcDesc{gm.rc, gm.shape, {}});
+}
+
+void GModel::linkOut(Graph &g, ade::NodeHandle opH, ade::NodeHandle objH, std::size_t out_port)
+{
+ // FIXME: check validity using kernel prototype
+
+ // Check if output is already connected
+ for (const auto& out_e : opH->outEdges())
+ {
+ GAPI_Assert(g.metadata(out_e).get<Output>().port != out_port);
+ }
+
+ auto &op = g.metadata(opH).get<Op>();
+ auto &gm = g.metadata(objH).get<Data>();
+
+ GAPI_Assert(objH->inNodes().size() == 0u);
+
+ ade::EdgeHandle eh = g.link(opH, objH);
+ g.metadata(eh).set(Output{out_port});
+
+ // TODO: outs must be allocated according to kernel protocol!
+ const auto storage_with_port = ade::util::checked_cast<std::size_t>(out_port+1);
+ const auto min_out_size = std::max(op.outs.size(), storage_with_port);
+ op.outs.resize(min_out_size, RcDesc{-1,GShape::GMAT,{}}); // FIXME: Invalid shape instead?
+ op.outs[out_port] = RcDesc{gm.rc, gm.shape, {}};
+}
+
+std::vector<ade::NodeHandle> GModel::orderedInputs(Graph &g, ade::NodeHandle nh)
+{
+ std::vector<ade::NodeHandle> sorted_in_nhs(nh->inEdges().size());
+ for (const auto& in_eh : nh->inEdges())
+ {
+ const auto port = g.metadata(in_eh).get<cv::gimpl::Input>().port;
+ GAPI_Assert(port < sorted_in_nhs.size());
+ sorted_in_nhs[port] = in_eh->srcNode();
+ }
+ return sorted_in_nhs;
+}
+
+std::vector<ade::NodeHandle> GModel::orderedOutputs(Graph &g, ade::NodeHandle nh)
+{
+ std::vector<ade::NodeHandle> sorted_out_nhs(nh->outEdges().size());
+ for (const auto& out_eh : nh->outEdges())
+ {
+ const auto port = g.metadata(out_eh).get<cv::gimpl::Output>().port;
+ GAPI_Assert(port < sorted_out_nhs.size());
+ sorted_out_nhs[port] = out_eh->dstNode();
+ }
+ return sorted_out_nhs;
+}
+
+void GModel::init(Graph& g)
+{
+ g.metadata().set(DataObjectCounter());
+}
+
+void GModel::log(Graph &g, ade::NodeHandle nh, std::string &&msg, ade::NodeHandle updater)
+{
+ std::string s = std::move(msg);
+ if (updater != nullptr)
+ {
+ std::stringstream fmt;
+ fmt << " (via " << updater << ")";
+ s += fmt.str();
+ }
+
+ if (g.metadata(nh).contains<Journal>())
+ {
+ g.metadata(nh).get<Journal>().messages.push_back(s);
+ }
+ else
+ {
+ g.metadata(nh).set(Journal{{s}});
+ }
+}
+
+// FIXME:
+// Unify with GModel::log(.. ade::NodeHandle ..)
+void GModel::log(Graph &g, ade::EdgeHandle eh, std::string &&msg, ade::NodeHandle updater)
+{
+ std::string s = std::move(msg);
+ if (updater != nullptr)
+ {
+ std::stringstream fmt;
+ fmt << " (via " << updater << ")";
+ s += fmt.str();
+ }
+
+ if (g.metadata(eh).contains<Journal>())
+ {
+ g.metadata(eh).get<Journal>().messages.push_back(s);
+ }
+ else
+ {
+ g.metadata(eh).set(Journal{{s}});
+ }
+}
+
+ade::NodeHandle GModel::detail::dataNodeOf(const ConstGraph &g, const GOrigin &origin)
+{
+ // FIXME: Does it still work with graph transformations, e.g. redirectWriter()??
+ return g.metadata().get<Layout>().object_nodes.at(origin);
+}
+
+void GModel::redirectReaders(Graph &g, ade::NodeHandle from, ade::NodeHandle to)
+{
+ std::vector<ade::EdgeHandle> ehh(from->outEdges().begin(), from->outEdges().end());
+ for (auto e : ehh)
+ {
+ auto dst = e->dstNode();
+ auto input = g.metadata(e).get<Input>();
+ g.erase(e);
+ linkIn(g, dst, to, input.port);
+ }
+}
+
+void GModel::redirectWriter(Graph &g, ade::NodeHandle from, ade::NodeHandle to)
+{
+ GAPI_Assert(from->inEdges().size() == 1);
+ auto e = from->inEdges().front();
+ auto op = e->srcNode();
+ auto output = g.metadata(e).get<Output>();
+ g.erase(e);
+ linkOut(g, op, to, output.port);
+}
+
+GMetaArgs GModel::collectInputMeta(GModel::ConstGraph cg, ade::NodeHandle node)
+{
+ GAPI_Assert(cg.metadata(node).get<NodeType>().t == NodeType::OP);
+ GMetaArgs in_meta_args(cg.metadata(node).get<Op>().args.size());
+
+ for (const auto &e : node->inEdges())
+ {
+ const auto& in_data = cg.metadata(e->srcNode()).get<Data>();
+ in_meta_args[cg.metadata(e).get<Input>().port] = in_data.meta;
+ }
+
+ return in_meta_args;
+}
+
+
+ade::EdgeHandle GModel::getInEdgeByPort(const GModel::ConstGraph& cg,
+ const ade::NodeHandle& nh,
+ std::size_t in_port)
+{
+ auto inEdges = nh->inEdges();
+ const auto& edge = ade::util::find_if(inEdges, [&](ade::EdgeHandle eh) {
+ return cg.metadata(eh).get<Input>().port == in_port;
+ });
+ GAPI_Assert(edge != inEdges.end());
+ return *edge;
+}
+
+GMetaArgs GModel::collectOutputMeta(GModel::ConstGraph cg, ade::NodeHandle node)
+{
+ GAPI_Assert(cg.metadata(node).get<NodeType>().t == NodeType::OP);
+ GMetaArgs out_meta_args(cg.metadata(node).get<Op>().outs.size());
+
+ for (const auto &e : node->outEdges())
+ {
+ const auto& out_data = cg.metadata(e->dstNode()).get<Data>();
+ out_meta_args[cg.metadata(e).get<Output>().port] = out_data.meta;
+ }
+
+ return out_meta_args;
+}
+
+bool GModel::isActive(const GModel::Graph &cg, const cv::gapi::GBackend &backend)
+{
+ return ade::util::contains(cg.metadata().get<ActiveBackends>().backends,
+ backend);
+}
+
+}} // cv::gimpl
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.hpp
new file mode 100644
index 000000000..003519b82
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodel.hpp
@@ -0,0 +1,251 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GMODEL_HPP
+#define OPENCV_GAPI_GMODEL_HPP
+
+#include <memory> // shared_ptr
+#include <unordered_map>
+#include <functional> // std::function
+
+#include <ade/graph.hpp>
+#include <ade/typed_graph.hpp>
+#include <ade/passes/topological_sort.hpp>
+
+// /!\ ATTENTION:
+//
+// No API includes like GMat, GNode, GCall here!
+// This part of the system is API-unaware by its design.
+//
+
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+#include "api/gapi_priv.hpp" // GShape
+#include "api/gproto_priv.hpp" // origin_of
+#include "backends/common/gbackend.hpp"
+
+#include "compiler/gobjref.hpp"
+#include "compiler/gislandmodel.hpp"
+
+namespace cv { namespace gimpl {
+
+// TODO: Document all metadata types
+
+struct NodeType
+{
+ static const char *name() { return "NodeType"; }
+ enum { OP, DATA } t;
+};
+
+struct Input
+{
+ static const char *name() { return "Input"; }
+ std::size_t port;
+};
+
+struct Output
+{
+ static const char *name() { return "Output"; }
+ std::size_t port;
+};
+
+struct Op
+{
+ static const char *name() { return "Op"; }
+ cv::GKernel k;
+ std::vector<GArg> args; // TODO: Introduce a new type for internal args?
+ std::vector<RcDesc> outs; // TODO: Introduce a new type for resource references
+
+ cv::gapi::GBackend backend;
+ util::any opaque;
+};
+
+struct Data
+{
+ static const char *name() { return "Data"; }
+
+ // FIXME: This is a _pure_ duplication of RcDesc now! (except storage)
+ GShape shape; // FIXME: Probably to be replaced by GMetaArg?
+ int rc;
+ GMetaArg meta;
+ HostCtor ctor; // T-specific helper to deal with unknown types in our code
+ // FIXME: Why rc+shape+meta is not represented as RcDesc here?
+
+ enum class Storage
+ {
+ INTERNAL, // data object is not listed in GComputation protocol
+ INPUT, // data object is listed in GComputation protocol as Input
+ OUTPUT, // data object is listed in GComputation protocol as Output
+ CONST, // data object is constant
+ };
+ Storage storage;
+};
+
+struct ConstValue
+{
+ static const char *name() { return "ConstValue"; }
+ GRunArg arg;
+};
+
+// This metadata is valid for both DATA and OP kinds of nodes
+// FIXME: Rename to IslandTag
+struct Island
+{
+ static const char *name() { return "Island"; }
+ std::string island; // can be set by user, otherwise is set by fusion
+};
+
+struct Protocol
+{
+ static const char *name() { return "Protocol"; }
+ // TODO: Replace the whole thing with a "Protocol" object
+ std::vector<RcDesc> inputs;
+ std::vector<RcDesc> outputs;
+
+ std::vector<ade::NodeHandle> in_nhs;
+ std::vector<ade::NodeHandle> out_nhs;
+};
+
+struct OutputMeta
+{
+ static const char *name() { return "OutputMeta"; }
+ GMetaArgs outMeta;
+};
+
+struct Journal
+{
+ static const char *name() { return "Journal"; }
+ std::vector<std::string> messages;
+};
+
+// The mapping between user-side GMat/GScalar/... objects
+// and its appropriate nodes. Can be stored in graph optionally
+// (NOT used by any compiler or backends, introspection purposes
+// only)
+struct Layout
+{
+ static const char *name() { return "Layout"; }
+ GOriginMap<ade::NodeHandle> object_nodes;
+};
+
+// Unique data object counter (per-type)
+class DataObjectCounter
+{
+public:
+ static const char* name() { return "DataObjectCounter"; }
+ int GetNewId(GShape shape) { return m_next_data_id[shape]++; }
+private:
+ std::unordered_map<cv::GShape, int> m_next_data_id;
+};
+
+// A projected graph of Islands (generated from graph of Operations)
+struct IslandModel
+{
+ static const char* name() { return "IslandModel"; }
+ std::shared_ptr<ade::Graph> model;
+};
+
+// List of backends selected for current graph execution
+struct ActiveBackends
+{
+ static const char *name() { return "ActiveBackends"; }
+ std::unordered_set<cv::gapi::GBackend> backends;
+};
+
+namespace GModel
+{
+ using Graph = ade::TypedGraph
+ < NodeType
+ , Input
+ , Output
+ , Op
+ , Data
+ , ConstValue
+ , Island
+ , Protocol
+ , OutputMeta
+ , Journal
+ , ade::passes::TopologicalSortData
+ , DataObjectCounter
+ , Layout
+ , IslandModel
+ , ActiveBackends
+ >;
+
+ // FIXME: How to define it based on GModel???
+ using ConstGraph = ade::ConstTypedGraph
+ < NodeType
+ , Input
+ , Output
+ , Op
+ , Data
+ , ConstValue
+ , Island
+ , Protocol
+ , OutputMeta
+ , Journal
+ , ade::passes::TopologicalSortData
+ , DataObjectCounter
+ , Layout
+ , IslandModel
+ , ActiveBackends
+ >;
+
+ // User should initialize graph before using it
+ // GAPI_EXPORTS for tests
+ GAPI_EXPORTS void init (Graph& g);
+
+ ade::NodeHandle mkOpNode(Graph &g, const GKernel &k, const std::vector<GArg>& args, const std::string &island);
+
+ // FIXME: change it to take GMeta instead of GShape?
+ ade::NodeHandle mkDataNode(Graph &g, const GOrigin& origin);
+
+ // Adds a string message to a node. Any node can be subject of log, messages then
+ // appear in the dumped .dot file.x
+ void log(Graph &g, ade::NodeHandle op, std::string &&message, ade::NodeHandle updater = ade::NodeHandle());
+ void log(Graph &g, ade::EdgeHandle op, std::string &&message, ade::NodeHandle updater = ade::NodeHandle());
+
+ void linkIn (Graph &g, ade::NodeHandle op, ade::NodeHandle obj, std::size_t in_port);
+ void linkOut (Graph &g, ade::NodeHandle op, ade::NodeHandle obj, std::size_t out_port);
+
+ // FIXME: Align this GModel API properly, it is a mess now
+ namespace detail
+ {
+ // FIXME: GAPI_EXPORTS only because of tests!!!
+ GAPI_EXPORTS ade::NodeHandle dataNodeOf(const ConstGraph& g, const GOrigin &origin);
+ }
+ template<typename T> inline ade::NodeHandle dataNodeOf(const ConstGraph& g, T &&t)
+ {
+ return detail::dataNodeOf(g, cv::gimpl::proto::origin_of(GProtoArg{t}));
+ }
+
+ void linkIn (Graph &g, ade::NodeHandle op, ade::NodeHandle obj, std::size_t in_port);
+ void linkOut (Graph &g, ade::NodeHandle op, ade::NodeHandle obj, std::size_t out_port);
+
+ void redirectReaders(Graph &g, ade::NodeHandle from, ade::NodeHandle to);
+ void redirectWriter (Graph &g, ade::NodeHandle from, ade::NodeHandle to);
+
+ std::vector<ade::NodeHandle> orderedInputs (Graph &g, ade::NodeHandle nh);
+ std::vector<ade::NodeHandle> orderedOutputs(Graph &g, ade::NodeHandle nh);
+
+ // Returns input meta array for given op node
+ // Array is sparse, as metadata for non-gapi input objects is empty
+ // TODO:
+ // Cover with tests!!
+ GMetaArgs collectInputMeta(GModel::ConstGraph cg, ade::NodeHandle node);
+ GMetaArgs collectOutputMeta(GModel::ConstGraph cg, ade::NodeHandle node);
+
+ ade::EdgeHandle getInEdgeByPort(const GModel::ConstGraph& cg, const ade::NodeHandle& nh, std::size_t in_port);
+
+ // Returns true if the given backend participates in the execution
+ bool isActive(const GModel::Graph &cg, const cv::gapi::GBackend &backend);
+} // namespace GModel
+
+
+}} // namespace cv::gimpl
+
+#endif // OPENCV_GAPI_GMODEL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodelbuilder.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodelbuilder.cpp
new file mode 100644
index 000000000..c9b2fbbdf
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodelbuilder.cpp
@@ -0,0 +1,305 @@
+// 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) 2018 Intel Corporation
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// FIXME: "I personally hate this file"
+// - Dmitry
+//
+////////////////////////////////////////////////////////////////////////////////
+#include "precomp.hpp"
+
+#include <utility> // tuple
+#include <stack> // stack
+#include <vector> // vector
+#include <unordered_set> // unordered_set
+#include <type_traits> // is_same
+
+#include <ade/util/zip_range.hpp> // util::indexed
+
+#include "api/gapi_priv.hpp" // GOrigin
+#include "api/gproto_priv.hpp" // descriptor_of and other GProtoArg-related
+#include "api/gcall_priv.hpp"
+#include "api/gnode_priv.hpp"
+
+#include "compiler/gmodelbuilder.hpp"
+
+namespace {
+
+
+// TODO: move to helpers and cover with internal tests?
+template<typename T> struct GVisited
+{
+ typedef std::unordered_set<T> VTs;
+
+ bool visited(const T& t) const { return m_visited.find(t) != m_visited.end(); }
+ void visit (const T& t) { m_visited.insert(t); }
+ const VTs& visited() const { return m_visited; }
+
+private:
+ VTs m_visited;
+};
+
+template<typename T, typename U = T> struct GVisitedTracker: protected GVisited<T>
+{
+ typedef std::vector<U> TUs;
+
+ void visit(const T& t, const U& u) { GVisited<T>::visit(t); m_tracked.push_back(u); }
+ const TUs& tracked() const { return m_tracked; }
+ using GVisited<T>::visited;
+
+private:
+ TUs m_tracked;
+};
+
+} // namespace
+
+
+cv::gimpl::Unrolled cv::gimpl::unrollExpr(const GProtoArgs &ins,
+ const GProtoArgs &outs)
+{
+ // FIXME: Who's gonna check if ins/outs are not EMPTY?
+ // FIXME: operator== for GObjects? (test if the same object or not)
+ using GObjId = const cv::GOrigin*;
+
+ GVisitedTracker<const GNode::Priv*, cv::GNode> ops;
+ GVisited<GObjId> reached_sources;
+ cv::GOriginSet origins;
+
+ // Cache input argument objects for a faster look-up
+ // While the only reliable way to identify a Data object is Origin
+ // (multiple data objects may refer to the same Origin as result of
+ // multuple yield() calls), input objects can be uniquely identified
+ // by its `priv` address. Here we rely on this to verify if the expression
+ // we unroll actually matches the protocol specified to us by user.
+ std::unordered_set<GObjId> in_objs_p;
+ for (const auto& in_obj : ins)
+ {
+ // Objects are guarnateed to remain alive while this method
+ // is working, so it is safe to keep pointers here and below
+ in_objs_p.insert(&proto::origin_of(in_obj));
+ }
+
+ // Recursive expression traversal
+ std::stack<cv::GProtoArg> data_objs(std::deque<cv::GProtoArg>(outs.begin(), outs.end()));
+ while (!data_objs.empty())
+ {
+ const auto obj = data_objs.top();
+ const auto &obj_p = proto::origin_of(obj);
+ data_objs.pop();
+
+ const auto &origin = obj_p;
+ origins.insert(origin); // TODO: Put Object description here later on
+
+ // If this Object is listed in the protocol, don't dive deeper (even
+ // if it is in fact a result of operation). Our computation is
+ // bounded by this data slot, so terminate this recursion path early.
+ if (in_objs_p.find(&obj_p) != in_objs_p.end())
+ {
+ reached_sources.visit(&obj_p);
+ continue;
+ }
+
+ const cv::GNode &node = origin.node;
+ switch (node.shape())
+ {
+ case cv::GNode::NodeShape::EMPTY:
+ // TODO: Own exception type?
+ util::throw_error(std::logic_error("Empty node reached!"));
+ break;
+
+ case cv::GNode::NodeShape::PARAM:
+ case cv::GNode::NodeShape::CONST_BOUNDED:
+ // No preceding operation to this data object - so the data object is either a GComputation
+ // parameter or a constant (compile-time) value
+ // Record it to check if protocol matches expression tree later
+ if (!reached_sources.visited(&obj_p))
+ reached_sources.visit(&obj_p);
+ break;
+
+ case cv::GNode::NodeShape::CALL:
+ if (!ops.visited(&node.priv()))
+ {
+ // This operation hasn't been visited yet - mark it so,
+ // then add its operands to stack to continue recursion.
+ ops.visit(&node.priv(), node);
+
+ const cv::GCall call = origin.node.call();
+ const cv::GCall::Priv& call_p = call.priv();
+
+ // Put the outputs object description of the node
+ // so that they are not lost if they are not consumed by other operations
+ for (const auto &it : ade::util::indexed(call_p.m_k.outShapes))
+ {
+ std::size_t port = ade::util::index(it);
+ GShape shape = ade::util::value(it);
+
+ GOrigin org { shape, node, port};
+ origins.insert(org);
+ }
+
+ for (const auto &arg : call_p.m_args)
+ {
+ if (proto::is_dynamic(arg))
+ {
+ data_objs.push(proto::rewrap(arg)); // Dive deeper
+ }
+ }
+ }
+ break;
+
+ default:
+ // Unsupported node shape
+ GAPI_Assert(false);
+ break;
+ }
+ }
+
+ // Check if protocol mentions data_objs which weren't reached during traversal
+ const auto missing_reached_sources = [&reached_sources](GObjId p) {
+ return reached_sources.visited().find(p) == reached_sources.visited().end();
+ };
+ if (ade::util::any_of(in_objs_p, missing_reached_sources))
+ {
+ // TODO: Own exception type or a return code?
+ util::throw_error(std::logic_error("Data object listed in Protocol "
+ "wasn\'t reached during unroll"));
+ }
+
+ // Check if there endpoint (parameter) data_objs which are not listed in protocol
+ const auto missing_in_proto = [&in_objs_p](GObjId p) {
+ return p->node.shape() != cv::GNode::NodeShape::CONST_BOUNDED &&
+ in_objs_p.find(p) == in_objs_p.end();
+ };
+ if (ade::util::any_of(reached_sources.visited(), missing_in_proto))
+ {
+ // TODO: Own exception type or a return code?
+ util::throw_error(std::logic_error("Data object reached during unroll "
+ "wasn\'t found in Protocol"));
+ }
+
+ return cv::gimpl::Unrolled{ops.tracked(), origins};
+}
+
+
+cv::gimpl::GModelBuilder::GModelBuilder(ade::Graph &g)
+ : m_g(g)
+{
+}
+
+cv::gimpl::GModelBuilder::ProtoSlots
+cv::gimpl::GModelBuilder::put(const GProtoArgs &ins, const GProtoArgs &outs)
+{
+ const auto unrolled = cv::gimpl::unrollExpr(ins, outs);
+
+ // First, put all operations and its arguments into graph.
+ for (const auto &op_expr_node : unrolled.all_ops)
+ {
+ GAPI_Assert(op_expr_node.shape() == GNode::NodeShape::CALL);
+ const GCall& call = op_expr_node.call();
+ const GCall::Priv& call_p = call.priv();
+ ade::NodeHandle call_h = put_OpNode(op_expr_node);
+
+ for (const auto &it : ade::util::indexed(call_p.m_args))
+ {
+ const auto in_port = ade::util::index(it);
+ const auto& in_arg = ade::util::value(it);
+
+ if (proto::is_dynamic(in_arg))
+ {
+ ade::NodeHandle data_h = put_DataNode(proto::origin_of(in_arg));
+ cv::gimpl::GModel::linkIn(m_g, call_h, data_h, in_port);
+ }
+ }
+ }
+
+ // Then iterate via all "origins", instantiate (if not yet) Data graph nodes
+ // and connect these nodes with their producers in graph
+ for (const auto &origin : unrolled.all_data)
+ {
+ const cv::GNode& prod = origin.node;
+ GAPI_Assert(prod.shape() != cv::GNode::NodeShape::EMPTY);
+
+ ade::NodeHandle data_h = put_DataNode(origin);
+ if (prod.shape() == cv::GNode::NodeShape::CALL)
+ {
+ ade::NodeHandle call_h = put_OpNode(prod);
+ cv::gimpl::GModel::linkOut(m_g, call_h, data_h, origin.port);
+ }
+ }
+
+ // Mark graph data nodes as INPUTs and OUTPUTs respectively (according to the protocol)
+ for (const auto &arg : ins)
+ {
+ ade::NodeHandle nh = put_DataNode(proto::origin_of(arg));
+ m_g.metadata(nh).get<Data>().storage = Data::Storage::INPUT;
+ }
+ for (const auto &arg : outs)
+ {
+ ade::NodeHandle nh = put_DataNode(proto::origin_of(arg));
+ m_g.metadata(nh).get<Data>().storage = Data::Storage::OUTPUT;
+ }
+
+ // And, finally, store data object layout in meta
+ m_g.metadata().set(Layout{m_graph_data});
+
+ // After graph is generated, specify which data objects are actually
+ // computation entry/exit points.
+ using NodeDescr = std::pair<std::vector<RcDesc>,
+ std::vector<ade::NodeHandle> >;
+
+ const auto get_proto_slots = [&](const GProtoArgs &proto) -> NodeDescr
+ {
+ NodeDescr slots;
+
+ slots.first.reserve(proto.size());
+ slots.second.reserve(proto.size());
+
+ for (const auto &arg : proto)
+ {
+ ade::NodeHandle nh = put_DataNode(proto::origin_of(arg));
+ const auto &desc = m_g.metadata(nh).get<Data>();
+ //These extra empty {} are to please GCC (-Wmissing-field-initializers)
+ slots.first.push_back(RcDesc{desc.rc, desc.shape, {}});
+ slots.second.push_back(nh);
+ }
+ return slots;
+ };
+
+ auto in_slots = get_proto_slots(ins);
+ auto out_slots = get_proto_slots(outs);
+ return ProtoSlots{in_slots.first, out_slots.first,
+ in_slots.second, out_slots.second};
+}
+
+ade::NodeHandle cv::gimpl::GModelBuilder::put_OpNode(const cv::GNode &node)
+{
+ const auto& node_p = node.priv();
+ const auto it = m_graph_ops.find(&node_p);
+ if (it == m_graph_ops.end())
+ {
+ GAPI_Assert(node.shape() == GNode::NodeShape::CALL);
+ const auto &call_p = node.call().priv();
+ auto nh = cv::gimpl::GModel::mkOpNode(m_g, call_p.m_k, call_p.m_args, node_p.m_island);
+ m_graph_ops[&node_p] = nh;
+ return nh;
+ }
+ else return it->second;
+}
+
+// FIXME: rename to get_DataNode (and same for Op)
+ade::NodeHandle cv::gimpl::GModelBuilder::put_DataNode(const GOrigin &origin)
+{
+ const auto it = m_graph_data.find(origin);
+ if (it == m_graph_data.end())
+ {
+ auto nh = cv::gimpl::GModel::mkDataNode(m_g, origin);
+ m_graph_data[origin] = nh;
+ return nh;
+ }
+ else return it->second;
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodelbuilder.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodelbuilder.hpp
new file mode 100644
index 000000000..ce12c7e11
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gmodelbuilder.hpp
@@ -0,0 +1,77 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GMODEL_BUILDER_HPP
+#define OPENCV_GAPI_GMODEL_BUILDER_HPP
+
+#include <map>
+#include <unordered_map>
+
+#include "opencv2/gapi/gproto.hpp"
+#include "opencv2/gapi/gcall.hpp"
+
+#include "api/gapi_priv.hpp"
+#include "api/gnode.hpp"
+#include "compiler/gmodel.hpp"
+
+namespace cv { namespace gimpl {
+
+struct Unrolled
+{
+ std::vector<cv::GNode> all_ops;
+ GOriginSet all_data;
+
+ // NB.: Right now, as G-API operates with GMats only and that
+ // GMats have no type or dimensions (when a computation is built),
+ // track only origins (data links) with no any additional meta.
+};
+
+// FIXME: GAPI_EXPORTS only because of tests!!!
+GAPI_EXPORTS Unrolled unrollExpr(const GProtoArgs &ins, const GProtoArgs &outs);
+
+// This class generates an ADE graph with G-API specific metadata
+// to represent user-specified computation in terms of graph model
+//
+// Resulting graph is built according to the following rules:
+// - Every operation is a node
+// - Every dynamic object (GMat) is a node
+// - Edges between nodes represent producer/consumer relationships
+// between operations and data objects.
+// FIXME: GAPI_EXPORTS only because of tests!!!
+class GAPI_EXPORTS GModelBuilder
+{
+ GModel::Graph m_g;
+
+ // Mappings of G-API user framework entities to ADE node handles
+ std::unordered_map<const cv::GNode::Priv*, ade::NodeHandle> m_graph_ops;
+ GOriginMap<ade::NodeHandle> m_graph_data;
+
+ // Internal methods for mapping APIs into ADE during put()
+ ade::NodeHandle put_OpNode(const cv::GNode &node);
+ ade::NodeHandle put_DataNode(const cv::GOrigin &origin);
+
+public:
+ explicit GModelBuilder(ade::Graph &g);
+
+ // TODO: replace GMat with a generic type
+ // TODO: Cover with tests! (as the rest of internal stuff)
+ // FIXME: Calling this method multiple times is currently UB
+ // TODO: add a semantic link between "ints" returned and in-model data IDs.
+ typedef std::tuple<std::vector<RcDesc>,
+ std::vector<RcDesc>,
+ std::vector<ade::NodeHandle>,
+ std::vector<ade::NodeHandle> > ProtoSlots;
+
+ ProtoSlots put(const GProtoArgs &ins, const GProtoArgs &outs);
+
+protected:
+ ade::NodeHandle opNode(cv::GMat gmat);
+};
+
+}}
+
+#endif // OPENCV_GAPI_GMODEL_BUILDER_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gobjref.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gobjref.hpp
new file mode 100644
index 000000000..be365c90e
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/gobjref.hpp
@@ -0,0 +1,50 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GMATREF_HPP
+#define OPENCV_GAPI_GMATREF_HPP
+
+#include "opencv2/gapi/util/variant.hpp"
+#include "opencv2/gapi/garg.hpp"
+
+#include "api/gapi_priv.hpp" // GShape, HostCtor
+
+namespace cv
+{
+
+namespace gimpl
+{
+ struct RcDesc
+ {
+ int id; // id is unique but local to shape
+ GShape shape; // pair <id,shape> IS the unique ID
+ HostCtor ctor; // FIXME: is it really used here? Or in <Data>?
+
+ bool operator==(const RcDesc &rhs) const
+ {
+ // FIXME: ctor is not checked (should be?)
+ return id == rhs.id && shape == rhs.shape;
+ }
+
+ bool operator< (const RcDesc &rhs) const
+ {
+ return (id == rhs.id) ? shape < rhs.shape : id < rhs.id;
+ }
+ };
+} // gimpl
+
+namespace detail
+{
+ template<> struct GTypeTraits<cv::gimpl::RcDesc>
+ {
+ static constexpr const ArgKind kind = ArgKind::GOBJREF;
+ };
+}
+
+} // cv
+
+#endif // OPENCV_GAPI_GMATREF_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/dump_dot.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/dump_dot.cpp
new file mode 100644
index 000000000..8741089ba
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/dump_dot.cpp
@@ -0,0 +1,223 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <iostream> // cout
+#include <sstream> // stringstream
+#include <fstream> // ofstream
+
+#include <ade/passes/check_cycles.hpp>
+
+#include "opencv2/gapi/gproto.hpp"
+#include "compiler/gmodel.hpp"
+#include "compiler/gislandmodel.hpp"
+#include "compiler/passes/passes.hpp"
+
+namespace cv { namespace gimpl { namespace passes {
+
+// TODO: FIXME: Ideally all this low-level stuff with accessing ADE APIs directly
+// should be incapsulated somewhere into GModel, so here we'd operate not
+// with raw nodes and edges, but with Operations and Data it produce/consume.
+void dumpDot(const ade::Graph &g, std::ostream& os)
+{
+ GModel::ConstGraph gr(g);
+
+ const std::unordered_map<cv::GShape, std::string> data_labels = {
+ {cv::GShape::GMAT, "GMat"},
+ {cv::GShape::GSCALAR, "GScalar"},
+ {cv::GShape::GARRAY, "GArray"},
+ };
+
+ auto format_op_label = [&gr](ade::NodeHandle nh) -> std::string {
+ std::stringstream ss;
+ const cv::GKernel k = gr.metadata(nh).get<Op>().k;
+ ss << k.name << "_" << nh;
+ return ss.str();
+ };
+
+ auto format_op = [&format_op_label](ade::NodeHandle nh) -> std::string {
+ return "\"" + format_op_label(nh) + "\"";
+ };
+
+ auto format_obj = [&gr, &data_labels](ade::NodeHandle nh) -> std::string {
+ std::stringstream ss;
+ const auto &data = gr.metadata(nh).get<Data>();
+ ss << data_labels.at(data.shape) << "_" << data.rc;
+ return ss.str();
+ };
+
+ auto format_log = [&gr](ade::NodeHandle nh, const std::string &obj_name) {
+ std::stringstream ss;
+ const auto &msgs = gr.metadata(nh).get<Journal>().messages;
+ ss << "xlabel=\"";
+ if (!obj_name.empty()) { ss << "*** " << obj_name << " ***:\n"; };
+ for (const auto &msg : msgs) { ss << msg << "\n"; }
+ ss << "\"";
+ return ss.str();
+ };
+
+ // FIXME:
+ // Unify with format_log
+ auto format_log_e = [&gr](ade::EdgeHandle nh) {
+ std::stringstream ss;
+ const auto &msgs = gr.metadata(nh).get<Journal>().messages;
+ for (const auto &msg : msgs) { ss << "\n" << msg; }
+ return ss.str();
+ };
+
+ auto sorted = gr.metadata().get<ade::passes::TopologicalSortData>();
+
+ os << "digraph GAPI_Computation {\n";
+
+ // Prior to dumping the graph itself, list Data and Op nodes individually
+ // and put type information in labels.
+ // Also prepare list of nodes in islands, if any
+ std::map<std::string, std::vector<std::string> > islands;
+ for (auto &nh : sorted.nodes())
+ {
+ const auto node_type = gr.metadata(nh).get<NodeType>().t;
+ if (NodeType::DATA == node_type)
+ {
+ const auto obj_data = gr.metadata(nh).get<Data>();
+ const auto obj_name = format_obj(nh);
+
+ os << obj_name << " [label=\"" << obj_name << "\n" << obj_data.meta << "\"";
+ if (gr.metadata(nh).contains<Journal>()) { os << ", " << format_log(nh, obj_name); }
+ os << " ]\n";
+
+ if (gr.metadata(nh).contains<Island>())
+ islands[gr.metadata(nh).get<Island>().island].push_back(obj_name);
+ }
+ else if (NodeType::OP == gr.metadata(nh).get<NodeType>().t)
+ {
+ const auto obj_name = format_op(nh);
+ const auto obj_name_label = format_op_label(nh);
+
+ os << obj_name << " [label=\"" << obj_name_label << "\"";
+ if (gr.metadata(nh).contains<Journal>()) { os << ", " << format_log(nh, obj_name_label); }
+ os << " ]\n";
+
+ if (gr.metadata(nh).contains<Island>())
+ islands[gr.metadata(nh).get<Island>().island].push_back(obj_name);
+ }
+ }
+
+ // Then, dump Islands (only nodes, operations and data, without links)
+ for (const auto &isl : islands)
+ {
+ os << "subgraph \"cluster " + isl.first << "\" {\n";
+ for(auto isl_node : isl.second) os << isl_node << ";\n";
+ os << "label=\"" << isl.first << "\";";
+ os << "}\n";
+ }
+
+ // Now dump the graph
+ for (auto &nh : sorted.nodes())
+ {
+ // FIXME: Alan Kay probably hates me.
+ switch (gr.metadata(nh).get<NodeType>().t)
+ {
+ case NodeType::DATA:
+ {
+ const auto obj_name = format_obj(nh);
+ for (const auto &eh : nh->outEdges())
+ {
+ os << obj_name << " -> " << format_op(eh->dstNode())
+ << " [ label = \"in_port: "
+ << gr.metadata(eh).get<Input>().port;
+ if (gr.metadata(eh).contains<Journal>()) { os << format_log_e(eh); }
+ os << "\" ] \n";
+ }
+ }
+ break;
+ case NodeType::OP:
+ {
+ for (const auto &eh : nh->outEdges())
+ {
+ os << format_op(nh) << " -> " << format_obj(eh->dstNode())
+ << " [ label = \"out_port: "
+ << gr.metadata(eh).get<Output>().port
+ << " \" ]; \n";
+ }
+ }
+ break;
+ default: GAPI_Assert(false);
+ }
+ }
+
+ // And finally dump a GIslandModel (not connected with GModel directly,
+ // but projected in the same .dot file side-by-side)
+ auto pIG = gr.metadata().get<IslandModel>().model;
+ GIslandModel::Graph gim(*pIG);
+ for (auto nh : gim.nodes())
+ {
+ switch (gim.metadata(nh).get<NodeKind>().k)
+ {
+ case NodeKind::ISLAND:
+ {
+ const auto island = gim.metadata(nh).get<FusedIsland>().object;
+ const auto isl_name = "\"" + island->name() + "\"";
+ for (auto out_nh : nh->outNodes())
+ {
+ os << isl_name << " -> \"slot:"
+ << format_obj(gim.metadata(out_nh).get<DataSlot>()
+ .original_data_node)
+ << "\"\n";
+ }
+ }
+ break;
+
+ case NodeKind::SLOT:
+ {
+ const auto obj_name = format_obj(gim.metadata(nh).get<DataSlot>()
+ .original_data_node);
+ for (auto cons_nh : nh->outNodes())
+ {
+ os << "\"slot:" << obj_name << "\" -> \""
+ << gim.metadata(cons_nh).get<FusedIsland>().object->name()
+ << "\"\n";
+ }
+ }
+ break;
+
+ default:
+ GAPI_Assert(false);
+ break;
+ }
+ }
+
+ os << "}" << std::endl;
+}
+
+void dumpDot(ade::passes::PassContext &ctx, std::ostream& os)
+{
+ dumpDot(ctx.graph, os);
+}
+
+void dumpDotStdout(ade::passes::PassContext &ctx)
+{
+ dumpDot(ctx, std::cout);
+}
+
+void dumpDotToFile(ade::passes::PassContext &ctx, const std::string& dump_path)
+{
+ std::ofstream dump_file(dump_path);
+
+ if (dump_file.is_open())
+ {
+ dumpDot(ctx, dump_file);
+ dump_file << std::endl;
+ }
+}
+
+void dumpGraph(ade::passes::PassContext &ctx, const std::string& dump_path)
+{
+ dump_path.empty() ? dumpDotStdout(ctx) : dumpDotToFile(ctx, dump_path);
+}
+
+}}} // cv::gimpl::passes
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/exec.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/exec.cpp
new file mode 100644
index 000000000..7119e3411
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/exec.cpp
@@ -0,0 +1,641 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <string>
+#include <list> // list
+#include <iomanip> // setw, etc
+#include <fstream> // ofstream
+#include <memory>
+#include <functional>
+
+#include <ade/util/algorithm.hpp> // contains
+#include <ade/util/chain_range.hpp> // chain
+
+#include "opencv2/gapi/util/optional.hpp" // util::optional
+#include "logger.hpp" // GAPI_LOG
+
+#include "compiler/gmodel.hpp"
+#include "compiler/gislandmodel.hpp"
+#include "compiler/passes/passes.hpp"
+#include "compiler/passes/helpers.hpp"
+#include "compiler/transactions.hpp"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// N.B.
+// Merge is a binary operation (LHS `Merge` RHS) where LHS may be arbitrary
+//
+// After every merge, the procedure starts from the beginning (in the topological
+// order), thus trying to merge next "unmerged" island to the latest merged one.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Uncomment to dump more info on merge process
+// FIXME: make it user-configurable run-time option
+// #define DEBUG_MERGE
+
+namespace cv
+{
+namespace gimpl
+{
+namespace
+{
+ bool fusionIsTrivial(const ade::Graph &src_graph)
+ {
+ // Fusion is considered trivial if there only one
+ // active backend and no user-defined islands
+ // FIXME:
+ // Also check the cases backend can't handle
+ // (e.x. GScalar connecting two fluid ops should split the graph)
+ const GModel::ConstGraph g(src_graph);
+ const auto& active_backends = g.metadata().get<ActiveBackends>().backends;
+ return active_backends.size() == 1 &&
+ ade::util::all_of(g.nodes(), [&](ade::NodeHandle nh) {
+ return !g.metadata(nh).contains<Island>();
+ });
+ }
+
+ void fuseTrivial(GIslandModel::Graph &g, const ade::Graph &src_graph)
+ {
+ const GModel::ConstGraph src_g(src_graph);
+
+ const auto& backend = *src_g.metadata().get<ActiveBackends>().backends.cbegin();
+ const auto& proto = src_g.metadata().get<Protocol>();
+ GIsland::node_set all, in_ops, out_ops;
+
+ all.insert(src_g.nodes().begin(), src_g.nodes().end());
+
+ for (const auto nh : proto.in_nhs)
+ {
+ all.erase(nh);
+ in_ops.insert(nh->outNodes().begin(), nh->outNodes().end());
+ }
+ for (const auto nh : proto.out_nhs)
+ {
+ all.erase(nh);
+ out_ops.insert(nh->inNodes().begin(), nh->inNodes().end());
+ }
+
+ auto isl = std::make_shared<GIsland>(backend,
+ std::move(all),
+ std::move(in_ops),
+ std::move(out_ops),
+ util::optional<std::string>{});
+
+ auto ih = GIslandModel::mkIslandNode(g, std::move(isl));
+
+ for (const auto nh : proto.in_nhs)
+ {
+ auto slot = GIslandModel::mkSlotNode(g, nh);
+ g.link(slot, ih);
+ }
+ for (const auto nh : proto.out_nhs)
+ {
+ auto slot = GIslandModel::mkSlotNode(g, nh);
+ g.link(ih, slot);
+ }
+ }
+
+ struct MergeContext
+ {
+ using CycleCausers = std::pair< std::shared_ptr<GIsland>,
+ std::shared_ptr<GIsland> >;
+
+ struct CycleHasher final
+ {
+ std::size_t operator()(const CycleCausers& p) const
+ {
+ std::size_t a = std::hash<GIsland*>()(p.first.get());
+ std::size_t b = std::hash<GIsland*>()(p.second.get());
+ return a ^ (b << 1);
+ }
+ };
+
+ // Set of Islands pairs which cause a cycle if merged.
+ // Every new merge produces a new Island, and if Islands were
+ // merged (and thus dropped from GIslandModel), the objects may
+ // still be alive as included into this set.
+ std::unordered_set<CycleCausers, CycleHasher> cycle_causers;
+ };
+
+ bool canMerge(const GIslandModel::Graph &g,
+ const ade::NodeHandle a_nh,
+ const ade::NodeHandle /*slot_nh*/,
+ const ade::NodeHandle b_nh,
+ const MergeContext &ctx = MergeContext())
+ {
+ auto a_ptr = g.metadata(a_nh).get<FusedIsland>().object;
+ auto b_ptr = g.metadata(b_nh).get<FusedIsland>().object;
+ GAPI_Assert(a_ptr.get());
+ GAPI_Assert(b_ptr.get());
+
+ // Islands with different affinity can't be merged
+ if (a_ptr->backend() != b_ptr->backend())
+ return false;
+
+ // Islands which cause a cycle can't be merged as well
+ // (since the flag is set, the procedure already tried to
+ // merge these islands in the past)
+ if (ade::util::contains(ctx.cycle_causers, std::make_pair(a_ptr, b_ptr))||
+ ade::util::contains(ctx.cycle_causers, std::make_pair(b_ptr, a_ptr)))
+ return false;
+
+ // There may be user-defined islands. Initially user-defined
+ // islands also are built from single operations and then merged
+ // by this procedure, but there is some exceptions.
+ // User-specified island can't be merged to an internal island
+ if ( ( a_ptr->is_user_specified() && !b_ptr->is_user_specified())
+ || (!a_ptr->is_user_specified() && b_ptr->is_user_specified()))
+ {
+ return false;
+ }
+ else if (a_ptr->is_user_specified() && b_ptr->is_user_specified())
+ {
+ // These islads are _different_ user-specified Islands
+ // FIXME: today it may only differ by name
+ if (a_ptr->name() != b_ptr->name())
+ return false;
+ }
+
+ // FIXME: add a backend-specified merge checker
+ return true;
+ }
+
+ inline bool isProducedBy(const ade::NodeHandle &slot,
+ const ade::NodeHandle &island)
+ {
+ // A data slot may have only 0 or 1 producer
+ if (slot->inNodes().size() == 0)
+ return false;
+
+ return slot->inNodes().front() == island;
+ }
+
+ inline bool isConsumedBy(const ade::NodeHandle &slot,
+ const ade::NodeHandle &island)
+ {
+ auto it = std::find_if(slot->outNodes().begin(),
+ slot->outNodes().end(),
+ [&](const ade::NodeHandle &nh) {
+ return nh == island;
+ });
+ return it != slot->outNodes().end();
+ }
+
+ /**
+ * Find a candidate Island for merge for the given Island nh.
+ *
+ * @param g Island Model where merge occurs
+ * @param nh GIsland node, either LHS or RHS of probable merge
+ * @param ctx Merge context, may contain some cached stuff to avoid
+ * double/triple/etc checking
+ * @return Tuple of Island handle, Data slot handle (which connects them),
+ * and a position of found handle with respect to nh (IN/OUT)
+ */
+ std::tuple<ade::NodeHandle, ade::NodeHandle, Direction>
+ findCandidate(const GIslandModel::Graph &g,
+ ade::NodeHandle nh,
+ const MergeContext &ctx = MergeContext())
+ {
+ using namespace std::placeholders;
+
+ // Find a first matching candidate GIsland for merge
+ // among inputs
+ for (const auto& input_data_nh : nh->inNodes())
+ {
+ if (input_data_nh->inNodes().size() != 0)
+ {
+ // Data node must have a single producer only
+ GAPI_DbgAssert(input_data_nh->inNodes().size() == 1);
+ auto input_data_prod_nh = input_data_nh->inNodes().front();
+ if (canMerge(g, input_data_prod_nh, input_data_nh, nh, ctx))
+ return std::make_tuple(input_data_prod_nh,
+ input_data_nh,
+ Direction::In);
+ }
+ } // for(inNodes)
+
+ // Ok, now try to find it among the outputs
+ for (const auto& output_data_nh : nh->outNodes())
+ {
+ auto mergeTest = [&](ade::NodeHandle cons_nh) -> bool {
+ return canMerge(g, nh, output_data_nh, cons_nh, ctx);
+ };
+ auto cand_it = std::find_if(output_data_nh->outNodes().begin(),
+ output_data_nh->outNodes().end(),
+ mergeTest);
+ if (cand_it != output_data_nh->outNodes().end())
+ return std::make_tuple(*cand_it,
+ output_data_nh,
+ Direction::Out);
+ } // for(outNodes)
+ // Empty handle, no good candidates
+ return std::make_tuple(ade::NodeHandle(),
+ ade::NodeHandle(),
+ Direction::Invalid);
+ }
+
+ // A cancellable merge of two GIslands, "a" and "b", connected via "slot"
+ class MergeAction
+ {
+ ade::Graph &m_g;
+ const ade::Graph &m_orig_g;
+ GIslandModel::Graph m_gim;
+ ade::NodeHandle m_prod;
+ ade::NodeHandle m_slot;
+ ade::NodeHandle m_cons;
+
+ Change::List m_changes;
+
+ struct MergeObjects
+ {
+ using NS = GIsland::node_set;
+ NS all; // same as in GIsland
+ NS in_ops; // same as in GIsland
+ NS out_ops; // same as in GIsland
+ NS opt_interim_slots; // can be dropped (optimized out)
+ NS non_opt_interim_slots;// can't be dropped (extern. link)
+ };
+ MergeObjects identify() const;
+
+ public:
+ MergeAction(ade::Graph &g,
+ const ade::Graph &orig_g,
+ ade::NodeHandle prod,
+ ade::NodeHandle slot,
+ ade::NodeHandle cons)
+ : m_g(g)
+ , m_orig_g(orig_g)
+ , m_gim(GIslandModel::Graph(m_g))
+ , m_prod(prod)
+ , m_slot(slot)
+ , m_cons(cons)
+ {
+ }
+
+ void tryMerge(); // Try to merge islands Prod and Cons
+ void rollback(); // Roll-back changes if merge has been done but broke the model
+ void commit(); // Fix changes in the model after successful merge
+ };
+
+ // Merge proceduce is a replacement of two Islands, Prod and Cons,
+ // connected via !Slot!, with a new Island, which contain all Prod
+ // nodes + all Cons nodes, and reconnected in the graph properly:
+ //
+ // Merge(Prod, !Slot!, Cons)
+ //
+ // [Slot 2]
+ // :
+ // v
+ // ... [Slot 0] -> Prod -> !Slot! -> Cons -> [Slot 3] -> ...
+ // ... [Slot 1] -' : '-> [Slot 4] -> ...
+ // V
+ // ...
+ // results into:
+ //
+ // ... [Slot 0] -> Merged -> [Slot 3] ...
+ // ... [Slot 1] : :-> [Slot 4] ...
+ // ... [Slot 2] ' '-> !Slot! ...
+ //
+ // The rules are the following:
+ // 1) All Prod input slots become Merged input slots;
+ // - Example: Slot 0 Slot 1
+ // 2) Any Cons input slots which come from Islands different to Prod
+ // also become Merged input slots;
+ // - Example: Slot 2
+ // 3) All Cons output slots become Merged output slots;
+ // - Example: Slot 3, Slot 4
+ // 4) All Prod output slots which are not consumed by Cons
+ // also become Merged output slots;
+ // - (not shown on the example)
+ // 5) If the !Slot! which connects Prod and Cons is consumed
+ // exclusively by Cons, it is optimized out (dropped) from the model;
+ // 6) If the !Slot! is used by consumers other by Cons, it
+ // becomes an extra output of Merged
+ // 7) !Slot! may be not the only connection between Prod and Cons,
+ // but as a result of merge operation, all such connections
+ // should be handles as described for !Slot!
+
+ MergeAction::MergeObjects MergeAction::identify() const
+ {
+ auto lhs = m_gim.metadata(m_prod).get<FusedIsland>().object;
+ auto rhs = m_gim.metadata(m_cons).get<FusedIsland>().object;
+
+ GIsland::node_set interim_slots;
+
+ GIsland::node_set merged_all(lhs->contents());
+ merged_all.insert(rhs->contents().begin(), rhs->contents().end());
+
+ GIsland::node_set merged_in_ops(lhs->in_ops()); // (1)
+ for (auto cons_in_slot_nh : m_cons->inNodes()) // (2)
+ {
+ if (isProducedBy(cons_in_slot_nh, m_prod))
+ {
+ interim_slots.insert(cons_in_slot_nh);
+ // at this point, interim_slots are not sync with merged_all
+ // (merged_all will be updated with interim_slots which
+ // will be optimized out).
+ }
+ else
+ {
+ const auto extra_in_ops = rhs->consumers(m_g, cons_in_slot_nh);
+ merged_in_ops.insert(extra_in_ops.begin(), extra_in_ops.end());
+ }
+ }
+
+ GIsland::node_set merged_out_ops(rhs->out_ops()); // (3)
+ for (auto prod_out_slot_nh : m_prod->outNodes()) // (4)
+ {
+ if (!isConsumedBy(prod_out_slot_nh, m_cons))
+ {
+ merged_out_ops.insert(lhs->producer(m_g, prod_out_slot_nh));
+ }
+ }
+
+ // (5,6,7)
+ GIsland::node_set opt_interim_slots;
+ GIsland::node_set non_opt_interim_slots;
+
+ auto is_non_opt = [&](const ade::NodeHandle &slot_nh) {
+ // If a data object associated with this slot is a part
+ // of GComputation _output_ protocol, it can't be optimzied out
+ const auto data_nh = m_gim.metadata(slot_nh).get<DataSlot>().original_data_node;
+ const auto &data = GModel::ConstGraph(m_orig_g).metadata(data_nh).get<Data>();
+ if (data.storage == Data::Storage::OUTPUT)
+ return true;
+
+ // Otherwise, a non-optimizeable data slot is the one consumed
+ // by some other island than "cons"
+ const auto it = std::find_if(slot_nh->outNodes().begin(),
+ slot_nh->outNodes().end(),
+ [&](ade::NodeHandle &&nh)
+ {return nh != m_cons;});
+ return it != slot_nh->outNodes().end();
+ };
+ for (auto slot_nh : interim_slots)
+ {
+ // Put all intermediate data nodes (which are BOTH optimized
+ // and not-optimized out) to Island contents.
+ merged_all.insert(m_gim.metadata(slot_nh)
+ .get<DataSlot>().original_data_node);
+
+ GIsland::node_set &dst = is_non_opt(slot_nh)
+ ? non_opt_interim_slots // there are consumers other than m_cons
+ : opt_interim_slots; // there's no consumers other than m_cons
+ dst.insert(slot_nh);
+ }
+
+ // (4+6).
+ // BTW, (4) could be "All Prod output slots read NOT ONLY by Cons"
+ for (auto non_opt_slot_nh : non_opt_interim_slots)
+ {
+ merged_out_ops.insert(lhs->producer(m_g, non_opt_slot_nh));
+ }
+ return MergeObjects{
+ merged_all, merged_in_ops, merged_out_ops,
+ opt_interim_slots, non_opt_interim_slots
+ };
+ }
+
+ // FIXME(DM): Probably this procedure will be refactored dramatically one day...
+ void MergeAction::tryMerge()
+ {
+ // _: Understand the contents and I/O connections of a new merged Island
+ MergeObjects mo = identify();
+ auto lhs_obj = m_gim.metadata(m_prod).get<FusedIsland>().object;
+ auto rhs_obj = m_gim.metadata(m_cons).get<FusedIsland>().object;
+ GAPI_Assert( ( lhs_obj->is_user_specified() && rhs_obj->is_user_specified())
+ || (!lhs_obj->is_user_specified() && !rhs_obj->is_user_specified()));
+ cv::util::optional<std::string> maybe_user_tag;
+ if (lhs_obj->is_user_specified() && rhs_obj->is_user_specified())
+ {
+ GAPI_Assert(lhs_obj->name() == rhs_obj->name());
+ maybe_user_tag = cv::util::make_optional(lhs_obj->name());
+ }
+
+ // A: Create a new Island and add it to the graph
+ auto backend = m_gim.metadata(m_prod).get<FusedIsland>()
+ .object->backend();
+ auto merged = std::make_shared<GIsland>(backend,
+ std::move(mo.all),
+ std::move(mo.in_ops),
+ std::move(mo.out_ops),
+ std::move(maybe_user_tag));
+ // FIXME: move this debugging to some user-controllable log-level
+#ifdef DEBUG_MERGE
+ merged->debug();
+#endif
+ auto new_nh = GIslandModel::mkIslandNode(m_gim, std::move(merged));
+ m_changes.enqueue<Change::NodeCreated>(new_nh);
+
+ // B: Disconnect all Prod's input Slots from Prod,
+ // connect it to Merged
+ std::vector<ade::EdgeHandle> input_edges(m_prod->inEdges().begin(),
+ m_prod->inEdges().end());
+ for (auto in_edge : input_edges)
+ {
+ m_changes.enqueue<Change::NewLink>(m_g, in_edge->srcNode(), new_nh);
+ m_changes.enqueue<Change::DropLink>(m_g, m_prod, in_edge);
+ }
+
+ // C: Disconnect all Cons' output Slots from Cons,
+ // connect it to Merged
+ std::vector<ade::EdgeHandle> output_edges(m_cons->outEdges().begin(),
+ m_cons->outEdges().end());
+ for (auto out_edge : output_edges)
+ {
+ m_changes.enqueue<Change::NewLink>(m_g, new_nh, out_edge->dstNode());
+ m_changes.enqueue<Change::DropLink>(m_g, m_cons, out_edge);
+ }
+
+ // D: Process the intermediate slots (betweed Prod n Cons).
+ // D/1 - Those which are optimized out are just removed from the model
+ for (auto opt_slot_nh : mo.opt_interim_slots)
+ {
+ GAPI_Assert(1 == opt_slot_nh->inNodes().size() );
+ GAPI_Assert(m_prod == opt_slot_nh->inNodes().front());
+
+ std::vector<ade::EdgeHandle> edges_to_drop;
+ ade::util::copy(ade::util::chain(opt_slot_nh->inEdges(),
+ opt_slot_nh->outEdges()),
+ std::back_inserter(edges_to_drop));
+ for (auto eh : edges_to_drop)
+ {
+ m_changes.enqueue<Change::DropLink>(m_g, opt_slot_nh, eh);
+ }
+ m_changes.enqueue<Change::DropNode>(opt_slot_nh);
+ }
+ // D/2 - Those which are used externally are connected to new nh
+ // as outputs.
+ for (auto non_opt_slot_nh : mo.non_opt_interim_slots)
+ {
+ GAPI_Assert(1 == non_opt_slot_nh->inNodes().size() );
+ GAPI_Assert(m_prod == non_opt_slot_nh->inNodes().front());
+ m_changes.enqueue<Change::DropLink>(m_g, non_opt_slot_nh,
+ non_opt_slot_nh->inEdges().front());
+
+ std::vector<ade::EdgeHandle> edges_to_probably_drop
+ (non_opt_slot_nh->outEdges().begin(),
+ non_opt_slot_nh->outEdges().end());;
+ for (auto eh : edges_to_probably_drop)
+ {
+ if (eh->dstNode() == m_cons)
+ {
+ // drop only edges to m_cons, as there's other consumers
+ m_changes.enqueue<Change::DropLink>(m_g, non_opt_slot_nh, eh);
+ }
+ }
+ m_changes.enqueue<Change::NewLink>(m_g, new_nh, non_opt_slot_nh);
+ }
+
+ // E. All Prod's output edges which are directly related to Merge (e.g.
+ // connected to Cons) were processed on step (D).
+ // Relink the remaining output links
+ std::vector<ade::EdgeHandle> prod_extra_out_edges
+ (m_prod->outEdges().begin(),
+ m_prod->outEdges().end());
+ for (auto extra_out : prod_extra_out_edges)
+ {
+ m_changes.enqueue<Change::NewLink>(m_g, new_nh, extra_out->dstNode());
+ m_changes.enqueue<Change::DropLink>(m_g, m_prod, extra_out);
+ }
+
+ // F. All Cons' input edges which are directly related to merge (e.g.
+ // connected to Prod) were processed on step (D) as well,
+ // remaining should become Merged island's input edges
+ std::vector<ade::EdgeHandle> cons_extra_in_edges
+ (m_cons->inEdges().begin(),
+ m_cons->inEdges().end());
+ for (auto extra_in : cons_extra_in_edges)
+ {
+ m_changes.enqueue<Change::NewLink>(m_g, extra_in->srcNode(), new_nh);
+ m_changes.enqueue<Change::DropLink>(m_g, m_cons, extra_in);
+ }
+
+ // G. Finally, drop the original Island nodes. DropNode() does
+ // the sanity check for us (both nodes should have 0 edges).
+ m_changes.enqueue<Change::DropNode>(m_prod);
+ m_changes.enqueue<Change::DropNode>(m_cons);
+ }
+
+ void MergeAction::rollback()
+ {
+ m_changes.rollback(m_g);
+ }
+ void MergeAction::commit()
+ {
+ m_changes.commit(m_g);
+ }
+
+#ifdef DEBUG_MERGE
+ void merge_debug(const ade::Graph &g, int iteration)
+ {
+ std::stringstream filename;
+ filename << "fusion_" << static_cast<const void*>(&g)
+ << "_" << std::setw(4) << std::setfill('0') << iteration
+ << ".dot";
+ std::ofstream ofs(filename.str());
+ passes::dumpDot(g, ofs);
+ }
+#endif
+
+ void fuseGeneral(ade::Graph& im, const ade::Graph& g)
+ {
+ GIslandModel::Graph gim(im);
+ MergeContext mc;
+
+ bool there_was_a_merge = false;
+ std::size_t iteration = 0u;
+ do
+ {
+ there_was_a_merge = false;
+
+ // FIXME: move this debugging to some user-controllable log level
+ #ifdef DEBUG_MERGE
+ GAPI_LOG_INFO(NULL, "Before next merge attempt " << iteration << "...");
+ merge_debug(g, iteration);
+ #endif
+ iteration++;
+ auto sorted = pass_helpers::topoSort(im);
+ for (auto nh : sorted)
+ {
+ if (NodeKind::ISLAND == gim.metadata(nh).get<NodeKind>().k)
+ {
+ ade::NodeHandle cand_nh;
+ ade::NodeHandle cand_slot;
+ Direction dir = Direction::Invalid;
+ std::tie(cand_nh, cand_slot, dir) = findCandidate(gim, nh, mc);
+ if (cand_nh != nullptr && dir != Direction::Invalid)
+ {
+ auto lhs_nh = (dir == Direction::In ? cand_nh : nh);
+ auto rhs_nh = (dir == Direction::Out ? cand_nh : nh);
+
+ auto l_obj = gim.metadata(lhs_nh).get<FusedIsland>().object;
+ auto r_obj = gim.metadata(rhs_nh).get<FusedIsland>().object;
+ GAPI_LOG_INFO(NULL, r_obj->name() << " can be merged into " << l_obj->name());
+ // Try to do a merge. If merge was succesfull, check if the
+ // graph have cycles (cycles are prohibited at this point).
+ // If there are cycles, roll-back the merge and mark a pair of
+ // these Islands with a special tag - "cycle-causing".
+ MergeAction action(im, g, lhs_nh, cand_slot, rhs_nh);
+ action.tryMerge();
+ if (pass_helpers::hasCycles(im))
+ {
+ GAPI_LOG_INFO(NULL,
+ "merge(" << l_obj->name() << "," << r_obj->name() <<
+ ") caused cycle, rolling back...");
+ action.rollback();
+ // don't try to merge these two islands next time (findCandidate will use that)
+ mc.cycle_causers.insert({l_obj, r_obj});
+ }
+ else
+ {
+ GAPI_LOG_INFO(NULL,
+ "merge(" << l_obj->name() << "," << r_obj->name() <<
+ ") was successful!");
+ action.commit();
+ #ifdef DEBUG_MERGE
+ GIslandModel::syncIslandTags(gim, g);
+ #endif
+ there_was_a_merge = true;
+ break; // start do{}while from the beginning
+ }
+ } // if(can merge)
+ } // if(ISLAND)
+ } // for(all nodes)
+ }
+ while (there_was_a_merge);
+ }
+} // anonymous namespace
+
+void passes::fuseIslands(ade::passes::PassContext &ctx)
+{
+ std::shared_ptr<ade::Graph> gptr(new ade::Graph);
+ GIslandModel::Graph gim(*gptr);
+
+ if (fusionIsTrivial(ctx.graph))
+ {
+ fuseTrivial(gim, ctx.graph);
+ }
+ else
+ {
+ GIslandModel::generateInitial(gim, ctx.graph);
+ fuseGeneral(*gptr.get(), ctx.graph);
+ }
+ GModel::Graph(ctx.graph).metadata().set(IslandModel{std::move(gptr)});
+}
+
+void passes::syncIslandTags(ade::passes::PassContext &ctx)
+{
+ GModel::Graph gm(ctx.graph);
+ std::shared_ptr<ade::Graph> gptr(gm.metadata().get<IslandModel>().model);
+ GIslandModel::Graph gim(*gptr);
+ GIslandModel::syncIslandTags(gim, ctx.graph);
+}
+}} // namespace cv::gimpl
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/helpers.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/helpers.cpp
new file mode 100644
index 000000000..60bf36afd
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/helpers.cpp
@@ -0,0 +1,122 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <algorithm> // copy
+#include <unordered_map>
+#include <unordered_set>
+
+#include <ade/util/filter_range.hpp>
+
+#include "opencv2/gapi/own/assert.hpp" // GAPI_Assert
+#include "compiler/passes/helpers.hpp"
+
+namespace {
+namespace Cycles
+{
+ // FIXME: This code is taken directly from ADE.
+ // export a bool(ade::Graph) function with pass instead
+ enum class TraverseState
+ {
+ visiting,
+ visited,
+ };
+ using state_t = std::unordered_map<ade::Node*, TraverseState>;
+
+ bool inline checkCycle(state_t& state, const ade::NodeHandle& node)
+ {
+ GAPI_Assert(nullptr != node);
+ state[node.get()] = TraverseState::visiting;
+ for (auto adj: node->outNodes())
+ {
+ auto it = state.find(adj.get());
+ if (state.end() == it) // not visited
+ {
+ // FIXME: use std::stack instead on-stack recursion
+ if (checkCycle(state, adj))
+ {
+ return true; // detected! (deeper frame)
+ }
+ }
+ else if (TraverseState::visiting == it->second)
+ {
+ return true; // detected! (this frame)
+ }
+ }
+ state[node.get()] = TraverseState::visited;
+ return false; // not detected
+ }
+
+ bool inline hasCycles(const ade::Graph &graph)
+ {
+ state_t state;
+ bool detected = false;
+ for (auto node: graph.nodes())
+ {
+ if (state.end() == state.find(node.get()))
+ {
+ // not yet visited during recursion
+ detected |= checkCycle(state, node);
+ if (detected) break;
+ }
+ }
+ return detected;
+ }
+} // namespace Cycles
+
+namespace TopoSort
+{
+ using sorted_t = std::vector<ade::NodeHandle>;
+ using visited_t = std::unordered_set<ade::Node*>;
+
+ struct NonEmpty final
+ {
+ bool operator()(const ade::NodeHandle& node) const
+ {
+ return nullptr != node;
+ }
+ };
+
+ void inline visit(sorted_t& sorted, visited_t& visited, const ade::NodeHandle& node)
+ {
+ if (visited.end() == visited.find(node.get()))
+ {
+ for (auto adj: node->inNodes())
+ {
+ visit(sorted, visited, adj);
+ }
+ sorted.push_back(node);
+ visited.insert(node.get());
+ }
+ }
+
+ sorted_t inline topoSort(const ade::Graph &g)
+ {
+ sorted_t sorted;
+ visited_t visited;
+ for (auto node: g.nodes())
+ {
+ visit(sorted, visited, node);
+ }
+
+ auto r = ade::util::filter<NonEmpty>(ade::util::toRange(sorted));
+ return sorted_t(r.begin(), r.end());
+ }
+} // namespace TopoSort
+
+} // anonymous namespace
+
+bool cv::gimpl::pass_helpers::hasCycles(const ade::Graph &g)
+{
+ return Cycles::hasCycles(g);
+}
+
+std::vector<ade::NodeHandle> cv::gimpl::pass_helpers::topoSort(const ade::Graph &g)
+{
+ return TopoSort::topoSort(g);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/helpers.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/helpers.hpp
new file mode 100644
index 000000000..3aa18e627
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/helpers.hpp
@@ -0,0 +1,31 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_COMPILER_PASSES_HELPERS_HPP
+#define OPENCV_GAPI_COMPILER_PASSES_HELPERS_HPP
+
+// FIXME: DROP THIS and REUSE ADE utilities
+// (which serve as passes already but are not exposed as standalone functions)
+
+#include <vector>
+
+#include <ade/passes/pass_base.hpp>
+#include <ade/node.hpp> // FIXME: Forward declarations instead?
+#include <ade/graph.hpp>
+
+namespace cv {
+namespace gimpl {
+namespace pass_helpers {
+
+bool hasCycles(const ade::Graph &graph);
+std::vector<ade::NodeHandle> topoSort(const ade::Graph &graph);
+
+} // namespace pass_helpers
+} // namespace gimpl
+} // name
+
+#endif // OPENCV_GAPI_COMPILER_PASSES_HELPERS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/islands.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/islands.cpp
new file mode 100644
index 000000000..942f738bd
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/islands.cpp
@@ -0,0 +1,233 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <sstream>
+#include <stack>
+#include <ade/util/chain_range.hpp>
+#include <ade/graph.hpp>
+
+#include "compiler/gmodel.hpp"
+#include "compiler/passes/passes.hpp"
+
+namespace
+{
+ bool is_within_same_island(const cv::gimpl::GModel::Graph &gr,
+ const ade::NodeHandle &dataNode,
+ const std::string &island)
+ {
+ // A data node is within the same island as it's reader node
+ // if and only if data object's producer island (if there's a producer)
+ // is the same as the specified one.
+ //
+ // An object may have only a single producer, but multiple consumers,
+ // and these consumers may be assigned to different Islands.
+ // Since "initIslands" traversal direction is op-to-args, i.e. reverse,
+ // a single Data object may be visited twice during Islands initialization.
+ //
+ // In this case, Data object is part of Island A if and only if:
+ // - Data object's producer is part of Island A,
+ // - AND any of Data obejct's consumers is part of Island A.
+ //
+ // Op["island0"] --> Data[ ? ] --> Op["island0"]
+ // :
+ // '---------> Op["island1"]
+ //
+ // In the above example, Data object is assigned to "island0" as
+ // it is surrounded by operations assigned to "island0"
+
+ using namespace cv::gimpl;
+
+ if ( gr.metadata(dataNode).contains<Island>()
+ && gr.metadata(dataNode).get<Island>().island != island)
+ return false;
+
+ if (dataNode->inNodes().empty())
+ return false;
+
+ GAPI_Assert(dataNode->inNodes().size() == 1u);
+ const auto prod_h = dataNode->inNodes().front();
+
+ // FIXME: ADE should have something like get_or<> or get<>(default)
+ GAPI_Assert(gr.metadata(prod_h).get<NodeType>().t == NodeType::OP);
+ return ( gr.metadata(prod_h).contains<Island>()
+ && gr.metadata(prod_h).get<Island>().island == island)
+ && (ade::util::any_of(dataNode->outNodes(), [&](ade::NodeHandle cons_h)
+ {
+ return ( gr.metadata(cons_h).contains<Island>()
+ && gr.metadata(cons_h).get<Island>().island == island);
+ }));
+ }
+} // anonymous namespace
+
+// Initially only Operations have Island tag. This pass adds Island tag
+// to all data objects within an Island.
+// A data object is considered within an Island if and only if
+// its reader and writer are assigned to this Island (see above).
+void cv::gimpl::passes::initIslands(ade::passes::PassContext &ctx)
+{
+ GModel::Graph gr(ctx.graph);
+ for (const auto &nh : gr.nodes())
+ {
+ if (gr.metadata(nh).get<NodeType>().t == NodeType::OP)
+ {
+ if (gr.metadata(nh).contains<Island>())
+ {
+ const auto island = gr.metadata(nh).get<Island>().island;
+
+ // It is enough to check only input nodes
+ for (const auto &in_data_node : nh->inNodes())
+ {
+ if (is_within_same_island(gr, in_data_node, island))
+ {
+ gr.metadata(in_data_node).set(Island{island});
+ }
+ } // for(in_data_node)
+ } // if (contains<Island>)
+ } // if (OP)
+ } // for (nodes)
+}
+
+// There should be no multiple (disconnected) islands with the same name.
+// This may occur if user assigns the same islands name to multiple ranges
+// in the graph.
+// FIXME: How it could be avoided on an earlier stage?
+void cv::gimpl::passes::checkIslands(ade::passes::PassContext &ctx)
+{
+ GModel::ConstGraph gr(ctx.graph);
+
+ // The algorithm is teh following:
+ //
+ // 1. Put all Tagged nodes (both Operations and Data) into a set
+ // 2. Initialize Visited set as (empty)
+ // 3. Initialize Traversal stack as (empty)
+ // 4. Initialize Islands map (String -> Integer) as (empty)
+ // 5. For every Tagged node from a set
+ // a. Skip if it is Visited
+ // b. For every input/output node:
+ // * if it is tagged with the same island:
+ // - add it to Traversal stack
+ // - remove from Tagged nodes if it is t
+ // c. While (stack is not empty):
+ // - Take a node from Stack
+ // - Repeat (b)
+ // d. Increment Islands map [this island] by 1
+ //
+ //
+ // If whatever Island has counter is more than 1, it is a disjoint
+ // one (i.e. there's two islands with the same name).
+
+ using node_set = std::unordered_set
+ < ade::NodeHandle
+ , ade::HandleHasher<ade::Node>
+ >;
+ node_set tagged_nodes;
+ node_set visited_tagged_nodes;
+ std::unordered_map<std::string, int> island_counters;
+
+ for (const auto &nh : gr.nodes())
+ {
+ if (gr.metadata(nh).contains<Island>())
+ {
+ tagged_nodes.insert(nh);
+ island_counters[gr.metadata(nh).get<Island>().island] = 0;
+ }
+ }
+
+ // Make a copy to allow list modifications during traversal
+ for (const auto &tagged_nh : tagged_nodes)
+ {
+ if (visited_tagged_nodes.end() != ade::util::find(visited_tagged_nodes, tagged_nh))
+ continue;
+
+ // Run the recursive traversal process as described in 5/a-d.
+ // This process is like a flood-fill traversal for island.
+ // If there's to distint successful flood-fills happened for the same island
+ // name, there are two islands with this name.
+ std::stack<ade::NodeHandle> stack;
+ stack.push(tagged_nh);
+
+ while (!stack.empty())
+ {
+ const auto this_nh = stack.top();
+ stack.pop();
+
+ // Since _this_ node is visited, it is a part of processed island
+ // so mark it as visited to skip in other recursive processes
+ visited_tagged_nodes.insert(this_nh);
+
+ GAPI_DbgAssert(gr.metadata(this_nh).contains<Island>());
+ GAPI_DbgAssert( gr.metadata(this_nh ).get<Island>().island
+ == gr.metadata(tagged_nh).get<Island>().island);
+ const auto &this_island = gr.metadata(this_nh).get<Island>().island;
+
+ for (const auto neighbor_nh : ade::util::chain(this_nh->inNodes(), this_nh->outNodes()))
+ {
+ if ( gr.metadata(neighbor_nh).contains<Island>()
+ && gr.metadata(neighbor_nh).get<Island>().island == this_island
+ && !visited_tagged_nodes.count(neighbor_nh))
+ {
+ stack.push(neighbor_nh);
+ }
+ } // for (neighbor)
+ } // while (stack)
+
+ // Flood-fill is over, now increment island counter for this island
+ island_counters[gr.metadata(tagged_nh).get<Island>().island]++;
+ } // for(tagged)
+
+ bool check_failed = false;
+ std::stringstream ss;
+ for (const auto &ic : island_counters)
+ {
+ GAPI_Assert(ic.second > 0);
+ if (ic.second > 1)
+ {
+ check_failed = true;
+ ss << "\"" << ic.first << "\"(" << ic.second << ") ";
+ }
+ }
+ if (check_failed)
+ {
+ util::throw_error
+ (std::logic_error("There are multiple distinct islands "
+ "with the same name: [" + ss.str() + "], "
+ "please check your cv::gapi::island() parameters!"));
+ }
+}
+
+void cv::gimpl::passes::checkIslandsContent(ade::passes::PassContext &ctx)
+{
+ GModel::ConstGraph gr(ctx.graph);
+ std::unordered_map<std::string, cv::gapi::GBackend> backends_of_islands;
+ for (const auto& nh : gr.nodes())
+ {
+ if (NodeType::OP == gr.metadata(nh).get<NodeType>().t &&
+ gr.metadata(nh).contains<Island>())
+ {
+ const auto island = gr.metadata(nh).get<Island>().island;
+ auto island_backend_it = backends_of_islands.find(island);
+ const auto& op = gr.metadata(nh).get<Op>();
+
+ if (island_backend_it != backends_of_islands.end())
+ {
+ // Check that backend of the operation coincides with the backend of the island
+ // Backend of the island is determined by the backend of the first operation from this island
+ if (island_backend_it->second != op.backend)
+ {
+ util::throw_error(std::logic_error(island + " contains kernels " + op.k.name +
+ " with different backend"));
+ }
+ }
+ else
+ {
+ backends_of_islands.emplace(island, op.backend);
+ }
+ }
+ }
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/kernels.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/kernels.cpp
new file mode 100644
index 000000000..2703149e7
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/kernels.cpp
@@ -0,0 +1,157 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <ade/util/zip_range.hpp> // util::indexed
+#include <ade/graph.hpp>
+#include <ade/passes/check_cycles.hpp>
+
+#include "opencv2/gapi/gcompoundkernel.hpp" // compound::backend()
+
+#include "compiler/gmodel.hpp"
+#include "compiler/passes/passes.hpp"
+
+#include "api/gbackend_priv.hpp"
+#include "backends/common/gbackend.hpp"
+#include "compiler/gmodelbuilder.hpp"
+#include "logger.hpp" // GAPI_LOG
+
+namespace
+{
+ struct ImplInfo
+ {
+ cv::GKernelImpl impl;
+ cv::GArgs in_args;
+ };
+
+ // Generaly the algorithm is following
+ //
+ // 1. Get GCompoundKernel implementation
+ // 2. Create GCompoundContext
+ // 3. Run GCompoundKernel with GCompoundContext
+ // 4. Build subgraph from imputs/outputs GCompoundKernel
+ // 5. Replace compound node to subgraph
+
+ void expand(ade::Graph& g, ade::NodeHandle nh, const ImplInfo& impl_info)
+ {
+ cv::gimpl::GModel::Graph gr(g);
+ auto compound_impl = cv::util::any_cast<cv::detail::GCompoundKernel>(impl_info.impl.opaque);
+
+ // GCompoundContext instantiates its own objects
+ // in accordance with the RcDescs from in_args
+ cv::detail::GCompoundContext context(impl_info.in_args);
+ compound_impl.apply(context);
+
+ cv::GProtoArgs ins, outs;
+ ins.reserve(context.m_args.size());
+ outs.reserve(context.m_results.size());
+
+ // Inputs can be non-dynamic types.
+ // Such inputs are not used when building a graph
+ for (const auto& arg : context.m_args)
+ {
+ if (cv::gimpl::proto::is_dynamic(arg))
+ {
+ ins.emplace_back(cv::gimpl::proto::rewrap(arg));
+ }
+ }
+
+ ade::util::transform(context.m_results, std::back_inserter(outs), &cv::gimpl::proto::rewrap);
+
+ cv::gimpl::GModelBuilder builder(g);
+
+ // Build the subgraph graph which will need to replace the compound node
+ const auto& proto_slots = builder.put(ins, outs);
+
+ const auto& in_nhs = std::get<2>(proto_slots);
+ const auto& out_nhs = std::get<3>(proto_slots);
+
+ auto sorted_in_nhs = cv::gimpl::GModel::orderedInputs(gr, nh);
+ auto sorted_out_nhs = cv::gimpl::GModel::orderedOutputs(gr, nh);
+
+ // Reconnect expanded kernels from graph data objects
+ // to subgraph data objects, then drop that graph data objects
+ for (const auto& it : ade::util::zip(in_nhs, sorted_in_nhs))
+ {
+ const auto& subgr_in_nh = std::get<0>(it);
+ const auto& comp_in_nh = std::get<1>(it);
+
+ cv::gimpl::GModel::redirectReaders(gr, subgr_in_nh, comp_in_nh);
+ gr.erase(subgr_in_nh);
+ }
+
+ gr.erase(nh);
+
+ for (const auto& it : ade::util::zip(out_nhs, sorted_out_nhs))
+ {
+ const auto& subgr_out_nh = std::get<0>(it);
+ const auto& comp_out_nh = std::get<1>(it);
+
+ cv::gimpl::GModel::redirectWriter(gr, subgr_out_nh, comp_out_nh);
+ gr.erase(subgr_out_nh);
+ }
+ }
+}
+// This pass, given the kernel package, selects a kernel implementation
+// for every operation in the graph
+void cv::gimpl::passes::resolveKernels(ade::passes::PassContext &ctx,
+ const gapi::GKernelPackage &kernels,
+ const gapi::GLookupOrder &order)
+{
+ std::unordered_set<cv::gapi::GBackend> active_backends;
+
+ GModel::Graph gr(ctx.graph);
+ for (const auto &nh : gr.nodes())
+ {
+ if (gr.metadata(nh).get<NodeType>().t == NodeType::OP)
+ {
+ auto &op = gr.metadata(nh).get<Op>();
+ cv::gapi::GBackend selected_backend;
+ cv::GKernelImpl selected_impl;
+ std::tie(selected_backend, selected_impl)
+ = kernels.lookup(op.k.name, order);
+
+ selected_backend.priv().unpackKernel(ctx.graph, nh, selected_impl);
+ op.backend = selected_backend;
+ active_backends.insert(selected_backend);
+ }
+ }
+ gr.metadata().set(ActiveBackends{active_backends});
+}
+
+void cv::gimpl::passes::expandKernels(ade::passes::PassContext &ctx, const gapi::GKernelPackage &kernels)
+{
+ GModel::Graph gr(ctx.graph);
+
+ // Repeat the loop while there are compound kernels.
+ // Restart procedure after every successfull unrolling
+ bool has_compound_kernel = true;
+ while (has_compound_kernel)
+ {
+ has_compound_kernel = false;
+ for (const auto& nh : gr.nodes())
+ {
+ if (gr.metadata(nh).get<NodeType>().t == NodeType::OP)
+ {
+ const auto& op = gr.metadata(nh).get<Op>();
+
+ cv::gapi::GBackend selected_backend;
+ cv::GKernelImpl selected_impl;
+ std::tie(selected_backend, selected_impl) = kernels.lookup(op.k.name);
+
+ if (selected_backend == cv::gapi::compound::backend())
+ {
+ has_compound_kernel = true;
+ expand(ctx.graph, nh, ImplInfo{selected_impl, op.args});
+ break;
+ }
+ }
+ }
+ }
+ GAPI_LOG_INFO(NULL, "Final graph: " << ctx.graph.nodes().size() << " nodes" << std::endl);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/meta.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/meta.cpp
new file mode 100644
index 000000000..528d84ce8
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/meta.cpp
@@ -0,0 +1,125 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <ade/util/zip_range.hpp> // util::indexed
+#include <ade/graph.hpp>
+#include <ade/passes/check_cycles.hpp>
+
+#include "compiler/gmodel.hpp"
+#include "compiler/passes/passes.hpp"
+#include "logger.hpp" // GAPI_LOG
+
+
+// Iterate over all nodes and initialize meta of objects taken from the
+// outside (i.e., computation input/output arguments)
+void cv::gimpl::passes::initMeta(ade::passes::PassContext &ctx, const GMetaArgs &metas)
+{
+ GModel::Graph gr(ctx.graph);
+
+ const auto &proto = gr.metadata().get<Protocol>();
+
+ for (const auto& it : ade::util::indexed(proto.in_nhs))
+ {
+ auto& data = gr.metadata(ade::util::value(it)).get<Data>();
+ data.meta = metas.at(ade::util::index(it));
+ }
+}
+
+// Iterate over all operations in the topological order, trigger kernels
+// validate() function, update output objects metadata.
+void cv::gimpl::passes::inferMeta(ade::passes::PassContext &ctx, bool meta_is_initialized)
+{
+ // FIXME: ADE pass dependency on topo_sort?
+ // FIXME: ADE pass dependency on initMeta?
+ GModel::Graph gr(ctx.graph);
+
+ const auto sorted = gr.metadata().get<ade::passes::TopologicalSortData>() ;
+ for (const auto &nh : sorted.nodes())
+ {
+ if (gr.metadata(nh).get<NodeType>().t == NodeType::OP)
+ {
+ const auto& op = gr.metadata(nh).get<Op>();
+ GAPI_Assert(op.k.outMeta != nullptr);
+
+ // Prepare operation's input metadata vector
+ // Note that it's size is usually different from nh.inEdges.size(),
+ // and its element count is equal to operation's arguments count.
+ GMetaArgs input_meta_args(op.args.size());
+
+ // Iterate through input edges, update input_meta_args's slots
+ // appropriately. Not all of them will be updated due to (see above).
+ GAPI_Assert(nh->inEdges().size() > 0);
+ for (const auto &in_eh : nh->inEdges())
+ {
+ const auto& input_port = gr.metadata(in_eh).get<Input>().port;
+ const auto& input_nh = in_eh->srcNode();
+ GAPI_Assert(gr.metadata(input_nh).get<NodeType>().t == NodeType::DATA);
+
+ const auto& input_meta = gr.metadata(input_nh).get<Data>().meta;
+ if (util::holds_alternative<util::monostate>(input_meta))
+ {
+ // No meta in an input argument - a fatal error
+ // (note graph is traversed here in topoligcal order)
+ util::throw_error(std::logic_error("Fatal: input object's metadata "
+ "not found!"));
+ // FIXME: Add more details!!!
+ }
+ input_meta_args.at(input_port) = input_meta;
+ }
+ // Now ask kernel for it's output meta.
+ // Resulting out_args may have a larger size than op.outs, since some
+ // outputs could stay unused (unconnected)
+ const auto& out_metas = op.k.outMeta(input_meta_args, op.args);
+
+ // Walk through operation's outputs, update meta of output objects
+ // appropriately
+ GAPI_Assert(nh->outEdges().size() > 0);
+ for (const auto &out_eh : nh->outEdges())
+ {
+ const auto &output_port = gr.metadata(out_eh).get<Output>().port;
+ const auto &output_nh = out_eh->dstNode();
+ GAPI_Assert(gr.metadata(output_nh).get<NodeType>().t == NodeType::DATA);
+
+ auto &output_meta = gr.metadata(output_nh).get<Data>().meta;
+ if (!meta_is_initialized && !util::holds_alternative<util::monostate>(output_meta))
+ {
+ GAPI_LOG_INFO(NULL,
+ "!!! Output object has an initialized meta - "
+ "how it is possible today?" << std::endl; );
+ if (output_meta != out_metas.at(output_port))
+ {
+ util::throw_error(std::logic_error("Fatal: meta mismatch"));
+ // FIXME: New exception type?
+ // FIXME: More details!
+ }
+ }
+ // Store meta in graph
+ output_meta = out_metas.at(output_port);
+ }
+ } // if(OP)
+ } // for(sorted)
+}
+
+// After all metadata in graph is infered, store a vector of inferred metas
+// for computation output values.
+void cv::gimpl::passes::storeResultingMeta(ade::passes::PassContext &ctx)
+{
+ GModel::Graph gr(ctx.graph);
+
+ const auto &proto = gr.metadata().get<Protocol>();
+ GMetaArgs output_metas(proto.out_nhs.size());
+
+ for (const auto& it : ade::util::indexed(proto.out_nhs))
+ {
+ auto& data = gr.metadata(ade::util::value(it)).get<Data>();
+ output_metas[ade::util::index(it)] = data.meta;
+ }
+
+ gr.metadata().set(OutputMeta{output_metas});
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/passes.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/passes.hpp
new file mode 100644
index 000000000..14f6acdc0
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/passes/passes.hpp
@@ -0,0 +1,58 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_COMPILER_PASSES_HPP
+#define OPENCV_GAPI_COMPILER_PASSES_HPP
+
+#include <ostream>
+#include <ade/passes/pass_base.hpp>
+
+#include "opencv2/gapi/garg.hpp"
+#include "opencv2/gapi/gcommon.hpp"
+
+// Forward declarations - external
+namespace ade {
+ class Graph;
+
+ namespace passes {
+ struct PassContext;
+ }
+}
+
+namespace cv {
+
+namespace gimpl { namespace passes {
+
+void dumpDot(const ade::Graph &g, std::ostream& os);
+void dumpDot(ade::passes::PassContext &ctx, std::ostream& os);
+void dumpDotStdout(ade::passes::PassContext &ctx);
+void dumpGraph(ade::passes::PassContext &ctx, const std::string& dump_path);
+void dumpDotToFile(ade::passes::PassContext &ctx, const std::string& dump_path);
+
+void initIslands(ade::passes::PassContext &ctx);
+void checkIslands(ade::passes::PassContext &ctx);
+void checkIslandsContent(ade::passes::PassContext &ctx);
+
+void initMeta(ade::passes::PassContext &ctx, const GMetaArgs &metas);
+void inferMeta(ade::passes::PassContext &ctx, bool meta_is_initialized);
+void storeResultingMeta(ade::passes::PassContext &ctx);
+
+void expandKernels(ade::passes::PassContext &ctx,
+ const gapi::GKernelPackage& kernels);
+
+void resolveKernels(ade::passes::PassContext &ctx,
+ const gapi::GKernelPackage &kernels,
+ const gapi::GLookupOrder &order);
+
+void fuseIslands(ade::passes::PassContext &ctx);
+void syncIslandTags(ade::passes::PassContext &ctx);
+
+}} // namespace gimpl::passes
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_COMPILER_PASSES_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/transactions.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/transactions.hpp
new file mode 100644
index 000000000..54af8a6e6
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/compiler/transactions.hpp
@@ -0,0 +1,147 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_COMPILER_TRANSACTIONS_HPP
+#define OPENCV_GAPI_COMPILER_TRANSACTIONS_HPP
+
+#include <algorithm> // find_if
+#include <functional>
+#include <list>
+
+#include <ade/graph.hpp>
+
+#include "opencv2/gapi/own/assert.hpp"
+
+enum class Direction: int {Invalid, In, Out};
+
+////////////////////////////////////////////////////////////////////////////
+////
+// TODO: Probably it can be moved to ADE
+
+namespace Change
+{
+ struct Base
+ {
+ virtual void commit (ade::Graph & ) {};
+ virtual void rollback(ade::Graph & ) {};
+ virtual ~Base() = default;
+ };
+
+ class NodeCreated final: public Base
+ {
+ ade::NodeHandle m_node;
+ public:
+ explicit NodeCreated(const ade::NodeHandle &nh) : m_node(nh) {}
+ virtual void rollback(ade::Graph &g) override { g.erase(m_node); }
+ };
+
+ // NB: Drops all metadata stored in the EdgeHandle,
+ // which is not restored even in the rollback
+
+ // FIXME: either add a way for users to preserve meta manually
+ // or extend ADE to manipulate with meta such way
+ class DropLink final: public Base
+ {
+ ade::NodeHandle m_node;
+ Direction m_dir;
+
+ ade::NodeHandle m_sibling;
+
+ public:
+ DropLink(ade::Graph &g,
+ const ade::NodeHandle &node,
+ const ade::EdgeHandle &edge)
+ : m_node(node), m_dir(node == edge->srcNode()
+ ? Direction::Out
+ : Direction::In)
+ {
+ m_sibling = (m_dir == Direction::In
+ ? edge->srcNode()
+ : edge->dstNode());
+ g.erase(edge);
+ }
+
+ virtual void rollback(ade::Graph &g) override
+ {
+ switch(m_dir)
+ {
+ case Direction::In: g.link(m_sibling, m_node); break;
+ case Direction::Out: g.link(m_node, m_sibling); break;
+ default: GAPI_Assert(false);
+ }
+ }
+ };
+
+ class NewLink final: public Base
+ {
+ ade::EdgeHandle m_edge;
+
+ public:
+ NewLink(ade::Graph &g,
+ const ade::NodeHandle &prod,
+ const ade::NodeHandle &cons)
+ : m_edge(g.link(prod, cons))
+ {
+ }
+
+ virtual void rollback(ade::Graph &g) override
+ {
+ g.erase(m_edge);
+ }
+ };
+
+ class DropNode final: public Base
+ {
+ ade::NodeHandle m_node;
+
+ public:
+ explicit DropNode(const ade::NodeHandle &nh)
+ : m_node(nh)
+ {
+ // According to the semantic, node should be disconnected
+ // manually before it is dropped
+ GAPI_Assert(m_node->inEdges().size() == 0);
+ GAPI_Assert(m_node->outEdges().size() == 0);
+ }
+
+ virtual void commit(ade::Graph &g) override
+ {
+ g.erase(m_node);
+ }
+ };
+
+ class List
+ {
+ std::list< std::unique_ptr<Base> > m_changes;
+
+ public:
+ template<typename T, typename ...Args>
+ void enqueue(Args&&... args)
+ {
+ std::unique_ptr<Base> p(new T(args...));
+ m_changes.push_back(std::move(p));
+ }
+
+ void commit(ade::Graph &g)
+ {
+ // Commit changes in the forward order
+ for (auto& ch : m_changes) ch->commit(g);
+ }
+
+ void rollback(ade::Graph &g)
+ {
+ // Rollback changes in the reverse order
+ for (auto it = m_changes.rbegin(); it != m_changes.rend(); ++it)
+ {
+ (*it)->rollback(g);
+ }
+ }
+ };
+} // namespace Change
+////////////////////////////////////////////////////////////////////////////
+
+#endif // OPENCV_GAPI_COMPILER_TRANSACTIONS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.cpp b/inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.cpp
new file mode 100644
index 000000000..f117c0633
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.cpp
@@ -0,0 +1,244 @@
+// 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) 2018 Intel Corporation
+
+
+#include "precomp.hpp"
+
+#include <iostream>
+
+#include <ade/util/zip_range.hpp>
+
+#include "opencv2/gapi/opencv_includes.hpp"
+#include "executor/gexecutor.hpp"
+#include "compiler/passes/passes.hpp"
+
+cv::gimpl::GExecutor::GExecutor(std::unique_ptr<ade::Graph> &&g_model)
+ : m_orig_graph(std::move(g_model))
+ , m_island_graph(GModel::Graph(*m_orig_graph).metadata()
+ .get<IslandModel>().model)
+ , m_gm(*m_orig_graph)
+ , m_gim(*m_island_graph)
+{
+ // NB: Right now GIslandModel is acyclic, so for a naive execution,
+ // simple unrolling to a list of triggers is enough
+
+ // Naive execution model is similar to current CPU (OpenCV) plugin
+ // execution model:
+ // 1. Allocate all internal resources first (NB - CPU plugin doesn't do it)
+ // 2. Put input/output GComputation arguments to the storage
+ // 3. For every Island, prepare vectors of input/output parameter descs
+ // 4. Iterate over a list of operations (sorted in the topological order)
+ // 5. For every operation, form a list of input/output data objects
+ // 6. Run GIslandExecutable
+ // 7. writeBack
+
+ auto sorted = m_gim.metadata().get<ade::passes::TopologicalSortData>();
+ for (auto nh : sorted.nodes())
+ {
+ switch (m_gim.metadata(nh).get<NodeKind>().k)
+ {
+ case NodeKind::ISLAND:
+ {
+ std::vector<RcDesc> input_rcs;
+ std::vector<RcDesc> output_rcs;
+ input_rcs.reserve(nh->inNodes().size());
+ output_rcs.reserve(nh->outNodes().size());
+
+ auto xtract = [&](ade::NodeHandle slot_nh, std::vector<RcDesc> &vec) {
+ const auto orig_data_nh
+ = m_gim.metadata(slot_nh).get<DataSlot>().original_data_node;
+ const auto &orig_data_info
+ = m_gm.metadata(orig_data_nh).get<Data>();
+ vec.emplace_back(RcDesc{ orig_data_info.rc
+ , orig_data_info.shape
+ , orig_data_info.ctor});
+ };
+ // (3)
+ for (auto in_slot_nh : nh->inNodes()) xtract(in_slot_nh, input_rcs);
+ for (auto out_slot_nh : nh->outNodes()) xtract(out_slot_nh, output_rcs);
+
+ m_ops.emplace_back(OpDesc{ std::move(input_rcs)
+ , std::move(output_rcs)
+ , m_gim.metadata(nh).get<IslandExec>().object});
+ }
+ break;
+
+ case NodeKind::SLOT:
+ {
+ const auto orig_data_nh
+ = m_gim.metadata(nh).get<DataSlot>().original_data_node;
+ // (1)
+ initResource(orig_data_nh);
+ m_slots.emplace_back(DataDesc{nh, orig_data_nh});
+ }
+ break;
+
+ default:
+ GAPI_Assert(false);
+ break;
+ } // switch(kind)
+ } // for(gim nodes)
+}
+
+void cv::gimpl::GExecutor::initResource(const ade::NodeHandle &orig_nh)
+{
+ const Data &d = m_gm.metadata(orig_nh).get<Data>();
+
+ if ( d.storage != Data::Storage::INTERNAL
+ && d.storage != Data::Storage::CONST)
+ return;
+
+ // INTERNALS+CONST only! no need to allocate/reset output objects
+ // to as it is bound externally (e.g. already in the m_res)
+
+ switch (d.shape)
+ {
+ case GShape::GMAT:
+ {
+ const auto desc = util::get<cv::GMatDesc>(d.meta);
+ const auto type = CV_MAKETYPE(desc.depth, desc.chan);
+ m_res.slot<cv::gapi::own::Mat>()[d.rc].create(desc.size, type);
+ }
+ break;
+
+ case GShape::GSCALAR:
+ if (d.storage == Data::Storage::CONST)
+ {
+ auto rc = RcDesc{d.rc, d.shape, d.ctor};
+ magazine::bindInArg(m_res, rc, m_gm.metadata(orig_nh).get<ConstValue>().arg);
+ }
+ break;
+
+ case GShape::GARRAY:
+ // Constructed on Reset, do nothing here
+ break;
+
+ default:
+ GAPI_Assert(false);
+ }
+}
+
+void cv::gimpl::GExecutor::run(cv::gimpl::GRuntimeArgs &&args)
+{
+ // (2)
+ const auto proto = m_gm.metadata().get<Protocol>();
+
+ // Basic check if input/output arguments are correct
+ // FIXME: Move to GCompiled (do once for all GExecutors)
+ if (proto.inputs.size() != args.inObjs.size()) // TODO: Also check types
+ {
+ util::throw_error(std::logic_error
+ ("Computation's input protocol doesn\'t "
+ "match actual arguments!"));
+ }
+ if (proto.outputs.size() != args.outObjs.size()) // TODO: Also check types
+ {
+ util::throw_error(std::logic_error
+ ("Computation's output protocol doesn\'t "
+ "match actual arguments!"));
+ }
+
+ namespace util = ade::util;
+
+ //ensure that output Mat parameters are correctly allocated
+ for (auto index : util::iota(proto.out_nhs.size()) ) //FIXME: avoid copy of NodeHandle and GRunRsltComp ?
+ {
+ auto& nh = proto.out_nhs.at(index);
+ const Data &d = m_gm.metadata(nh).get<Data>();
+ if (d.shape == GShape::GMAT)
+ {
+ using cv::util::get;
+ const auto desc = get<cv::GMatDesc>(d.meta);
+ const auto type = CV_MAKETYPE(desc.depth, desc.chan);
+
+#if !defined(GAPI_STANDALONE)
+ // Building as part of OpenCV - follow OpenCV behavior
+ // if output buffer is not enough to hold the result, reallocate it
+ auto& out_mat = *get<cv::Mat*>(args.outObjs.at(index));
+ out_mat.create(cv::gapi::own::to_ocv(desc.size), type);
+#else
+ // Building standalone - output buffer should always exist,
+ // and _exact_ match our inferred metadata
+ auto& out_mat = *get<cv::gapi::own::Mat*>(args.outObjs.at(index));
+ GAPI_Assert( out_mat.type() == type
+ && out_mat.data != nullptr
+ && out_mat.rows == desc.size.height
+ && out_mat.cols == desc.size.width)
+#endif // !defined(GAPI_STANDALONE)
+ }
+ }
+ // Update storage with user-passed objects
+ for (auto it : ade::util::zip(ade::util::toRange(proto.inputs),
+ ade::util::toRange(args.inObjs)))
+ {
+ magazine::bindInArg(m_res, std::get<0>(it), std::get<1>(it));
+ }
+ for (auto it : ade::util::zip(ade::util::toRange(proto.outputs),
+ ade::util::toRange(args.outObjs)))
+ {
+ magazine::bindOutArg(m_res, std::get<0>(it), std::get<1>(it));
+ }
+
+ // Reset internal data
+ for (auto &sd : m_slots)
+ {
+ const auto& data = m_gm.metadata(sd.data_nh).get<Data>();
+ magazine::resetInternalData(m_res, data);
+ }
+
+ // Run the script
+ for (auto &op : m_ops)
+ {
+ // (5)
+ using InObj = GIslandExecutable::InObj;
+ using OutObj = GIslandExecutable::OutObj;
+ std::vector<InObj> in_objs;
+ std::vector<OutObj> out_objs;
+ in_objs.reserve (op.in_objects.size());
+ out_objs.reserve(op.out_objects.size());
+
+ for (const auto &rc : op.in_objects)
+ {
+ in_objs.emplace_back(InObj{rc, magazine::getArg(m_res, rc)});
+ }
+ for (const auto &rc : op.out_objects)
+ {
+ out_objs.emplace_back(OutObj{rc, magazine::getObjPtr(m_res, rc)});
+ }
+
+ // (6)
+ op.isl_exec->run(std::move(in_objs), std::move(out_objs));
+ }
+
+ // (7)
+ for (auto it : ade::util::zip(ade::util::toRange(proto.outputs),
+ ade::util::toRange(args.outObjs)))
+ {
+ magazine::writeBack(m_res, std::get<0>(it), std::get<1>(it));
+ }
+}
+
+const cv::gimpl::GModel::Graph& cv::gimpl::GExecutor::model() const
+{
+ return m_gm;
+}
+
+bool cv::gimpl::GExecutor::canReshape() const
+{
+ // FIXME: Introduce proper reshaping support on GExecutor level
+ // for all cases!
+ return (m_ops.size() == 1) && m_ops[0].isl_exec->canReshape();
+}
+
+void cv::gimpl::GExecutor::reshape(const GMetaArgs& inMetas, const GCompileArgs& args)
+{
+ GAPI_Assert(canReshape());
+ auto& g = *m_orig_graph.get();
+ ade::passes::PassContext ctx{g};
+ passes::initMeta(ctx, inMetas);
+ passes::inferMeta(ctx, true);
+ m_ops[0].isl_exec->reshape(g, args);
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.hpp
new file mode 100644
index 000000000..e4128ba77
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/executor/gexecutor.hpp
@@ -0,0 +1,97 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_GEXECUTOR_HPP
+#define OPENCV_GAPI_GEXECUTOR_HPP
+
+#include <memory> // unique_ptr, shared_ptr
+
+#include <utility> // tuple, required by magazine
+#include <unordered_map> // required by magazine
+
+#include <ade/graph.hpp>
+
+#include "backends/common/gbackend.hpp"
+
+namespace cv {
+namespace gimpl {
+
+// Graph-level executor interface.
+//
+// This class specifies API for a "super-executor" which orchestrates
+// the overall Island graph execution.
+//
+// Every Island (subgraph) execution is delegated to a particular
+// backend and is done opaquely to the GExecutor.
+//
+// Inputs to a GExecutor instance are:
+// - GIslandModel - a high-level graph model which may be seen as a
+// "procedure" to execute.
+// - GModel - a low-level graph of operations (from which a GIslandModel
+// is projected)
+// - GComputation runtime arguments - vectors of input/output objects
+//
+// Every GExecutor is responsible for
+// a. Maintaining non-island (intermediate) data objects within graph
+// b. Providing GIslandExecutables with input/output data according to
+// their protocols
+// c. Triggering execution of GIslandExecutables when task/data dependencies
+// are met.
+//
+// By default G-API stores all data on host, and cross-Island
+// exchange happens via host buffers (and CV data objects).
+//
+// Today's exchange data objects are:
+// - cv::Mat - for image buffers
+// - cv::Scalar - for single values (with up to four components inside)
+// - cv::detail::VectorRef - an untyped wrapper over std::vector<T>
+//
+
+class GExecutor
+{
+protected:
+ std::unique_ptr<ade::Graph> m_orig_graph;
+ std::shared_ptr<ade::Graph> m_island_graph;
+
+ cv::gimpl::GModel::Graph m_gm; // FIXME: make const?
+ cv::gimpl::GIslandModel::Graph m_gim; // FIXME: make const?
+
+ // FIXME: Naive executor details are here for now
+ // but then it should be moved to another place
+ struct OpDesc
+ {
+ std::vector<RcDesc> in_objects;
+ std::vector<RcDesc> out_objects;
+ std::shared_ptr<GIslandExecutable> isl_exec;
+ };
+ std::vector<OpDesc> m_ops;
+
+ struct DataDesc
+ {
+ ade::NodeHandle slot_nh;
+ ade::NodeHandle data_nh;
+ };
+ std::vector<DataDesc> m_slots;
+
+ Mag m_res;
+
+ void initResource(const ade::NodeHandle &orig_nh); // FIXME: shouldn't it be RcDesc?
+
+public:
+ explicit GExecutor(std::unique_ptr<ade::Graph> &&g_model);
+ void run(cv::gimpl::GRuntimeArgs &&args);
+
+ bool canReshape() const;
+ void reshape(const GMetaArgs& inMetas, const GCompileArgs& args);
+
+ const GModel::Graph& model() const; // FIXME: make it ConstGraph?
+};
+
+} // namespace gimpl
+} // namespace cv
+
+#endif // OPENCV_GAPI_GEXECUTOR_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/logger.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/logger.hpp
new file mode 100644
index 000000000..ff4c7591b
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/logger.hpp
@@ -0,0 +1,22 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef __OPENCV_GAPI_LOGGER_HPP__
+#define __OPENCV_GAPI_LOGGER_HPP__
+
+#if !defined(GAPI_STANDALONE)
+# include "opencv2/core/cvdef.h"
+# include "opencv2/core/utils/logger.hpp"
+# define GAPI_LOG_INFO(tag, ...) CV_LOG_INFO(tag, __VA_ARGS__)
+# define GAPI_LOG_WARNING(tag, ...) CV_LOG_WARNING(tag, __VA_ARGS__)
+#else
+# define GAPI_LOG_INFO(tag, ...)
+# define GAPI_LOG_WARNING(tag, ...)
+#endif // !defined(GAPI_STANDALONE)
+
+
+#endif // __OPENCV_GAPI_LOGGER_HPP__
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/src/precomp.hpp b/inference-engine/thirdparty/fluid/modules/gapi/src/precomp.hpp
new file mode 100644
index 000000000..eebe9d896
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/src/precomp.hpp
@@ -0,0 +1,21 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef __OPENCV_GAPI_PRECOMP_HPP__
+#define __OPENCV_GAPI_PRECOMP_HPP__
+
+#if !defined(GAPI_STANDALONE)
+# include "opencv2/core.hpp"
+# include "opencv2/imgproc.hpp"
+# include "opencv2/gapi/core.hpp"
+# include "opencv2/gapi/imgproc.hpp"
+#endif // !defined(GAPI_STANDALONE)
+
+#include "opencv2/gapi.hpp"
+#include "opencv2/gapi/gkernel.hpp"
+
+#endif // __OPENCV_GAPI_PRECOMP_HPP__
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_compoundkernel_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_compoundkernel_tests.cpp
new file mode 100644
index 000000000..1f5de7a92
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_compoundkernel_tests.cpp
@@ -0,0 +1,500 @@
+// 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) 2018 Intel Corporation
+
+
+// FIXME: move out from Common
+
+#include "test_precomp.hpp"
+#include "opencv2/gapi/cpu/core.hpp"
+
+#include <ade/util/algorithm.hpp>
+
+namespace opencv_test
+{
+namespace
+{
+ G_TYPED_KERNEL(GCompoundDoubleAddC, <GMat(GMat, GScalar)>, "org.opencv.test.compound_double_addC")
+ {
+ static GMatDesc outMeta(GMatDesc in, GScalarDesc) { return in; }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundDoubleAddCImpl, GCompoundDoubleAddC)
+ {
+ static GMat expand(cv::GMat in, cv::GScalar s)
+ {
+ return cv::gapi::addC(cv::gapi::addC(in, s), s);
+ }
+ };
+
+ G_TYPED_KERNEL(GCompoundAddC, <GMat(GMat, GScalar)>, "org.opencv.test.compound_addC")
+ {
+ static GMatDesc outMeta(GMatDesc in, GScalarDesc) { return in; }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundAddCImpl, GCompoundAddC)
+ {
+ static GMat expand(cv::GMat in, cv::GScalar s)
+ {
+ return cv::gapi::addC(in, s);
+ }
+ };
+
+ using GMat3 = std::tuple<GMat,GMat,GMat>;
+ using GMat2 = std::tuple<GMat,GMat>;
+
+ G_TYPED_KERNEL_M(GCompoundMergeWithSplit, <GMat3(GMat, GMat, GMat)>, "org.opencv.test.compound_merge_split")
+ {
+ static std::tuple<GMatDesc,GMatDesc,GMatDesc> outMeta(GMatDesc a, GMatDesc b, GMatDesc c)
+ {
+ return std::make_tuple(a, b, c);
+ }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundMergeWithSplitImpl, GCompoundMergeWithSplit)
+ {
+ static GMat3 expand(cv::GMat a, cv::GMat b, cv::GMat c)
+ {
+ return cv::gapi::split3(cv::gapi::merge3(a, b, c));
+ }
+ };
+
+ G_TYPED_KERNEL(GCompoundAddWithAddC, <GMat(GMat, GMat, GScalar)>, "org.opencv.test.compound_add_with_addc")
+ {
+ static GMatDesc outMeta(GMatDesc in, GMatDesc, GScalarDesc)
+ {
+ return in;
+ }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundAddWithAddCImpl, GCompoundAddWithAddC)
+ {
+ static GMat expand(cv::GMat in1, cv::GMat in2, cv::GScalar s)
+ {
+ return cv::gapi::addC(cv::gapi::add(in1, in2), s);
+ }
+ };
+
+ G_TYPED_KERNEL_M(GCompoundSplitWithAdd, <GMat2(GMat)>, "org.opencv.test.compound_split_with_add")
+ {
+ static std::tuple<GMatDesc, GMatDesc> outMeta(GMatDesc in)
+ {
+ const auto out_depth = in.depth;
+ const auto out_desc = in.withType(out_depth, 1);
+ return std::make_tuple(out_desc, out_desc);
+ }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundSplitWithAddImpl, GCompoundSplitWithAdd)
+ {
+ static GMat2 expand(cv::GMat in)
+ {
+ cv::GMat a, b, c;
+ std::tie(a, b, c) = cv::gapi::split3(in);
+ return std::make_tuple(cv::gapi::add(a, b), c);
+ }
+ };
+
+ G_TYPED_KERNEL_M(GCompoundParallelAddC, <GMat2(GMat, GScalar)>, "org.opencv.test.compound_parallel_addc")
+ {
+ static std::tuple<GMatDesc, GMatDesc> outMeta(GMatDesc in, GScalarDesc)
+ {
+ return std::make_tuple(in, in);
+ }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundParallelAddCImpl, GCompoundParallelAddC)
+ {
+ static GMat2 expand(cv::GMat in, cv::GScalar s)
+ {
+ return std::make_tuple(cv::gapi::addC(in, s), cv::gapi::addC(in, s));
+ }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundAddImpl, cv::gapi::core::GAdd)
+ {
+ static GMat expand(cv::GMat in1, cv::GMat in2, int)
+ {
+ return cv::gapi::sub(cv::gapi::sub(in1, in2), in2);
+ }
+ };
+
+ G_TYPED_KERNEL(GCompoundAddWithAddCWithDoubleAddC, <GMat(GMat, GMat, GScalar)>, "org.opencv.test.compound_add_with_addC_with_double_addC")
+ {
+ static GMatDesc outMeta(GMatDesc in, GMatDesc, GScalarDesc)
+ {
+ return in;
+ }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundAddWithAddCWithDoubleAddCImpl, GCompoundAddWithAddCWithDoubleAddC)
+ {
+ static GMat expand(cv::GMat in1, cv::GMat in2, cv::GScalar s)
+ {
+ return GCompoundDoubleAddC::on(GCompoundAddWithAddC::on(in1, in2, s), s);
+ }
+ };
+
+ using GDoubleArray = cv::GArray<double>;
+ G_TYPED_KERNEL(GNegateArray, <GDoubleArray(GDoubleArray)>, "org.opencv.test.negate_array")
+ {
+ static GArrayDesc outMeta(const GArrayDesc&) { return empty_array_desc(); }
+ };
+
+ GAPI_OCV_KERNEL(GNegateArrayImpl, GNegateArray)
+ {
+ static void run(const std::vector<double>& in, std::vector<double>& out)
+ {
+ ade::util::transform(in, std::back_inserter(out), std::negate<double>());
+ }
+ };
+
+ G_TYPED_KERNEL(GMaxInArray, <GScalar(GDoubleArray)>, "org.opencv.test.max_in_array")
+ {
+ static GScalarDesc outMeta(const GArrayDesc&) { return empty_scalar_desc(); }
+ };
+
+ GAPI_OCV_KERNEL(GMaxInArrayImpl, GMaxInArray)
+ {
+ static void run(const std::vector<double>& in, cv::Scalar& out)
+ {
+ out = *std::max_element(in.begin(), in.end());
+ }
+ };
+
+ G_TYPED_KERNEL(GCompoundMaxInArray, <GScalar(GDoubleArray)>, "org.opencv.test.compound_max_in_array")
+ {
+ static GScalarDesc outMeta(const GArrayDesc&) { return empty_scalar_desc(); }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundMaxInArrayImpl, GCompoundMaxInArray)
+ {
+ static GScalar expand(GDoubleArray in)
+ {
+ return GMaxInArray::on(in);
+ }
+ };
+
+ G_TYPED_KERNEL(GCompoundNegateArray, <GDoubleArray(GDoubleArray)>, "org.opencv.test.compound_negate_array")
+ {
+ static GArrayDesc outMeta(const GArrayDesc&) { return empty_array_desc(); }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundNegateArrayImpl, GCompoundNegateArray)
+ {
+ static GDoubleArray expand(GDoubleArray in)
+ {
+ return GNegateArray::on(in);
+ }
+ };
+
+ G_TYPED_KERNEL(SetDiagKernel, <GMat(GMat, GDoubleArray)>, "org.opencv.test.empty_kernel")
+ {
+ static GMatDesc outMeta(GMatDesc in, GArrayDesc) { return in; }
+ };
+
+ void setDiag(cv::Mat& in, const std::vector<double>& diag)
+ {
+ GAPI_Assert(in.rows == static_cast<int>(diag.size()));
+ GAPI_Assert(in.cols == static_cast<int>(diag.size()));
+ for (int i = 0; i < in.rows; ++i)
+ {
+ in.at<uchar>(i, i) = static_cast<uchar>(diag[i]);
+ }
+ }
+
+ GAPI_OCV_KERNEL(SetDiagKernelImpl, SetDiagKernel)
+ {
+ static void run(const cv::Mat& in, const std::vector<double>& v, cv::Mat& out)
+ {
+ in.copyTo(out);
+ setDiag(out, v);
+ }
+ };
+
+ G_TYPED_KERNEL(GCompoundGMatGArrayGMat, <GMat(GMat, GDoubleArray, GMat)>, "org.opencv.test.compound_gmat_garray_gmat")
+ {
+ static GMatDesc outMeta(GMatDesc in, GArrayDesc, GMatDesc) { return in; }
+ };
+
+ GAPI_COMPOUND_KERNEL(GCompoundGMatGArrayGMatImpl, GCompoundGMatGArrayGMat)
+ {
+ static GMat expand(GMat a, GDoubleArray b, GMat c)
+ {
+ return SetDiagKernel::on(cv::gapi::add(a, c), b);
+ }
+ };
+
+} // namespace
+
+// FIXME avoid cv::combine that use custom and default kernels together
+TEST(GCompoundKernel, ReplaceDefaultKernel)
+{
+ cv::GMat in1, in2;
+ auto out = cv::gapi::add(in1, in2);
+ const auto custom_pkg = cv::gapi::kernels<GCompoundAddImpl>();
+ const auto full_pkg = cv::gapi::combine(cv::gapi::core::cpu::kernels(), custom_pkg, cv::unite_policy::REPLACE);
+ cv::GComputation comp(cv::GIn(in1, in2), cv::GOut(out));
+ cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
+ in_mat2 = cv::Mat::eye(3, 3, CV_8UC1),
+ out_mat(3, 3, CV_8UC1),
+ ref_mat(3, 3, CV_8UC1);
+
+ comp.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat), cv::compile_args(full_pkg));
+ ref_mat = in_mat1 - in_mat2 - in_mat2;
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GCompoundKernel, DoubleAddC)
+{
+ cv::GMat in1, in2;
+ cv::GScalar s;
+ auto add_res = cv::gapi::add(in1, in2);
+ auto super = GCompoundDoubleAddC::on(add_res, s);
+ auto out = cv::gapi::addC(super, s);
+
+ const auto custom_pkg = cv::gapi::kernels<GCompoundDoubleAddCImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
+
+ cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
+ in_mat2 = cv::Mat::eye(3, 3, CV_8UC1),
+ out_mat(3, 3, CV_8UC1),
+ ref_mat(3, 3, CV_8UC1);
+
+ cv::Scalar scalar = 2;
+
+ comp.apply(cv::gin(in_mat1, in_mat2, scalar), cv::gout(out_mat), cv::compile_args(full_pkg));
+ ref_mat = in_mat1 + in_mat2 + scalar + scalar + scalar;
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GCompoundKernel, AddC)
+{
+ cv::GMat in1, in2;
+ cv::GScalar s;
+ auto add_res = cv::gapi::add(in1, in2);
+ auto super = GCompoundAddC::on(add_res, s);
+ auto out = cv::gapi::addC(super, s);
+
+ const auto custom_pkg = cv::gapi::kernels<GCompoundAddCImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
+
+ cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
+ in_mat2 = cv::Mat::eye(3, 3, CV_8UC1),
+ out_mat(3, 3, CV_8UC1),
+ ref_mat(3, 3, CV_8UC1);
+
+ cv::Scalar scalar = 2;
+
+ comp.apply(cv::gin(in_mat1, in_mat2, scalar), cv::gout(out_mat), cv::compile_args(full_pkg));
+ ref_mat = in_mat1 + in_mat2 + scalar + scalar;
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GCompoundKernel, MergeWithSplit)
+{
+ cv::GMat in, a1, b1, c1,
+ a2, b2, c2;
+
+ std::tie(a1, b1, c1) = cv::gapi::split3(in);
+ std::tie(a2, b2, c2) = GCompoundMergeWithSplit::on(a1, b1, c1);
+ auto out = cv::gapi::merge3(a2, b2, c2);
+
+ const auto custom_pkg = cv::gapi::kernels<GCompoundMergeWithSplitImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+
+ cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC3), out_mat, ref_mat;
+ comp.apply(cv::gin(in_mat), cv::gout(out_mat), cv::compile_args(full_pkg));
+ ref_mat = in_mat;
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GCompoundKernel, AddWithAddC)
+{
+ cv::GMat in1, in2;
+ cv::GScalar s;
+ auto out = GCompoundAddWithAddC::on(in1, in2, s);
+
+ const auto custom_pkg = cv::gapi::kernels<GCompoundAddWithAddCImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
+
+ cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
+ in_mat2 = cv::Mat::eye(3, 3, CV_8UC1),
+ out_mat(3, 3, CV_8UC1),
+ ref_mat(3, 3, CV_8UC1);
+
+ cv::Scalar scalar = 2;
+
+ comp.apply(cv::gin(in_mat1, in_mat2, scalar), cv::gout(out_mat), cv::compile_args(full_pkg));
+ ref_mat = in_mat1 + in_mat2 + scalar;
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GCompoundKernel, SplitWithAdd)
+{
+ cv::GMat in, out1, out2;
+ std::tie(out1, out2) = GCompoundSplitWithAdd::on(in);
+
+ const auto custom_pkg = cv::gapi::kernels<GCompoundSplitWithAddImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in), cv::GOut(out1, out2));
+
+ cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC3),
+ out_mat1(3, 3, CV_8UC1),
+ out_mat2(3, 3, CV_8UC1),
+ ref_mat1(3, 3, CV_8UC1),
+ ref_mat2(3, 3, CV_8UC1);
+
+ comp.apply(cv::gin(in_mat), cv::gout(out_mat1, out_mat2), cv::compile_args(full_pkg));
+
+ std::vector<cv::Mat> channels(3);
+ cv::split(in_mat, channels);
+
+ ref_mat1 = channels[0] + channels[1];
+ ref_mat2 = channels[2];
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat1 != ref_mat1));
+ EXPECT_EQ(0, cv::countNonZero(out_mat2 != ref_mat2));
+}
+
+TEST(GCompoundKernel, ParallelAddC)
+{
+ cv::GMat in1, out1, out2;
+ cv::GScalar in2;
+ std::tie(out1, out2) = GCompoundParallelAddC::on(in1, in2);
+
+ const auto custom_pkg = cv::gapi::kernels<GCompoundParallelAddCImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in1, in2), cv::GOut(out1, out2));
+
+ cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1),
+ out_mat1(3, 3, CV_8UC1),
+ out_mat2(3, 3, CV_8UC1),
+ ref_mat1(3, 3, CV_8UC1),
+ ref_mat2(3, 3, CV_8UC1);
+
+ cv::Scalar scalar = 2;
+
+ comp.apply(cv::gin(in_mat, scalar), cv::gout(out_mat1, out_mat2), cv::compile_args(full_pkg));
+
+ ref_mat1 = in_mat + scalar;
+ ref_mat2 = in_mat + scalar;
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat1 != ref_mat1));
+ EXPECT_EQ(0, cv::countNonZero(out_mat2 != ref_mat2));
+}
+
+TEST(GCompoundKernel, GCompundKernelAndDefaultUseOneData)
+{
+ cv::GMat in1, in2;
+ cv::GScalar s;
+ auto out = cv::gapi::add(GCompoundAddWithAddC::on(in1, in2, s), cv::gapi::addC(in2, s));
+
+ const auto custom_pkg = cv::gapi::kernels<GCompoundAddWithAddCImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
+
+ cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
+ in_mat2 = cv::Mat::eye(3, 3, CV_8UC1),
+ out_mat(3, 3, CV_8UC1),
+ ref_mat(3, 3, CV_8UC1);
+
+ cv::Scalar scalar = 2;
+
+ comp.apply(cv::gin(in_mat1, in_mat2, scalar), cv::gout(out_mat), cv::compile_args(full_pkg));
+ ref_mat = in_mat1 + in_mat2 + scalar + in_mat2 + scalar;
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GCompoundKernel, CompoundExpandedToCompound)
+{
+ cv::GMat in1, in2;
+ cv::GScalar s;
+ auto out = GCompoundAddWithAddCWithDoubleAddC::on(in1, in2, s);
+
+ const auto custom_pkg = cv::gapi::kernels<GCompoundAddWithAddCWithDoubleAddCImpl,
+ GCompoundAddWithAddCImpl,
+ GCompoundDoubleAddCImpl>();
+
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in1, in2, s), cv::GOut(out));
+
+ cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
+ in_mat2 = cv::Mat::eye(3, 3, CV_8UC1),
+ out_mat(3, 3, CV_8UC1),
+ ref_mat(3, 3, CV_8UC1);
+
+ cv::Scalar scalar = 2;
+
+ comp.apply(cv::gin(in_mat1, in_mat2, scalar), cv::gout(out_mat), cv::compile_args(full_pkg));
+ ref_mat = in_mat1 + in_mat2 + scalar + scalar + scalar;
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GCompoundKernel, MaxInArray)
+{
+ GDoubleArray in;
+ auto out = GCompoundMaxInArray::on(in);
+ const auto custom_pkg = cv::gapi::kernels<GCompoundMaxInArrayImpl, GMaxInArrayImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+ std::vector<double> v = { 1, 5, -2, 3, 10, 2};
+ cv::Scalar out_scl;
+ cv::Scalar ref_scl(*std::max_element(v.begin(), v.end()));
+
+ comp.apply(cv::gin(v), cv::gout(out_scl), cv::compile_args(full_pkg));
+
+ EXPECT_EQ(out_scl, ref_scl);
+}
+
+TEST(GCompoundKernel, NegateArray)
+{
+ GDoubleArray in;
+ GDoubleArray out = GCompoundNegateArray::on(in);
+ const auto custom_pkg = cv::gapi::kernels<GCompoundNegateArrayImpl, GNegateArrayImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+ std::vector<double> in_v = {1, 5, -2, -10, 3};
+ std::vector<double> out_v;
+ std::vector<double> ref_v;
+ ade::util::transform(in_v, std::back_inserter(ref_v), std::negate<double>());
+
+ comp.apply(cv::gin(in_v), cv::gout(out_v), cv::compile_args(full_pkg));
+
+ EXPECT_EQ(out_v, ref_v);
+}
+
+TEST(GCompoundKernel, RightGArrayHandle)
+{
+ cv::GMat in[2];
+ GDoubleArray a;
+ cv::GMat out = GCompoundGMatGArrayGMat::on(in[0], a, in[1]);
+ const auto custom_pkg = cv::gapi::kernels<GCompoundGMatGArrayGMatImpl, SetDiagKernelImpl>();
+ const auto full_pkg = cv::gapi::combine(custom_pkg, cv::gapi::core::cpu::kernels(), cv::unite_policy::KEEP);
+ cv::GComputation comp(cv::GIn(in[0], a, in[1]), cv::GOut(out));
+ std::vector<double> in_v(3, 1.0);
+ cv::Mat in_mat1 = cv::Mat::eye(cv::Size(3, 3), CV_8UC1),
+ in_mat2 = cv::Mat::eye(cv::Size(3, 3), CV_8UC1),
+ out_mat;
+ cv::Mat ref_mat= in_mat1 + in_mat2;
+ setDiag(ref_mat, in_v);
+
+ comp.apply(cv::gin(in_mat1, in_v, in_mat2), cv::gout(out_mat), cv::compile_args(full_pkg));
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+
+}
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests.cpp
new file mode 100644
index 000000000..eb7761248
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests.cpp
@@ -0,0 +1,9 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "gapi_core_tests_inl.hpp"
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests.hpp
new file mode 100644
index 000000000..77a82dfd2
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests.hpp
@@ -0,0 +1,153 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_CORE_TESTS_HPP
+#define OPENCV_GAPI_CORE_TESTS_HPP
+
+#include <iostream>
+
+#include "gapi_tests_common.hpp"
+
+namespace opencv_test
+{
+enum mathOp
+{
+ ADD = 0,
+ SUB = 1,
+ MUL = 2,
+ DIV = 3
+};
+
+enum bitwiseOp
+{
+ AND = 0,
+ OR = 1,
+ XOR = 2,
+ NOT = 3
+};
+
+namespace
+{
+const char *MathOperations[] = {"ADD", "SUB", "MUL", "DIV"};
+const char *BitwiseOperations[] = {"And", "Or", "Xor"};
+const char *CompareOperations[] = {"CMP_EQ", "CMP_GT", "CMP_GE", "CMP_LT", "CMP_LE", "CMP_NE"};
+//corresponds to OpenCV
+const char *NormOperations[] = {"", "NORM_INF", "NORM_L1", "","NORM_L2"};
+}
+
+
+struct PrintMathOpCoreParams
+{
+ template <class TestParams>
+ std::string operator()(const ::testing::TestParamInfo<TestParams>& info) const
+ {
+ std::stringstream ss;
+ cv::Size sz = std::get<4>(info.param);
+ ss<<MathOperations[std::get<0>(info.param)]
+ <<"_"<<std::get<1>(info.param)
+ <<"_"<<std::get<2>(info.param)
+ <<"_"<<(int)std::get<3>(info.param)
+ <<"_"<<sz.width
+ <<"x"<<sz.height
+ <<"_"<<(std::get<5>(info.param)+1)
+ <<"_"<<std::get<6>(info.param)
+ <<"_"<<std::get<7>(info.param);
+ return ss.str();
+ }
+};
+
+struct PrintCmpCoreParams
+{
+ template <class TestParams>
+ std::string operator()(const ::testing::TestParamInfo<TestParams>& info) const
+ {
+ std::stringstream ss;
+ cv::Size sz = std::get<3>(info.param);
+ ss<<CompareOperations[std::get<0>(info.param)]
+ <<"_"<<std::get<1>(info.param)
+ <<"_"<<std::get<2>(info.param)
+ <<"_"<<sz.width
+ <<"x"<<sz.height
+ <<"_"<<std::get<4>(info.param);
+ return ss.str();
+ }
+};
+
+struct PrintBWCoreParams
+{
+ template <class TestParams>
+ std::string operator()(const ::testing::TestParamInfo<TestParams>& info) const
+ {
+ std::stringstream ss;
+ cv::Size sz = std::get<2>(info.param);
+ ss<<BitwiseOperations[std::get<0>(info.param)]
+ <<"_"<<std::get<1>(info.param)
+ <<"_"<<sz.width
+ <<"x"<<sz.height
+ <<"_"<<std::get<3>(info.param);
+ return ss.str();
+ }
+};
+
+struct PrintNormCoreParams
+{
+ template <class TestParams>
+ std::string operator()(const ::testing::TestParamInfo<TestParams>& info) const
+ {
+ std::stringstream ss;
+ cv::Size sz = std::get<2>(info.param);
+ ss<<NormOperations[std::get<0>(info.param)]
+ <<"_"<<std::get<1>(info.param)
+ <<"_"<<sz.width
+ <<"x"<<sz.height;
+ return ss.str();
+ }
+};
+
+struct MathOpTest : public TestParams<std::tuple<mathOp,bool,int,double,cv::Size,int,bool,bool,cv::GCompileArgs>>{};
+struct MulDoubleTest : public TestParams<std::tuple<int,cv::Size,int,bool,cv::GCompileArgs>>{};
+struct DivTest : public TestParams<std::tuple<int,cv::Size,int,bool, cv::GCompileArgs>>{};
+struct DivCTest : public TestParams<std::tuple<int,cv::Size,int,bool, cv::GCompileArgs>>{};
+struct MeanTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>> {};
+struct MaskTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>> {};
+struct Polar2CartTest : public TestParams<std::tuple<cv::Size,bool, cv::GCompileArgs>> {};
+struct Cart2PolarTest : public TestParams<std::tuple<cv::Size,bool, cv::GCompileArgs>> {};
+struct CmpTest : public TestParams<std::tuple<CmpTypes,bool,int,cv::Size,bool, cv::GCompileArgs>>{};
+struct BitwiseTest : public TestParams<std::tuple<bitwiseOp,int,cv::Size,bool, cv::GCompileArgs>>{};
+struct NotTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>> {};
+struct SelectTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>> {};
+struct MinTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>>{};
+struct MaxTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>>{};
+struct AbsDiffTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>>{};
+struct AbsDiffCTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>> {};
+struct SumTest : public TestParams<std::tuple<int, cv::Size,bool,double,cv::GCompileArgs>> {};
+struct AddWeightedTest : public TestParams<std::tuple<int,cv::Size,int,bool,double,cv::GCompileArgs>>{};
+struct NormTest : public TestParams<std::tuple<NormTypes,int,cv::Size, double, cv::GCompileArgs>>{};
+struct IntegralTest : public TestWithParam<std::tuple<int,cv::Size, cv::GCompileArgs>> {};
+struct ThresholdTest : public TestParams<std::tuple<int,cv::Size,int,bool, cv::GCompileArgs>> {};
+struct ThresholdOTTest : public TestParams<std::tuple<int,cv::Size,int,bool, cv::GCompileArgs>> {};
+struct InRangeTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>> {};
+struct Split3Test : public TestParams<std::tuple<cv::Size, cv::GCompileArgs>> {};
+struct Split4Test : public TestParams<std::tuple<cv::Size, cv::GCompileArgs>> {};
+struct ResizeTest : public TestWithParam<std::tuple<compare_f, int, int, cv::Size, cv::Size, cv::GCompileArgs>> {};
+struct ResizeTestFxFy : public TestWithParam<std::tuple<compare_f, int, int, cv::Size, double, double, cv::GCompileArgs>> {};
+struct Merge3Test : public TestParams<std::tuple<cv::Size, cv::GCompileArgs>> {};
+struct Merge4Test : public TestParams<std::tuple<cv::Size, cv::GCompileArgs>> {};
+struct RemapTest : public TestParams<std::tuple<int,cv::Size,bool, cv::GCompileArgs>> {};
+struct FlipTest : public TestParams<std::tuple<int, int, cv::Size,bool, cv::GCompileArgs>> {};
+struct CropTest : public TestParams<std::tuple<int,cv::Rect,cv::Size,bool, cv::GCompileArgs>> {};
+struct ConcatHorTest : public TestWithParam<std::tuple<int, cv::Size, cv::GCompileArgs>> {};
+struct ConcatVertTest : public TestWithParam<std::tuple<int, cv::Size, cv::GCompileArgs>> {};
+struct ConcatVertVecTest : public TestWithParam<std::tuple<int, cv::Size, cv::GCompileArgs>> {};
+struct ConcatHorVecTest : public TestWithParam<std::tuple<int, cv::Size, cv::GCompileArgs>> {};
+struct LUTTest : public TestParams<std::tuple<int, int, cv::Size,bool, cv::GCompileArgs>> {};
+struct ConvertToTest : public TestParams<std::tuple<int, int, cv::Size, cv::GCompileArgs>> {};
+struct PhaseTest : public TestParams<std::tuple<int, cv::Size, bool, cv::GCompileArgs>> {};
+struct SqrtTest : public TestParams<std::tuple<int, cv::Size, cv::GCompileArgs>> {};
+} // opencv_test
+
+#endif //OPENCV_GAPI_CORE_TESTS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests_inl.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests_inl.hpp
new file mode 100644
index 000000000..d33b5cc63
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_core_tests_inl.hpp
@@ -0,0 +1,1479 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_CORE_TESTS_INL_HPP
+#define OPENCV_GAPI_CORE_TESTS_INL_HPP
+
+#include "opencv2/gapi/core.hpp"
+#include "gapi_core_tests.hpp"
+
+namespace opencv_test
+{
+
+TEST_P(MathOpTest, MatricesAccuracyTest )
+{
+ mathOp opType = ADD;
+ int type = 0, dtype = 0;
+ cv::Size sz;
+ double scale = 1; // mul, div
+ bool testWithScalar = false, initOutMatr = false, doReverseOp = false;
+ cv::GCompileArgs compile_args;
+ std::tie(opType, testWithScalar, type, scale, sz, dtype, initOutMatr, doReverseOp, compile_args) = GetParam();
+ initMatsRandU(type, sz, dtype, initOutMatr);
+
+ // G-API code & corresponding OpenCV code ////////////////////////////////
+ cv::GMat in1, in2, out;
+ if( testWithScalar )
+ {
+ cv::GScalar sc1;
+ switch(opType)
+ {
+ case (ADD):
+ {
+ out = cv::gapi::addC(in1, sc1, dtype);
+ cv::add(in_mat1, sc, out_mat_ocv, cv::noArray(), dtype);
+ break;
+ }
+ case (SUB):
+ {
+ if( doReverseOp )
+ {
+ out = cv::gapi::subRC(sc1, in1, dtype);
+ cv::subtract(sc, in_mat1, out_mat_ocv, cv::noArray(), dtype);
+ }
+ else
+ {
+ out = cv::gapi::subC(in1, sc1, dtype);
+ cv::subtract(in_mat1, sc, out_mat_ocv, cv::noArray(), dtype);
+ }
+ break;
+ }
+ case (DIV):
+ {
+ if( doReverseOp )
+ {
+ in_mat1.setTo(1, in_mat1 == 0); // avoid zeros in divide input data
+ out = cv::gapi::divRC(sc1, in1, scale, dtype);
+ cv::divide(sc, in_mat1, out_mat_ocv, scale, dtype);
+ break;
+ }
+ else
+ {
+ sc += Scalar(1, 1, 1, 1); // avoid zeros in divide input data
+ out = cv::gapi::divC(in1, sc1, scale, dtype);
+ cv::divide(in_mat1, sc, out_mat_ocv, scale, dtype);
+ break;
+ }
+ }
+ case (MUL):
+ {
+ // FIXME: add `scale` parameter to mulC
+ out = cv::gapi::mulC(in1, sc1, /* scale, */ dtype);
+ cv::multiply(in_mat1, sc, out_mat_ocv, 1., dtype);
+ break;
+ }
+ default:
+ {
+ FAIL() << "no such math operation type for scalar and matrix!";
+ }
+ }
+ cv::GComputation c(GIn(in1, sc1), GOut(out));
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+ else
+ {
+ switch(opType)
+ {
+ case (ADD):
+ {
+ out = cv::gapi::add(in1, in2, dtype);
+ cv::add(in_mat1, in_mat2, out_mat_ocv, cv::noArray(), dtype);
+ break;
+ }
+ case (SUB):
+ {
+ out = cv::gapi::sub(in1, in2, dtype);
+ cv::subtract(in_mat1, in_mat2, out_mat_ocv, cv::noArray(), dtype);
+ break;
+ }
+ case (DIV):
+ {
+ in_mat2.setTo(1, in_mat2 == 0); // avoid zeros in divide input data
+ out = cv::gapi::div(in1, in2, scale, dtype);
+ cv::divide(in_mat1, in_mat2, out_mat_ocv, scale, dtype);
+ break;
+ }
+ case (MUL):
+ {
+ out = cv::gapi::mul(in1, in2, scale, dtype);
+ cv::multiply(in_mat1, in_mat2, out_mat_ocv, scale, dtype);
+ break;
+ }
+ default:
+ {
+ FAIL() << "no such math operation type for matrix and matrix!";
+ }}
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ // TODO: make threshold vs bit-exact criteria be driven by testing parameter
+ #if 1
+ if (CV_MAT_DEPTH(out_mat_ocv.type()) != CV_32F &&
+ CV_MAT_DEPTH(out_mat_ocv.type()) != CV_64F)
+ {
+ // integral: allow 1% of differences, and no diffs by >1 unit
+ EXPECT_LE(countNonZeroPixels(cv::abs(out_mat_gapi - out_mat_ocv) > 0),
+ 0.01*out_mat_ocv.total());
+ EXPECT_LE(countNonZeroPixels(cv::abs(out_mat_gapi - out_mat_ocv) > 1), 0);
+ }
+ else
+ {
+ // floating-point: expect 6 decimal digits - best we expect of F32
+ EXPECT_EQ(0, cv::countNonZero(cv::abs(out_mat_gapi - out_mat_ocv) >
+ 1e-6*cv::abs(out_mat_ocv)));
+ }
+ #else
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ #endif
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(MulDoubleTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ int dtype = std::get<2>(param);
+ cv::Size sz_in = std::get<1>(param);
+ bool initOut = std::get<3>(param);
+
+ auto& rng = cv::theRNG();
+ double d = rng.uniform(0.0, 10.0);
+ auto compile_args = std::get<4>(param);
+ initMatrixRandU(type, sz_in, dtype, initOut);
+
+ // G-API code ////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ out = cv::gapi::mulC(in1, d, dtype);
+ cv::GComputation c(in1, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ // OpenCV code ///////////////////////////////////////////////////////////
+ cv::multiply(in_mat1, d, out_mat_ocv, 1, dtype);
+
+ // Comparison ////////////////////////////////////////////////////////////
+#if 1
+ if (CV_MAT_DEPTH(out_mat_ocv.type()) != CV_32F &&
+ CV_MAT_DEPTH(out_mat_ocv.type()) != CV_64F)
+ {
+ // integral: allow 1% of differences, and no diffs by >1 unit
+ EXPECT_LE(countNonZeroPixels(cv::abs(out_mat_gapi - out_mat_ocv) > 0),
+ 0.01*out_mat_ocv.total());
+ EXPECT_LE(countNonZeroPixels(cv::abs(out_mat_gapi - out_mat_ocv) > 1), 0);
+ }
+ else
+ {
+ // floating-point: expect 6 decimal digits - best we expect of F32
+ EXPECT_EQ(0, cv::countNonZero(cv::abs(out_mat_gapi - out_mat_ocv) >
+ 1e-6*cv::abs(out_mat_ocv)));
+ }
+#else
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+#endif
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+}
+
+TEST_P(DivTest, DISABLED_DivByZeroTest) // https://github.com/opencv/opencv/pull/12826
+{
+ int type = 0, dtype = 0;
+ cv::Size sz_in;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(type, sz_in, dtype, initOut, compile_args) = GetParam();
+
+ initMatrixRandU(type, sz_in, dtype, initOut);
+ in_mat2 = cv::Mat(sz_in, type);
+ in_mat2.setTo(cv::Scalar::all(0));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::div(in1, in2, 1.0, dtype);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::divide(in_mat1, in_mat2, out_mat_ocv, 1.0, dtype);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(DivCTest, DISABLED_DivByZeroTest) // https://github.com/opencv/opencv/pull/12826
+{
+ int type = 0, dtype = 0;
+ cv::Size sz_in;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(type, sz_in, dtype, initOut, compile_args) = GetParam();
+
+ initMatrixRandU(type, sz_in, dtype, initOut);
+ sc = cv::Scalar::all(0);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1;
+ cv::GScalar sc1;
+ auto out = cv::gapi::divC(in1, sc1, dtype);
+ cv::GComputation c(GIn(in1, sc1), GOut(out));
+
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::divide(in_mat1, sc, out_mat_ocv, dtype);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ cv::Mat zeros = cv::Mat::zeros(sz_in, type);
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != zeros));
+ }
+}
+
+TEST_P(MeanTest, AccuracyTest)
+{
+ int type = 0;
+ bool initOut = false;
+ cv::Size sz_in;
+ cv::GCompileArgs compile_args;
+ std::tie(type, sz_in, initOut, compile_args) = GetParam();
+ initMatrixRandU(type, sz_in, initOut);
+ cv::Scalar out_norm;
+ cv::Scalar out_norm_ocv;
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::mean(in);
+
+ cv::GComputation c(cv::GIn(in), cv::GOut(out));
+ c.apply(cv::gin(in_mat1), cv::gout(out_norm), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ out_norm_ocv = cv::mean(in_mat1);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(out_norm[0], out_norm_ocv[0]);
+ }
+}
+
+TEST_P(MaskTest, AccuracyTest)
+{
+ int type = 0;
+ bool initOut = false;
+ cv::Size sz_in;
+ cv::GCompileArgs compile_args;
+ std::tie(type, sz_in, initOut, compile_args) = GetParam();
+ initMatrixRandU(type, sz_in, type, initOut);
+
+ in_mat2 = cv::Mat(sz_in, CV_8UC1);
+ cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+ in_mat2 = in_mat2 > 128;
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in, m;
+ auto out = cv::gapi::mask(in, m);
+
+ cv::GComputation c(cv::GIn(in, m), cv::GOut(out));
+ c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ out_mat_ocv = cv::Mat::zeros(in_mat1.size(), in_mat1.type());
+ in_mat1.copyTo(out_mat_ocv, in_mat2);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ }
+}
+
+TEST_P(Polar2CartTest, AccuracyTest)
+{
+ auto param = GetParam();
+ cv::Size sz_in = std::get<0>(param);
+ auto compile_args = std::get<2>(param);
+ initMatsRandU(CV_32FC1, sz_in, CV_32FC1, std::get<1>(param));
+
+ cv::Mat out_mat2;
+ cv::Mat out_mat_ocv2;
+ if(std::get<1>(param) == true)
+ {
+ out_mat2 = cv::Mat(sz_in, CV_32FC1);
+ out_mat_ocv2 = cv::Mat(sz_in, CV_32FC1);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out1, out2;
+ std::tie(out1, out2) = cv::gapi::polarToCart(in1, in2);
+
+ cv::GComputation c(GIn(in1, in2), GOut(out1, out2));
+ c.apply(gin(in_mat1,in_mat2), gout(out_mat_gapi, out_mat2), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::polarToCart(in_mat1, in_mat2, out_mat_ocv, out_mat_ocv2);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ // Note that we cannot rely on bit-exact sin/cos functions used for this
+ // transform, so we need a threshold for verifying results vs reference.
+ //
+ // Relative threshold like 1e-6 is very restrictive, nearly best we can
+ // expect of single-precision elementary functions implementation.
+ //
+ // However, good idea is making such threshold configurable: parameter
+ // of this test - which a specific test istantiation could setup.
+ //
+ // Note that test instantiation for the OpenCV back-end could even let
+ // the threshold equal to zero, as CV back-end calls the same kernel.
+ //
+ // TODO: Make threshold a configurable parameter of this test (ADE-221)
+
+ cv::Mat &outx = out_mat_gapi,
+ &outy = out_mat2;
+ cv::Mat &refx = out_mat_ocv,
+ &refy = out_mat_ocv2;
+ cv::Mat difx = cv::abs(refx - outx),
+ dify = cv::abs(refy - outy);
+ cv::Mat absx = cv::abs(refx),
+ absy = cv::abs(refy);
+
+ EXPECT_EQ(0, cv::countNonZero(difx > 1e-6*absx));
+ EXPECT_EQ(0, cv::countNonZero(dify > 1e-6*absy));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(Cart2PolarTest, AccuracyTest)
+{
+ auto param = GetParam();
+ cv::Size sz_in = std::get<0>(param);
+ auto compile_args = std::get<2>(param);
+ initMatsRandU(CV_32FC1, sz_in, CV_32FC1, std::get<1>(param));
+
+ cv::Mat out_mat2(sz_in, CV_32FC1);
+ cv::Mat out_mat_ocv2(sz_in, CV_32FC1);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, out1, out2;
+ std::tie(out1, out2) = cv::gapi::cartToPolar(in1, in2);
+
+ cv::GComputation c(GIn(in1, in2), GOut(out1, out2));
+ c.apply(gin(in_mat1,in_mat2), gout(out_mat_gapi, out_mat2));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cartToPolar(in_mat1, in_mat2, out_mat_ocv, out_mat_ocv2);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ // Note that we cannot rely on bit-exact sin/cos functions used for this
+ // transform, so we need a threshold for verifying results vs reference.
+ //
+ // Relative threshold like 1e-6 is very restrictive, nearly best we can
+ // expect of single-precision elementary functions implementation.
+ //
+ // However, good idea is making such threshold configurable: parameter
+ // of this test - which a specific test istantiation could setup.
+ //
+ // Note that test instantiation for the OpenCV back-end could even let
+ // the threshold equal to zero, as CV back-end calls the same kernel.
+ //
+ // TODO: Make threshold a configurable parameter of this test (ADE-221)
+
+ cv::Mat &outm = out_mat_gapi,
+ &outa = out_mat2;
+ cv::Mat &refm = out_mat_ocv,
+ &refa = out_mat_ocv2;
+ cv::Mat difm = cv::abs(refm - outm),
+ difa = cv::abs(refa - outa);
+ cv::Mat absm = cv::abs(refm),
+ absa = cv::abs(refa);
+
+ // FIXME: Angle result looks inaccurate at OpenCV
+ // (expected relative accuracy like 1e-6)
+ EXPECT_EQ(0, cv::countNonZero(difm > 1e-6*absm));
+ EXPECT_EQ(0, cv::countNonZero(difa > 1e-3*absa));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(CmpTest, AccuracyTest)
+{
+ CmpTypes opType = CMP_EQ;
+ int type = 0;
+ cv::Size sz;
+ bool testWithScalar = false, initOutMatr = false;
+ cv::GCompileArgs compile_args;
+ std::tie(opType, testWithScalar, type, sz, initOutMatr, compile_args) = GetParam();
+ initMatsRandU(type, sz, CV_8U, initOutMatr);
+
+ // G-API code & corresponding OpenCV code ////////////////////////////////
+ cv::GMat in1, out;
+ if( testWithScalar )
+ {
+ cv::GScalar in2;
+ switch(opType)
+ {
+ case CMP_EQ: out = cv::gapi::cmpEQ(in1, in2); break;
+ case CMP_GT: out = cv::gapi::cmpGT(in1, in2); break;
+ case CMP_GE: out = cv::gapi::cmpGE(in1, in2); break;
+ case CMP_LT: out = cv::gapi::cmpLT(in1, in2); break;
+ case CMP_LE: out = cv::gapi::cmpLE(in1, in2); break;
+ case CMP_NE: out = cv::gapi::cmpNE(in1, in2); break;
+ default: FAIL() << "no such compare operation type for matrix and scalar!";
+ }
+
+ cv::compare(in_mat1, sc, out_mat_ocv, opType);
+
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+ }
+ else
+ {
+ cv::GMat in2;
+ switch(opType)
+ {
+ case CMP_EQ: out = cv::gapi::cmpEQ(in1, in2); break;
+ case CMP_GT: out = cv::gapi::cmpGT(in1, in2); break;
+ case CMP_GE: out = cv::gapi::cmpGE(in1, in2); break;
+ case CMP_LT: out = cv::gapi::cmpLT(in1, in2); break;
+ case CMP_LE: out = cv::gapi::cmpLE(in1, in2); break;
+ case CMP_NE: out = cv::gapi::cmpNE(in1, in2); break;
+ default: FAIL() << "no such compare operation type for two matrices!";
+ }
+
+ cv::compare(in_mat1, in_mat2, out_mat_ocv, opType);
+
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(BitwiseTest, AccuracyTest)
+{
+ bitwiseOp opType = AND;
+ int type = 0;
+ cv::Size sz;
+ bool initOutMatr = false;
+ cv::GCompileArgs compile_args;
+ std::tie(opType, type, sz, initOutMatr, compile_args) = GetParam();
+ initMatsRandU(type, sz, type, initOutMatr);
+
+ // G-API code & corresponding OpenCV code ////////////////////////////////
+ cv::GMat in1, in2, out;
+ switch(opType)
+ {
+ case AND:
+ {
+ out = cv::gapi::bitwise_and(in1, in2);
+ cv::bitwise_and(in_mat1, in_mat2, out_mat_ocv);
+ break;
+ }
+ case OR:
+ {
+ out = cv::gapi::bitwise_or(in1, in2);
+ cv::bitwise_or(in_mat1, in_mat2, out_mat_ocv);
+ break;
+ }
+ case XOR:
+ {
+ out = cv::gapi::bitwise_xor(in1, in2);
+ cv::bitwise_xor(in_mat1, in_mat2, out_mat_ocv);
+ break;
+ }
+ default:
+ {
+ FAIL() << "no such bitwise operation type!";
+ }
+ }
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(NotTest, AccuracyTest)
+{
+ auto param = GetParam();
+ cv::Size sz_in = std::get<1>(param);
+ auto compile_args = std::get<3>(param);
+ initMatrixRandU(std::get<0>(param), sz_in, std::get<0>(param), std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::bitwise_not(in);
+ cv::GComputation c(in, out);
+
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::bitwise_not(in_mat1, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(SelectTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Size sz_in = std::get<1>(param);
+ auto compile_args = std::get<3>(param);
+ initMatsRandU(type, sz_in, type, std::get<2>(param));
+ cv::Mat in_mask(sz_in, CV_8UC1);
+ cv::randu(in_mask, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, in3;
+ auto out = cv::gapi::select(in1, in2, in3);
+ cv::GComputation c(GIn(in1, in2, in3), GOut(out));
+
+ c.apply(gin(in_mat1, in_mat2, in_mask), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ in_mat2.copyTo(out_mat_ocv);
+ in_mat1.copyTo(out_mat_ocv, in_mask);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(MinTest, AccuracyTest)
+{
+ auto param = GetParam();
+ cv::Size sz_in = std::get<1>(param);
+ auto compile_args = std::get<3>(param);
+ initMatsRandU(std::get<0>(param), sz_in, std::get<0>(param), std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::min(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::min(in_mat1, in_mat2, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(MaxTest, AccuracyTest)
+{
+ auto param = GetParam();
+ cv::Size sz_in = std::get<1>(param);
+ auto compile_args = std::get<3>(param);
+ initMatsRandU(std::get<0>(param), sz_in, std::get<0>(param), std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::max(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::max(in_mat1, in_mat2, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(AbsDiffTest, AccuracyTest)
+{
+ auto param = GetParam();
+ cv::Size sz_in = std::get<1>(param);
+ auto compile_args = std::get<3>(param);
+ initMatsRandU(std::get<0>(param), sz_in, std::get<0>(param), std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::absDiff(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::absdiff(in_mat1, in_mat2, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(AbsDiffCTest, AccuracyTest)
+{
+ auto param = GetParam();
+ cv::Size sz_in = std::get<1>(param);
+ auto compile_args = std::get<3>(param);
+ initMatsRandU(std::get<0>(param), sz_in, std::get<0>(param), std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1;
+ cv::GScalar sc1;
+ auto out = cv::gapi::absDiffC(in1, sc1);
+ cv::GComputation c(cv::GIn(in1, sc1), cv::GOut(out));
+
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::absdiff(in_mat1, sc, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(SumTest, AccuracyTest)
+{
+ auto param = GetParam();
+ cv::Size sz_in = std::get<1>(param);
+ auto tolerance = std::get<3>(param);
+ auto compile_args = std::get<4>(param);
+ //initMatrixRandU(std::get<0>(param), sz_in, std::get<2>(param));
+ initMatsRandN(std::get<0>(param), sz_in, std::get<2>(param)); //TODO: workaround trying to fix SumTest failures
+
+
+ cv::Scalar out_sum;
+ cv::Scalar out_sum_ocv;
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::sum(in);
+
+ cv::GComputation c(cv::GIn(in), cv::GOut(out));
+ c.apply(cv::gin(in_mat1), cv::gout(out_sum), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ out_sum_ocv = cv::sum(in_mat1);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_LE(std::abs(out_sum[0] - out_sum_ocv[0]) / std::max(1.0, std::abs(out_sum_ocv[0])), tolerance)
+ << "OCV=" << out_sum_ocv[0] << " GAPI=" << out_sum[0];
+ }
+}
+
+TEST_P(AddWeightedTest, AccuracyTest)
+{
+ int type = 0, dtype = 0;
+ cv::Size sz_in;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ double tolerance = 0.0;
+ std::tie(type, sz_in, dtype, initOut, tolerance, compile_args) = GetParam();
+
+ auto& rng = cv::theRNG();
+ double alpha = rng.uniform(0.0, 1.0);
+ double beta = rng.uniform(0.0, 1.0);
+ double gamma = rng.uniform(0.0, 1.0);
+ initMatsRandU(type, sz_in, dtype, initOut);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::addWeighted(in1, alpha, in2, beta, gamma, dtype);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::addWeighted(in_mat1, alpha, in_mat2, beta, gamma, out_mat_ocv, dtype);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ // Note, that we cannot expect bitwise results for add-weighted:
+ //
+ // tmp = src1*alpha + src2*beta + gamma;
+ // dst = saturate<DST>( round(tmp) );
+ //
+ // Because tmp is floating-point, dst depends on compiler optimizations
+ //
+ // However, we must expect good accuracy of tmp, and rounding correctly
+
+ cv::Mat failures;
+
+ if (out_mat_ocv.type() == CV_32FC1)
+ {
+ // result: float - may vary in 7th decimal digit
+ failures = abs(out_mat_gapi - out_mat_ocv) > abs(out_mat_ocv) * 1e-6;
+ }
+ else
+ {
+ // result: integral - rounding may vary if fractional part of tmp
+ // is nearly 0.5
+
+ cv::Mat inexact, incorrect, diff, tmp;
+
+ inexact = out_mat_gapi != out_mat_ocv;
+
+ // even if rounded differently, check if still rounded correctly
+ cv::addWeighted(in_mat1, alpha, in_mat2, beta, gamma, tmp, CV_32F);
+ cv::subtract(out_mat_gapi, tmp, diff, cv::noArray(), CV_32F);
+ incorrect = abs(diff) >= tolerance;// 0.5000005f; // relative to 6 digits
+
+ failures = inexact & incorrect;
+ }
+
+ EXPECT_EQ(0, cv::countNonZero(failures));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(NormTest, AccuracyTest)
+{
+ NormTypes opType = NORM_INF;
+ int type = 0;
+ cv::Size sz;
+ double tolerance = 0.0;
+ cv::GCompileArgs compile_args;
+ std::tie(opType, type, sz, tolerance, compile_args) = GetParam();
+ initMatrixRandU(type, sz, type, false);
+
+ cv::Scalar out_norm;
+ cv::Scalar out_norm_ocv;
+
+ // G-API code & corresponding OpenCV code ////////////////////////////////
+ cv::GMat in1;
+ cv::GScalar out;
+ switch(opType)
+ {
+ case NORM_L1: out = cv::gapi::normL1(in1); break;
+ case NORM_L2: out = cv::gapi::normL2(in1); break;
+ case NORM_INF: out = cv::gapi::normInf(in1); break;
+ default: FAIL() << "no such norm operation type!";
+ }
+ out_norm_ocv = cv::norm(in_mat1, opType);
+ cv::GComputation c(GIn(in1), GOut(out));
+ c.apply(gin(in_mat1), gout(out_norm), std::move(compile_args));
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_LE(std::abs(out_norm[0] - out_norm_ocv[0]) / std::max(1.0, std::abs(out_norm_ocv[0])), tolerance)
+ << "OCV=" << out_norm_ocv[0] << " GAPI=" << out_norm[0];
+ }
+}
+
+TEST_P(IntegralTest, AccuracyTest)
+{
+ int type = std::get<0>(GetParam());
+ cv::Size sz_in = std::get<1>(GetParam());
+ auto compile_args = std::get<2>(GetParam());
+
+ int type_out = (type == CV_8U) ? CV_32SC1 : CV_64FC1;
+ cv::Mat in_mat1(sz_in, type);
+
+ cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ cv::Size sz_out = cv::Size(sz_in.width + 1, sz_in.height + 1);
+ cv::Mat out_mat1(sz_out, type_out);
+ cv::Mat out_mat_ocv1(sz_out, type_out);
+
+ cv::Mat out_mat2(sz_out, CV_64FC1);
+ cv::Mat out_mat_ocv2(sz_out, CV_64FC1);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, out1, out2;
+ std::tie(out1, out2) = cv::gapi::integral(in1, type_out, CV_64FC1);
+ cv::GComputation c(cv::GIn(in1), cv::GOut(out1, out2));
+
+ c.apply(cv::gin(in_mat1), cv::gout(out_mat1, out_mat2), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::integral(in_mat1, out_mat_ocv1, out_mat_ocv2);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv1 != out_mat1));
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv2 != out_mat2));
+ }
+}
+
+TEST_P(ThresholdTest, AccuracyTestBinary)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Size sz_in = std::get<1>(param);
+ int tt = std::get<2>(param);
+
+ auto compile_args = std::get<4>(param);
+ cv::Scalar thr = initScalarRandU(50);
+ cv::Scalar maxval = initScalarRandU(50) + cv::Scalar(50, 50, 50, 50);
+ initMatrixRandU(type, sz_in, type, std::get<3>(param));
+ cv::Scalar out_scalar;
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar th1, mv1;
+ out = cv::gapi::threshold(in1, th1, mv1, tt);
+ cv::GComputation c(GIn(in1, th1, mv1), GOut(out));
+
+ c.apply(gin(in_mat1, thr, maxval), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::threshold(in_mat1, out_mat_ocv, thr.val[0], maxval.val[0], tt);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ ASSERT_EQ(out_mat_gapi.size(), sz_in);
+ EXPECT_EQ(0, cv::norm(out_mat_ocv, out_mat_gapi, NORM_L1));
+ }
+}
+
+TEST_P(ThresholdOTTest, AccuracyTestOtsu)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Size sz_in = std::get<1>(param);
+ int tt = std::get<2>(param);
+
+ auto compile_args = std::get<4>(param);
+ cv::Scalar maxval = initScalarRandU(50) + cv::Scalar(50, 50, 50, 50);
+ initMatrixRandU(type, sz_in, type, std::get<3>(param));
+ cv::Scalar out_gapi_scalar;
+ double ocv_res;
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, out;
+ cv::GScalar mv1, scout;
+ std::tie<cv::GMat, cv::GScalar>(out, scout) = cv::gapi::threshold(in1, mv1, tt);
+ cv::GComputation c(cv::GIn(in1, mv1), cv::GOut(out, scout));
+
+ c.apply(gin(in_mat1, maxval), gout(out_mat_gapi, out_gapi_scalar), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ ocv_res = cv::threshold(in_mat1, out_mat_ocv, maxval.val[0], maxval.val[0], tt);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ EXPECT_EQ(ocv_res, out_gapi_scalar.val[0]);
+ }
+}
+
+TEST_P(InRangeTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Size sz_in = std::get<1>(param);
+
+ auto compile_args = std::get<3>(param);
+ cv::Scalar thrLow = initScalarRandU(100);
+ cv::Scalar thrUp = initScalarRandU(100) + cv::Scalar(100, 100, 100, 100);
+ initMatrixRandU(type, sz_in, type, std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1;
+ cv::GScalar th1, mv1;
+ auto out = cv::gapi::inRange(in1, th1, mv1);
+ cv::GComputation c(GIn(in1, th1, mv1), GOut(out));
+
+ c.apply(gin(in_mat1, thrLow, thrUp), gout(out_mat_gapi), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::inRange(in_mat1, thrLow, thrUp, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(Split3Test, AccuracyTest)
+{
+ cv::Size sz_in = std::get<0>(GetParam());
+ auto compile_args = std::get<1>(GetParam());
+ initMatrixRandU(CV_8UC3, sz_in, CV_8UC1);
+
+ cv::Mat out_mat2 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat3 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv2 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv3 = cv::Mat(sz_in, CV_8UC1);
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, out1, out2, out3;
+ std::tie(out1, out2, out3) = cv::gapi::split3(in1);
+ cv::GComputation c(cv::GIn(in1), cv::GOut(out1, out2, out3));
+
+ c.apply(cv::gin(in_mat1), cv::gout(out_mat_gapi, out_mat2, out_mat3), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ std::vector<cv::Mat> out_mats_ocv = {out_mat_ocv, out_mat_ocv2, out_mat_ocv3};
+ cv::split(in_mat1, out_mats_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv2 != out_mat2));
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv3 != out_mat3));
+ }
+}
+
+TEST_P(Split4Test, AccuracyTest)
+{
+ cv::Size sz_in = std::get<0>(GetParam());
+ auto compile_args = std::get<1>(GetParam());
+ initMatrixRandU(CV_8UC4, sz_in, CV_8UC1);
+ cv::Mat out_mat2 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat3 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat4 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv2 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv3 = cv::Mat(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv4 = cv::Mat(sz_in, CV_8UC1);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, out1, out2, out3, out4;
+ std::tie(out1, out2, out3, out4) = cv::gapi::split4(in1);
+ cv::GComputation c(cv::GIn(in1), cv::GOut(out1, out2, out3, out4));
+
+ c.apply(cv::gin(in_mat1), cv::gout(out_mat_gapi, out_mat2, out_mat3, out_mat4), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ std::vector<cv::Mat> out_mats_ocv = {out_mat_ocv, out_mat_ocv2, out_mat_ocv3, out_mat_ocv4};
+ cv::split(in_mat1, out_mats_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv2 != out_mat2));
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv3 != out_mat3));
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv4 != out_mat4));
+ }
+}
+
+static void ResizeAccuracyTest(compare_f cmpF, int type, int interp, cv::Size sz_in, cv::Size sz_out, double fx, double fy, cv::GCompileArgs&& compile_args)
+{
+ cv::Mat in_mat1 (sz_in, type );
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+
+ auto out_mat_sz = sz_out.area() == 0 ? cv::Size(saturate_cast<int>(sz_in.width *fx),
+ saturate_cast<int>(sz_in.height*fy))
+ : sz_out;
+ cv::Mat out_mat(out_mat_sz, type);
+ cv::Mat out_mat_ocv(out_mat_sz, type);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::resize(in, sz_out, fx, fy, interp);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::resize(in_mat1, out_mat_ocv, sz_out, fx, fy, interp);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat, out_mat_ocv));
+ }
+}
+
+TEST_P(ResizeTest, AccuracyTest)
+{
+ compare_f cmpF;
+ int type = 0, interp = 0;
+ cv::Size sz_in, sz_out;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, interp, sz_in, sz_out, compile_args) = GetParam();
+ ResizeAccuracyTest(cmpF, type, interp, sz_in, sz_out, 0.0, 0.0, std::move(compile_args));
+}
+
+TEST_P(ResizeTestFxFy, AccuracyTest)
+{
+ compare_f cmpF;
+ int type = 0, interp = 0;
+ cv::Size sz_in;
+ double fx = 0.0, fy = 0.0;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, interp, sz_in, fx, fy, compile_args) = GetParam();
+ ResizeAccuracyTest(cmpF, type, interp, sz_in, cv::Size{0, 0}, fx, fy, std::move(compile_args));
+}
+
+TEST_P(Merge3Test, AccuracyTest)
+{
+ cv::Size sz_in = std::get<0>(GetParam());
+ initMatsRandU(CV_8UC1, sz_in, CV_8UC3);
+ auto compile_args = std::get<1>(GetParam());
+ cv::Mat in_mat3(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat3, mean, stddev);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, in3;
+ auto out = cv::gapi::merge3(in1, in2, in3);
+
+ cv::GComputation c(cv::GIn(in1, in2, in3), cv::GOut(out));
+ c.apply(cv::gin(in_mat1, in_mat2, in_mat3), cv::gout(out_mat_gapi), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ std::vector<cv::Mat> in_mats_ocv = {in_mat1, in_mat2, in_mat3};
+ cv::merge(in_mats_ocv, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ }
+}
+
+TEST_P(Merge4Test, AccuracyTest)
+{
+ cv::Size sz_in = std::get<0>(GetParam());
+ initMatsRandU(CV_8UC1, sz_in, CV_8UC4);
+ auto compile_args = std::get<1>(GetParam());
+ cv::Mat in_mat3(sz_in, CV_8UC1);
+ cv::Mat in_mat4(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat3, mean, stddev);
+ cv::randn(in_mat4, mean, stddev);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2, in3, in4;
+ auto out = cv::gapi::merge4(in1, in2, in3, in4);
+
+ cv::GComputation c(cv::GIn(in1, in2, in3, in4), cv::GOut(out));
+ c.apply(cv::gin(in_mat1, in_mat2, in_mat3, in_mat4), cv::gout(out_mat_gapi), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ std::vector<cv::Mat> in_mats_ocv = {in_mat1, in_mat2, in_mat3, in_mat4};
+ cv::merge(in_mats_ocv, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ }
+}
+
+TEST_P(RemapTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Size sz_in = std::get<1>(param);
+ auto compile_args = std::get<3>(param);
+ initMatrixRandU(type, sz_in, type, std::get<2>(param));
+ cv::Mat in_map1(sz_in, CV_16SC2);
+ cv::Mat in_map2 = cv::Mat();
+ cv::randu(in_map1, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::Scalar bv = cv::Scalar();
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1;
+ auto out = cv::gapi::remap(in1, in_map1, in_map2, cv::INTER_NEAREST, cv::BORDER_REPLICATE, bv);
+ cv::GComputation c(in1, out);
+
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::remap(in_mat1, out_mat_ocv, in_map1, in_map2, cv::INTER_NEAREST, cv::BORDER_REPLICATE, bv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(FlipTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ int flipCode = std::get<1>(param);
+ cv::Size sz_in = std::get<2>(param);
+ initMatrixRandU(type, sz_in, type, false);
+ auto compile_args = std::get<4>(GetParam());
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::flip(in, flipCode);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::flip(in_mat1, out_mat_ocv, flipCode);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(CropTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Rect rect_to = std::get<1>(param);
+ cv::Size sz_in = std::get<2>(param);
+ auto compile_args = std::get<4>(param);
+
+ initMatrixRandU(type, sz_in, type, false);
+ cv::Size sz_out = cv::Size(rect_to.width, rect_to.height);
+ if( std::get<3>(param) == true )
+ {
+ out_mat_gapi = cv::Mat(sz_out, type);
+ out_mat_ocv = cv::Mat(sz_out, type);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::crop(in, rect_to);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::Mat(in_mat1, rect_to).copyTo(out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_out);
+ }
+}
+
+TEST_P(ConcatHorTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Size sz_out = std::get<1>(param);
+ auto compile_args = std::get<2>(param);
+
+ int wpart = sz_out.width / 4;
+ cv::Size sz_in1 = cv::Size(wpart, sz_out.height);
+ cv::Size sz_in2 = cv::Size(sz_out.width - wpart, sz_out.height);
+
+ cv::Mat in_mat1 (sz_in1, type );
+ cv::Mat in_mat2 (sz_in2, type);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+ cv::randn(in_mat2, mean, stddev);
+
+ cv::Mat out_mat(sz_out, type);
+ cv::Mat out_mat_ocv(sz_out, type);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::concatHor(in1, in2);
+
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::hconcat(in_mat1, in_mat2, out_mat_ocv );
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat));
+ }
+}
+
+TEST_P(ConcatVertTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Size sz_out = std::get<1>(param);
+ auto compile_args = std::get<2>(param);
+
+ int hpart = sz_out.height * 2/3;
+ cv::Size sz_in1 = cv::Size(sz_out.width, hpart);
+ cv::Size sz_in2 = cv::Size(sz_out.width, sz_out.height - hpart);
+
+ cv::Mat in_mat1 (sz_in1, type);
+ cv::Mat in_mat2 (sz_in2, type);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+ cv::randn(in_mat2, mean, stddev);
+
+ cv::Mat out_mat(sz_out, type);
+ cv::Mat out_mat_ocv(sz_out, type);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in1, in2;
+ auto out = cv::gapi::concatVert(in1, in2);
+
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::vconcat(in_mat1, in_mat2, out_mat_ocv );
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat));
+ }
+}
+
+TEST_P(ConcatVertVecTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Size sz_out = std::get<1>(param);
+ auto compile_args = std::get<2>(param);
+
+ int hpart1 = sz_out.height * 2/5;
+ int hpart2 = sz_out.height / 5;
+ cv::Size sz_in1 = cv::Size(sz_out.width, hpart1);
+ cv::Size sz_in2 = cv::Size(sz_out.width, hpart2);
+ cv::Size sz_in3 = cv::Size(sz_out.width, sz_out.height - hpart1 - hpart2);
+
+ cv::Mat in_mat1 (sz_in1, type);
+ cv::Mat in_mat2 (sz_in2, type);
+ cv::Mat in_mat3 (sz_in3, type);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+ cv::randn(in_mat2, mean, stddev);
+ cv::randn(in_mat3, mean, stddev);
+
+ cv::Mat out_mat(sz_out, type);
+ cv::Mat out_mat_ocv(sz_out, type);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ std::vector <cv::GMat> mats(3);
+ auto out = cv::gapi::concatVert(mats);
+
+ std::vector <cv::Mat> cvmats = {in_mat1, in_mat2, in_mat3};
+
+ cv::GComputation c({mats[0], mats[1], mats[2]}, {out});
+ c.apply(gin(in_mat1, in_mat2, in_mat3), gout(out_mat), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::vconcat(cvmats, out_mat_ocv );
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat));
+ }
+}
+
+TEST_P(ConcatHorVecTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type = std::get<0>(param);
+ cv::Size sz_out = std::get<1>(param);
+ auto compile_args = std::get<2>(param);
+
+ int wpart1 = sz_out.width / 3;
+ int wpart2 = sz_out.width / 4;
+ cv::Size sz_in1 = cv::Size(wpart1, sz_out.height);
+ cv::Size sz_in2 = cv::Size(wpart2, sz_out.height);
+ cv::Size sz_in3 = cv::Size(sz_out.width - wpart1 - wpart2, sz_out.height);
+
+ cv::Mat in_mat1 (sz_in1, type);
+ cv::Mat in_mat2 (sz_in2, type);
+ cv::Mat in_mat3 (sz_in3, type);
+ cv::Scalar mean = cv::Scalar::all(127);
+ cv::Scalar stddev = cv::Scalar::all(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+ cv::randn(in_mat2, mean, stddev);
+ cv::randn(in_mat3, mean, stddev);
+
+ cv::Mat out_mat(sz_out, type);
+ cv::Mat out_mat_ocv(sz_out, type);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ std::vector <cv::GMat> mats(3);
+ auto out = cv::gapi::concatHor(mats);
+
+ std::vector <cv::Mat> cvmats = {in_mat1, in_mat2, in_mat3};
+
+ cv::GComputation c({mats[0], mats[1], mats[2]}, {out});
+ c.apply(gin(in_mat1, in_mat2, in_mat3), gout(out_mat), std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::hconcat(cvmats, out_mat_ocv );
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat));
+ }
+}
+
+TEST_P(LUTTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type_mat = std::get<0>(param);
+ int type_lut = std::get<1>(param);
+ int type_out = CV_MAKETYPE(CV_MAT_DEPTH(type_lut), CV_MAT_CN(type_mat));
+ cv::Size sz_in = std::get<2>(param);
+ auto compile_args = std::get<4>(GetParam());
+
+ initMatrixRandU(type_mat, sz_in, type_out);
+ cv::Size sz_lut = cv::Size(1, 256);
+ cv::Mat in_lut(sz_lut, type_lut);
+ cv::randu(in_lut, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::LUT(in, in_lut);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::LUT(in_mat1, in_lut, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(ConvertToTest, AccuracyTest)
+{
+ auto param = GetParam();
+ int type_mat = std::get<0>(param);
+ int depth_to = std::get<1>(param);
+ cv::Size sz_in = std::get<2>(param);
+ int type_out = CV_MAKETYPE(depth_to, CV_MAT_CN(type_mat));
+ initMatrixRandU(type_mat, sz_in, type_out);
+ auto compile_args = std::get<3>(GetParam());
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::convertTo(in, depth_to);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ in_mat1.convertTo(out_mat_ocv, depth_to);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+
+TEST_P(PhaseTest, AccuracyTest)
+{
+ int img_type = -1;
+ cv::Size img_size;
+ bool angle_in_degrees = false;
+ cv::GCompileArgs compile_args;
+ std::tie(img_type, img_size, angle_in_degrees, compile_args) = GetParam();
+ initMatsRandU(img_type, img_size, img_type);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in_x, in_y;
+ auto out = cv::gapi::phase(in_x, in_y, angle_in_degrees);
+
+ cv::GComputation c(in_x, in_y, out);
+ c.apply(in_mat1, in_mat2, out_mat_gapi, std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ cv::phase(in_mat1, in_mat2, out_mat_ocv, angle_in_degrees);
+
+ // Comparison //////////////////////////////////////////////////////////////
+ // FIXME: use a comparison functor instead (after enabling OpenCL)
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ }
+}
+
+TEST_P(SqrtTest, AccuracyTest)
+{
+ int img_type = -1;
+ cv::Size img_size;
+ cv::GCompileArgs compile_args;
+ std::tie(img_type, img_size, compile_args) = GetParam();
+ initMatrixRandU(img_type, img_size, img_type);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::sqrt(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ cv::sqrt(in_mat1, out_mat_ocv);
+
+ // Comparison //////////////////////////////////////////////////////////////
+ // FIXME: use a comparison functor instead (after enabling OpenCL)
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ }
+}
+
+
+} // opencv_test
+
+#endif //OPENCV_GAPI_CORE_TESTS_INL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests.cpp
new file mode 100644
index 000000000..b7c027908
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests.cpp
@@ -0,0 +1,9 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "gapi_imgproc_tests_inl.hpp"
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests.hpp
new file mode 100644
index 000000000..c21b26b68
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests.hpp
@@ -0,0 +1,42 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_IMGPROC_TESTS_HPP
+#define OPENCV_GAPI_IMGPROC_TESTS_HPP
+
+#include <iostream>
+
+#include "gapi_tests_common.hpp"
+
+namespace opencv_test
+{
+
+struct Filter2DTest : public TestParams <std::tuple<compare_f, MatType,int,cv::Size,int,int,bool,cv::GCompileArgs>> {};
+struct BoxFilterTest : public TestParams <std::tuple<compare_f,MatType,int,cv::Size,int,int,bool,cv::GCompileArgs>> {};
+struct SepFilterTest : public TestParams <std::tuple<compare_f,MatType,int,cv::Size,int,bool,cv::GCompileArgs>> {};
+struct BlurTest : public TestParams <std::tuple<compare_f,MatType,int,cv::Size,int,bool,cv::GCompileArgs>> {};
+struct GaussianBlurTest : public TestParams <std::tuple<compare_f,MatType,int,cv::Size,bool,cv::GCompileArgs>> {};
+struct MedianBlurTest : public TestParams <std::tuple<compare_f,MatType,int,cv::Size,bool,cv::GCompileArgs>> {};
+struct ErodeTest : public TestParams <std::tuple<compare_f,MatType,int,cv::Size,int,bool,cv::GCompileArgs>> {};
+struct Erode3x3Test : public TestParams <std::tuple<compare_f,MatType,cv::Size,bool,int,cv::GCompileArgs>> {};
+struct DilateTest : public TestParams <std::tuple<compare_f,MatType,int,cv::Size,int,bool,cv::GCompileArgs>> {};
+struct Dilate3x3Test : public TestParams <std::tuple<compare_f,MatType,cv::Size,bool,int,cv::GCompileArgs>> {};
+struct SobelTest : public TestParams <std::tuple<compare_f,MatType,int,cv::Size,int,int,int,bool,cv::GCompileArgs>> {};
+struct EqHistTest : public TestParams <std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct CannyTest : public TestParams <std::tuple<compare_f,MatType,cv::Size,double,double,int,bool,bool,cv::GCompileArgs>> {};
+struct RGB2GrayTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct BGR2GrayTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct RGB2YUVTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct YUV2RGBTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct RGB2LabTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct BGR2LUVTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct LUV2BGRTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct BGR2YUVTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct YUV2BGRTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+} // opencv_test
+
+#endif //OPENCV_GAPI_IMGPROC_TESTS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp
new file mode 100644
index 000000000..3de428922
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp
@@ -0,0 +1,630 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_IMGPROC_TESTS_INL_HPP
+#define OPENCV_GAPI_IMGPROC_TESTS_INL_HPP
+
+#include "opencv2/gapi/imgproc.hpp"
+#include "gapi_imgproc_tests.hpp"
+
+namespace opencv_test
+{
+TEST_P(Filter2DTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, borderType = 0, dtype = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, borderType, dtype, initOut, compile_args) = GetParam();
+ initMatsRandN(type, sz, dtype, initOut);
+
+ cv::Point anchor = {-1, -1};
+ double delta = 0;
+
+ cv::Mat kernel = cv::Mat(kernSize, kernSize, CV_32FC1 );
+ cv::Scalar kernMean = cv::Scalar(1.0);
+ cv::Scalar kernStddev = cv::Scalar(2.0/3);
+ randn(kernel, kernMean, kernStddev);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::filter2D(in, dtype, kernel, anchor, delta, borderType);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::filter2D(in_mat1, out_mat_ocv, dtype, kernel, anchor, delta, borderType);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(BoxFilterTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int filterSize = 0, borderType = 0, dtype = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, filterSize, sz, borderType, dtype, initOut, compile_args) = GetParam();
+ initMatsRandN(type, sz, dtype, initOut);
+
+ cv::Point anchor = {-1, -1};
+ bool normalize = true;
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::boxFilter(in, dtype, cv::Size(filterSize, filterSize), anchor, normalize, borderType);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::boxFilter(in_mat1, out_mat_ocv, dtype, cv::Size(filterSize, filterSize), anchor, normalize, borderType);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(SepFilterTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, dtype = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, dtype, initOut, compile_args) = GetParam();
+
+ cv::Mat kernelX(kernSize, 1, CV_32F);
+ cv::Mat kernelY(kernSize, 1, CV_32F);
+ randu(kernelX, -1, 1);
+ randu(kernelY, -1, 1);
+ initMatsRandN(type, sz, dtype, initOut);
+
+ cv::Point anchor = cv::Point(-1, -1);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::sepFilter(in, dtype, kernelX, kernelY, anchor, cv::Scalar() );
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::sepFilter2D(in_mat1, out_mat_ocv, dtype, kernelX, kernelY );
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(BlurTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int filterSize = 0, borderType = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, filterSize, sz, borderType, initOut, compile_args) = GetParam();
+ initMatsRandN(type, sz, type, initOut);
+
+ cv::Point anchor = {-1, -1};
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::blur(in, cv::Size(filterSize, filterSize), anchor, borderType);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::blur(in_mat1, out_mat_ocv, cv::Size(filterSize, filterSize), anchor, borderType);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(GaussianBlurTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF,type, kernSize, sz, initOut, compile_args) = GetParam();
+ initMatsRandN(type, sz, type, initOut);
+
+ cv::Size kSize = cv::Size(kernSize, kernSize);
+ double sigmaX = rand();
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::gaussianBlur(in, kSize, sigmaX);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::GaussianBlur(in_mat1, out_mat_ocv, kSize, sigmaX);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(MedianBlurTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, initOut, compile_args) = GetParam();
+ initMatsRandN(type, sz, type, initOut);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::medianBlur(in, kernSize);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::medianBlur(in_mat1, out_mat_ocv, kernSize);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(ErodeTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, kernType = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, kernType, initOut, compile_args) = GetParam();
+ initMatsRandN(type, sz, type, initOut);
+
+ cv::Mat kernel = cv::getStructuringElement(kernType, cv::Size(kernSize, kernSize));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::erode(in, kernel);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::erode(in_mat1, out_mat_ocv, kernel);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(Erode3x3Test, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int numIters = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, sz, initOut, numIters, compile_args) = GetParam();
+ initMatsRandN(type, sz, type, initOut);
+
+ cv::Mat kernel = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(3,3));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::erode3x3(in, numIters);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::erode(in_mat1, out_mat_ocv, kernel, cv::Point(-1, -1), numIters);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(DilateTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, kernType = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, kernType, initOut, compile_args) = GetParam();
+ initMatsRandN(type, sz, type, initOut);
+
+ cv::Mat kernel = cv::getStructuringElement(kernType, cv::Size(kernSize, kernSize));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::dilate(in, kernel);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::dilate(in_mat1, out_mat_ocv, kernel);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(Dilate3x3Test, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int numIters = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, sz, initOut, numIters, compile_args) = GetParam();
+ initMatsRandN(type, sz, type, initOut);
+
+ cv::Mat kernel = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(3,3));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::dilate3x3(in, numIters);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::dilate(in_mat1, out_mat_ocv, kernel, cv::Point(-1,-1), numIters);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+
+TEST_P(SobelTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type = 0;
+ int kernSize = 0, dtype = 0, dx = 0, dy = 0;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, kernSize, sz, dtype, dx, dy, initOut, compile_args) = GetParam();
+ initMatsRandN(type, sz, dtype, initOut);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::Sobel(in, dtype, dx, dy, kernSize );
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::Sobel(in_mat1, out_mat_ocv, dtype, dx, dy, kernSize);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(EqHistTest, AccuracyTest)
+{
+ compare_f cmpF;
+ cv::Size sz;
+ bool initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, sz, initOut, compile_args) = GetParam();
+ initMatsRandN(CV_8UC1, sz, CV_8UC1, initOut);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::equalizeHist(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::equalizeHist(in_mat1, out_mat_ocv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(GetParam()));
+ }
+}
+
+TEST_P(CannyTest, AccuracyTest)
+{
+ compare_f cmpF;
+ MatType type;
+ int apSize = 0;
+ double thrLow = 0.0, thrUp = 0.0;
+ cv::Size sz;
+ bool l2gr = false, initOut = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, type, sz, thrLow, thrUp, apSize, l2gr, initOut, compile_args) = GetParam();
+
+ initMatsRandN(type, sz, CV_8UC1, initOut);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::Canny(in, thrLow, thrUp, apSize, l2gr);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::Canny(in_mat1, out_mat_ocv, thrLow, thrUp, apSize, l2gr);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(RGB2GrayTest, AccuracyTest)
+{
+ auto param = GetParam();
+ auto compile_args = std::get<3>(param);
+ compare_f cmpF = std::get<0>(param);
+ initMatsRandN(CV_8UC3, std::get<1>(param), CV_8UC1, std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::RGB2Gray(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_RGB2GRAY);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param));
+ }
+}
+
+TEST_P(BGR2GrayTest, AccuracyTest)
+{
+ auto param = GetParam();
+ auto compile_args = std::get<3>(param);
+ compare_f cmpF = std::get<0>(param);
+ initMatsRandN(CV_8UC3, std::get<1>(param), CV_8UC1, std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::BGR2Gray(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_BGR2GRAY);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param));
+ }
+}
+
+TEST_P(RGB2YUVTest, AccuracyTest)
+{
+ auto param = GetParam();
+ auto compile_args = std::get<3>(param);
+ compare_f cmpF = std::get<0>(param);
+ initMatsRandN(CV_8UC3, std::get<1>(param), CV_8UC3, std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::RGB2YUV(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_RGB2YUV);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param));
+ }
+}
+
+TEST_P(YUV2RGBTest, AccuracyTest)
+{
+ auto param = GetParam();
+ auto compile_args = std::get<3>(param);
+ compare_f cmpF = std::get<0>(param);
+ initMatsRandN(CV_8UC3, std::get<1>(param), CV_8UC3, std::get<2>(param));
+
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::YUV2RGB(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_YUV2RGB);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param));
+ }
+}
+
+TEST_P(RGB2LabTest, AccuracyTest)
+{
+ auto param = GetParam();
+ auto compile_args = std::get<3>(param);
+ compare_f cmpF = std::get<0>(param);
+ initMatsRandN(CV_8UC3, std::get<1>(param), CV_8UC3, std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::RGB2Lab(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_RGB2Lab);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param));
+ }
+}
+
+TEST_P(BGR2LUVTest, AccuracyTest)
+{
+ auto param = GetParam();
+ auto compile_args = std::get<3>(param);
+ compare_f cmpF = std::get<0>(param);
+ initMatsRandN(CV_8UC3, std::get<1>(param), CV_8UC3, std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::BGR2LUV(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_BGR2Luv);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param));
+ }
+}
+
+TEST_P(LUV2BGRTest, AccuracyTest)
+{
+ auto param = GetParam();
+ auto compile_args = std::get<3>(param);
+ compare_f cmpF = std::get<0>(param);
+ initMatsRandN(CV_8UC3, std::get<1>(param), CV_8UC3, std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::LUV2BGR(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_Luv2BGR);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param));
+ }
+}
+
+TEST_P(BGR2YUVTest, AccuracyTest)
+{
+ auto param = GetParam();
+ auto compile_args = std::get<3>(param);
+ compare_f cmpF = std::get<0>(param);
+ initMatsRandN(CV_8UC3, std::get<1>(param), CV_8UC3, std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::BGR2YUV(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_BGR2YUV);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param));
+ }
+}
+
+TEST_P(YUV2BGRTest, AccuracyTest)
+{
+ auto param = GetParam();
+ auto compile_args = std::get<3>(param);
+ compare_f cmpF = std::get<0>(param);
+ initMatsRandN(CV_8UC3, std::get<1>(param), CV_8UC3, std::get<2>(param));
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = cv::gapi::YUV2BGR(in);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColor(in_mat1, out_mat_ocv, cv::COLOR_YUV2BGR);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param));
+ }
+}
+} // opencv_test
+
+#endif //OPENCV_GAPI_IMGPROC_TESTS_INL_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests.cpp
new file mode 100644
index 000000000..1f6f0ce20
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests.cpp
@@ -0,0 +1,9 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "gapi_operators_tests_inl.hpp"
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests.hpp
new file mode 100644
index 000000000..9f53d3685
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests.hpp
@@ -0,0 +1,192 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_OPERATOR_TESTS_COMMON_HPP
+#define OPENCV_GAPI_OPERATOR_TESTS_COMMON_HPP
+
+#include "gapi_tests_common.hpp"
+
+namespace opencv_test
+{
+
+struct g_api_ocv_pair_mat_scalar {
+ using g_api_function_t = std::function<cv::GMat(cv::GMat,cv::GScalar)>;
+ using ocv_function_t = std::function<void(cv::Mat const&, cv::Scalar, cv::Mat&)>;
+
+ std::string name;
+ g_api_function_t g_api_function;
+ ocv_function_t ocv_function;
+
+
+ g_api_ocv_pair_mat_scalar(std::string const& n, g_api_function_t const& g, ocv_function_t const& o)
+ : name(n), g_api_function(g), ocv_function(o) {}
+
+ g_api_ocv_pair_mat_scalar() = default;
+
+ friend std::ostream& operator<<(std::ostream& o, const g_api_ocv_pair_mat_scalar& p)
+ {
+ return o<<p.name;
+ }
+};
+
+struct g_api_ocv_pair_mat_mat {
+ using g_api_function_t = std::function<cv::GMat(cv::GMat,cv::GMat)>;
+ using ocv_function_t = std::function<void(cv::Mat const&, cv::Mat const&, cv::Mat&)>;
+
+ std::string name;
+ g_api_function_t g_api_function;
+ ocv_function_t ocv_function;
+
+
+ g_api_ocv_pair_mat_mat(std::string const& n, g_api_function_t const& g, ocv_function_t const& o)
+ : name(n), g_api_function(g), ocv_function(o) {}
+
+ g_api_ocv_pair_mat_mat() = default;
+
+ friend std::ostream& operator<<(std::ostream& o, const g_api_ocv_pair_mat_mat& p)
+ {
+ return o<<p.name;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// FIXME: Please refactor this test to a template test (T,U) with enum (OP)
+//
+////////////////////////////////////////////////////////////////////////////////
+namespace
+{
+
+
+//declare test cases for matrix and scalar operators
+g_api_ocv_pair_mat_scalar opPlus = {std::string{"operator+"},
+ [](cv::GMat in,cv::GScalar c){return in+c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::add(in, c, out);}};
+g_api_ocv_pair_mat_scalar opPlusR = {std::string{"rev_operator+"},
+ [](cv::GMat in,cv::GScalar c){return c+in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::add(c, in, out);}};
+g_api_ocv_pair_mat_scalar opMinus = {std::string{"operator-"},
+ [](cv::GMat in,cv::GScalar c){return in-c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::subtract(in, c, out);}};
+g_api_ocv_pair_mat_scalar opMinusR = {std::string{"rev_operator-"},
+ [](cv::GMat in,cv::GScalar c){return c-in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::subtract(c, in, out);}};
+g_api_ocv_pair_mat_scalar opMul = {std::string{"operator*"},
+ [](cv::GMat in,cv::GScalar c){return in*c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::multiply(in, c, out);}};
+g_api_ocv_pair_mat_scalar opMulR = {std::string{"rev_operator*"},
+ [](cv::GMat in,cv::GScalar c){return c*in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::multiply(c, in, out);}};
+g_api_ocv_pair_mat_scalar opDiv = {std::string{"operator/"},
+ [](cv::GMat in,cv::GScalar c){return in/c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::divide(in, c, out);}};
+g_api_ocv_pair_mat_scalar opDivR = {std::string{"rev_operator/"},
+ [](cv::GMat in,cv::GScalar c){return c/in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::divide(c, in, out);}};
+
+g_api_ocv_pair_mat_scalar opGT = {std::string{"operator>"},
+ [](cv::GMat in,cv::GScalar c){return in>c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_GT);}};
+g_api_ocv_pair_mat_scalar opLT = {std::string{"operator<"},
+ [](cv::GMat in,cv::GScalar c){return in<c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_LT);}};
+g_api_ocv_pair_mat_scalar opGE = {std::string{"operator>="},
+ [](cv::GMat in,cv::GScalar c){return in>=c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_GE);}};
+g_api_ocv_pair_mat_scalar opLE = {std::string{"operator<="},
+ [](cv::GMat in,cv::GScalar c){return in<=c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_LE);}};
+g_api_ocv_pair_mat_scalar opEQ = {std::string{"operator=="},
+ [](cv::GMat in,cv::GScalar c){return in==c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_EQ);}};
+g_api_ocv_pair_mat_scalar opNE = {std::string{"operator!="},
+ [](cv::GMat in,cv::GScalar c){return in!=c;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(in, c, out,cv::CMP_NE);}};
+g_api_ocv_pair_mat_scalar opGTR = {std::string{"rev_operator>"},
+ [](cv::GMat in,cv::GScalar c){return c>in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_GT);}};
+g_api_ocv_pair_mat_scalar opLTR = {std::string{"rev_operator<"},
+ [](cv::GMat in,cv::GScalar c){return c<in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_LT);}};
+g_api_ocv_pair_mat_scalar opGER = {std::string{"rev_operator>="},
+ [](cv::GMat in,cv::GScalar c){return c>=in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_GE);}};
+g_api_ocv_pair_mat_scalar opLER = {std::string{"rev_operator<="},
+ [](cv::GMat in,cv::GScalar c){return c<=in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_LE);}};
+g_api_ocv_pair_mat_scalar opEQR = {std::string{"rev_operator=="},
+ [](cv::GMat in,cv::GScalar c){return c==in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_EQ);}};
+g_api_ocv_pair_mat_scalar opNER = {std::string{"rev_operator!="},
+ [](cv::GMat in,cv::GScalar c){return c!=in;},
+ [](const cv::Mat& in, cv::Scalar c, cv::Mat& out){cv::compare(c, in, out,cv::CMP_NE);}};
+
+g_api_ocv_pair_mat_scalar opAND = {std::string{"operator&"},
+ [](cv::GMat in1,cv::GScalar in2){return in1&in2;},
+ [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_and(in1, in2, out);}};
+g_api_ocv_pair_mat_scalar opOR = {std::string{"operator|"},
+ [](cv::GMat in1,cv::GScalar in2){return in1|in2;},
+ [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_or(in1, in2, out);}};
+g_api_ocv_pair_mat_scalar opXOR = {std::string{"operator^"},
+ [](cv::GMat in1,cv::GScalar in2){return in1^in2;},
+ [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_xor(in1, in2, out);}};
+g_api_ocv_pair_mat_scalar opANDR = {std::string{"rev_operator&"},
+ [](cv::GMat in1,cv::GScalar in2){return in2&in1;},
+ [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_and(in2, in1, out);}};
+g_api_ocv_pair_mat_scalar opORR = {std::string{"rev_operator|"},
+ [](cv::GMat in1,cv::GScalar in2){return in2|in1;},
+ [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_or(in2, in1, out);}};
+g_api_ocv_pair_mat_scalar opXORR = {std::string{"rev_operator^"},
+ [](cv::GMat in1,cv::GScalar in2){return in2^in1;},
+ [](const cv::Mat& in1, const cv::Scalar& in2, cv::Mat& out){cv::bitwise_xor(in2, in1, out);}};
+
+// declare test cases for matrix and matrix operators
+g_api_ocv_pair_mat_mat opPlusM = {std::string{"operator+"},
+ [](cv::GMat in1,cv::GMat in2){return in1+in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::add(in1, in2, out);}};
+g_api_ocv_pair_mat_mat opMinusM = {std::string{"operator-"},
+ [](cv::GMat in,cv::GMat in2){return in-in2;},
+ [](const cv::Mat& in, const cv::Mat& in2, cv::Mat& out){cv::subtract(in, in2, out);}};
+g_api_ocv_pair_mat_mat opDivM = {std::string{"operator/"},
+ [](cv::GMat in,cv::GMat in2){return in/in2;},
+ [](const cv::Mat& in, const cv::Mat& in2, cv::Mat& out){cv::divide(in, in2, out);}};
+g_api_ocv_pair_mat_mat opGreater = {std::string{"operator>"},
+ [](cv::GMat in1,cv::GMat in2){return in1>in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_GT);}};
+g_api_ocv_pair_mat_mat opGreaterEq = {std::string{"operator>="},
+ [](cv::GMat in1,cv::GMat in2){return in1>=in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_GE);}};
+g_api_ocv_pair_mat_mat opLess = {std::string{"operator<"},
+ [](cv::GMat in1,cv::GMat in2){return in1<in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_LT);}};
+g_api_ocv_pair_mat_mat opLessEq = {std::string{"operator<="},
+ [](cv::GMat in1,cv::GMat in2){return in1<=in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_LE);}};
+g_api_ocv_pair_mat_mat opEq = {std::string{"operator=="},
+ [](cv::GMat in1,cv::GMat in2){return in1==in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_EQ);}};
+g_api_ocv_pair_mat_mat opNotEq = {std::string{"operator!="},
+ [](cv::GMat in1,cv::GMat in2){return in1!=in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::compare(in1, in2, out, cv::CMP_NE);}};
+
+g_api_ocv_pair_mat_mat opAnd = {std::string{"operator&"},
+ [](cv::GMat in1,cv::GMat in2){return in1&in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::bitwise_and(in1, in2, out);}};
+g_api_ocv_pair_mat_mat opOr = {std::string{"operator|"},
+ [](cv::GMat in1,cv::GMat in2){return in1|in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::bitwise_or(in1, in2, out);}};
+g_api_ocv_pair_mat_mat opXor = {std::string{"operator^"},
+ [](cv::GMat in1,cv::GMat in2){return in1^in2;},
+ [](const cv::Mat& in1, const cv::Mat& in2, cv::Mat& out){cv::bitwise_xor(in1, in2, out);}};
+
+} // anonymous namespace
+struct MathOperatorMatScalarTest : public TestParams<std::tuple<compare_f, g_api_ocv_pair_mat_scalar,int,cv::Size,int,bool,cv::GCompileArgs>>{};
+struct MathOperatorMatMatTest : public TestParams<std::tuple<compare_f, g_api_ocv_pair_mat_mat,int,cv::Size,int,bool,cv::GCompileArgs>>{};
+struct NotOperatorTest : public TestParams<std::tuple<int,cv::Size,bool,cv::GCompileArgs>> {};
+} // opencv_test
+
+#endif // OPENCV_GAPI_OPERATOR_TESTS_COMMON_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests_inl.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests_inl.hpp
new file mode 100644
index 000000000..7ec702ae9
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_operators_tests_inl.hpp
@@ -0,0 +1,104 @@
+// 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) 2018 Intel Corporation
+
+
+#ifndef OPENCV_GAPI_OPERATOR_TESTS_INL_COMMON_HPP
+#define OPENCV_GAPI_OPERATOR_TESTS_INL_COMMON_HPP
+
+#include "gapi_operators_tests.hpp"
+
+namespace opencv_test
+{
+TEST_P(MathOperatorMatScalarTest, OperatorAccuracyTest )
+{
+ compare_f cmpF;
+ g_api_ocv_pair_mat_scalar op;
+ int type = 0, dtype = 0;
+ cv::Size sz;
+ bool initOutMatr = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, op, type, sz, dtype, initOutMatr, compile_args) = GetParam();
+ initMatsRandU(type, sz, dtype, initOutMatr);
+
+ auto fun_gapi = op.g_api_function;
+ auto fun_ocv = op.ocv_function ;
+
+ // G-API code & corresponding OpenCV code ////////////////////////////////
+
+ cv::GMat in1;
+ cv::GScalar in2;
+ auto out = fun_gapi(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ c.apply(gin(in_mat1, sc), gout(out_mat_gapi), std::move(compile_args));
+
+ fun_ocv(in_mat1, sc, out_mat_ocv);
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(MathOperatorMatMatTest, OperatorAccuracyTest )
+{
+ compare_f cmpF;
+ g_api_ocv_pair_mat_mat op;
+ int type = 0, dtype = 0;
+ cv::Size sz;
+ bool initOutMatr = false;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, op, type, sz, dtype, initOutMatr, compile_args) = GetParam();
+ initMatsRandU(type, sz, dtype, initOutMatr);
+
+ auto fun_gapi = op.g_api_function;
+ auto fun_ocv = op.ocv_function ;
+
+ // G-API code & corresponding OpenCV code ////////////////////////////////
+
+ cv::GMat in1;
+ cv::GMat in2;
+ auto out = fun_gapi(in1, in2);
+ cv::GComputation c(GIn(in1, in2), GOut(out));
+
+ c.apply(gin(in_mat1, in_mat2), gout(out_mat_gapi), std::move(compile_args));
+
+ fun_ocv(in_mat1, in_mat2, out_mat_ocv);
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(NotOperatorTest, OperatorAccuracyTest)
+{
+ cv::Size sz_in = std::get<1>(GetParam());
+ initMatrixRandU(std::get<0>(GetParam()), sz_in, std::get<0>(GetParam()), std::get<2>(GetParam()));
+ cv::GCompileArgs compile_args;
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in;
+ auto out = ~in;
+ cv::GComputation c(in, out);
+
+ c.apply(in_mat1, out_mat_gapi, std::move(compile_args));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ out_mat_ocv =~in_mat1;
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_EQ(0, cv::countNonZero(out_mat_ocv != out_mat_gapi));
+ EXPECT_EQ(out_mat_gapi.size(), sz_in);
+ }
+}
+} // opencv_test
+
+#endif // OPENCV_GAPI_OPERATOR_TESTS_INL_COMMON_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_tests_common.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_tests_common.hpp
new file mode 100644
index 000000000..be0fc3c7e
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/common/gapi_tests_common.hpp
@@ -0,0 +1,296 @@
+// 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) 2018 Intel Corporation
+
+
+#include <iostream>
+
+#include "opencv2/ts.hpp"
+#include "opencv2/gapi.hpp"
+
+namespace
+{
+ inline std::ostream& operator<<(std::ostream& o, const cv::GCompileArg& arg)
+ {
+ return o << (arg.tag.empty() ? "empty" : arg.tag);
+ }
+}
+
+namespace opencv_test
+{
+
+class TestFunctional
+{
+public:
+ cv::Mat in_mat1;
+ cv::Mat in_mat2;
+ cv::Mat out_mat_gapi;
+ cv::Mat out_mat_ocv;
+
+ cv::Scalar sc;
+
+ cv::Scalar initScalarRandU(unsigned upper)
+ {
+ auto& rng = cv::theRNG();
+ double s1 = rng(upper);
+ double s2 = rng(upper);
+ double s3 = rng(upper);
+ double s4 = rng(upper);
+ return cv::Scalar(s1, s2, s3, s4);
+ }
+
+ void initMatsRandU(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
+ {
+ in_mat1 = cv::Mat(sz_in, type);
+ in_mat2 = cv::Mat(sz_in, type);
+
+ sc = initScalarRandU(100);
+ cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ if (createOutputMatrices && dtype != -1)
+ {
+ out_mat_gapi = cv::Mat (sz_in, dtype);
+ out_mat_ocv = cv::Mat (sz_in, dtype);
+ }
+ }
+
+ void initMatrixRandU(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
+ {
+ in_mat1 = cv::Mat(sz_in, type);
+
+ sc = initScalarRandU(100);
+
+ cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ if (createOutputMatrices && dtype != -1)
+ {
+ out_mat_gapi = cv::Mat (sz_in, dtype);
+ out_mat_ocv = cv::Mat (sz_in, dtype);
+ }
+ }
+
+ void initMatsRandN(int type, cv::Size sz_in, int dtype, bool createOutputMatrices = true)
+ {
+ in_mat1 = cv::Mat(sz_in, type);
+ cv::randn(in_mat1, cv::Scalar::all(127), cv::Scalar::all(40.f));
+
+ if (createOutputMatrices && dtype != -1)
+ {
+ out_mat_gapi = cv::Mat(sz_in, dtype);
+ out_mat_ocv = cv::Mat(sz_in, dtype);
+ }
+ }
+
+ static cv::Mat nonZeroPixels(const cv::Mat& mat)
+ {
+ int channels = mat.channels();
+ std::vector<cv::Mat> split(channels);
+ cv::split(mat, split);
+ cv::Mat result;
+ for (int c=0; c < channels; c++)
+ {
+ if (c == 0)
+ result = split[c] != 0;
+ else
+ result = result | (split[c] != 0);
+ }
+ return result;
+ }
+
+ static int countNonZeroPixels(const cv::Mat& mat)
+ {
+ return cv::countNonZero( nonZeroPixels(mat) );
+ }
+
+};
+
+template<class T>
+class TestParams: public TestFunctional, public TestWithParam<T>{};
+
+template<class T>
+class TestPerfParams: public TestFunctional, public perf::TestBaseWithParam<T>{};
+
+using compare_f = std::function<bool(const cv::Mat &a, const cv::Mat &b)>;
+
+template<typename T>
+struct Wrappable
+{
+ compare_f to_compare_f()
+ {
+ T t = *static_cast<T*const>(this);
+ return [t](const cv::Mat &a, const cv::Mat &b)
+ {
+ return t(a, b);
+ };
+ }
+};
+
+class AbsExact : public Wrappable<AbsExact>
+{
+public:
+ AbsExact() {}
+ bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
+ {
+ if (cv::norm(in1, in2, NORM_INF) != 0)
+ {
+ std::cout << "AbsExact error: G-API output and reference output matrixes are not bitexact equal." << std::endl;
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+private:
+};
+
+class AbsTolerance : public Wrappable<AbsTolerance>
+{
+public:
+ AbsTolerance(double tol) : _tol(tol) {}
+ bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
+ {
+ if (cv::norm(in1, in2, NORM_INF) > _tol)
+ {
+ std::cout << "AbsTolerance error: Number of different pixels in " << std::endl;
+ std::cout << "G-API output and reference output matrixes exceeds " << _tol << " pixels threshold." << std::endl;
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+private:
+ double _tol;
+};
+
+class Tolerance_FloatRel_IntAbs : public Wrappable<Tolerance_FloatRel_IntAbs>
+{
+public:
+ Tolerance_FloatRel_IntAbs(double tol, double tol8u) : _tol(tol), _tol8u(tol8u) {}
+ bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
+ {
+ int depth = CV_MAT_DEPTH(in1.type());
+ {
+ double err = depth >= CV_32F ? cv::norm(in1, in2, NORM_L1 | NORM_RELATIVE)
+ : cv::norm(in1, in2, NORM_INF);
+ double tolerance = depth >= CV_32F ? _tol : _tol8u;
+ if (err > tolerance)
+ {
+ std::cout << "Tolerance_FloatRel_IntAbs error: err=" << err
+ << " tolerance=" << tolerance
+ << " depth=" << cv::typeToString(depth) << std::endl;
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+private:
+ double _tol;
+ double _tol8u;
+};
+
+
+class AbsSimilarPoints : public Wrappable<AbsSimilarPoints>
+{
+public:
+ AbsSimilarPoints(double tol, double percent) : _tol(tol), _percent(percent) {}
+ bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
+ {
+ Mat diff;
+ cv::absdiff(in1, in2, diff);
+ Mat err_mask = diff > _tol;
+ int err_points = cv::countNonZero(err_mask.reshape(1));
+ double max_err_points = _percent * std::max((size_t)1000, in1.total());
+ if (err_points > max_err_points)
+ {
+ std::cout << "AbsSimilarPoints error: err_points=" << err_points
+ << " max_err_points=" << max_err_points << " (total=" << in1.total() << ")"
+ << " diff_tolerance=" << _tol << std::endl;
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+private:
+ double _tol;
+ double _percent;
+};
+
+
+class ToleranceFilter : public Wrappable<ToleranceFilter>
+{
+public:
+ ToleranceFilter(double tol, double tol8u, double inf_tol = 2.0) : _tol(tol), _tol8u(tol8u), _inf_tol(inf_tol) {}
+ bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
+ {
+ int depth = CV_MAT_DEPTH(in1.type());
+ {
+ double err_Inf = cv::norm(in1, in2, NORM_INF);
+ if (err_Inf > _inf_tol)
+ {
+ std::cout << "ToleranceFilter error: err_Inf=" << err_Inf << " tolerance=" << _inf_tol << std::endl;
+ return false;
+ }
+ double err = cv::norm(in1, in2, NORM_L2 | NORM_RELATIVE);
+ double tolerance = depth >= CV_32F ? _tol : _tol8u;
+ if (err > tolerance)
+ {
+ std::cout << "ToleranceFilter error: err=" << err << " tolerance=" << tolerance
+ << " depth=" << cv::depthToString(depth)
+ << std::endl;
+ return false;
+ }
+ }
+ return true;
+ }
+private:
+ double _tol;
+ double _tol8u;
+ double _inf_tol;
+};
+
+class ToleranceColor : public Wrappable<ToleranceColor>
+{
+public:
+ ToleranceColor(double tol, double inf_tol = 2.0) : _tol(tol), _inf_tol(inf_tol) {}
+ bool operator() (const cv::Mat& in1, const cv::Mat& in2) const
+ {
+ {
+ double err_Inf = cv::norm(in1, in2, NORM_INF);
+ if (err_Inf > _inf_tol)
+ {
+ std::cout << "ToleranceColor error: err_Inf=" << err_Inf << " tolerance=" << _inf_tol << std::endl;;
+ return false;
+ }
+ double err = cv::norm(in1, in2, NORM_L1 | NORM_RELATIVE);
+ if (err > _tol)
+ {
+ std::cout << "ToleranceColor error: err=" << err << " tolerance=" << _tol << std::endl;;
+ return false;
+ }
+ }
+ return true;
+ }
+private:
+ double _tol;
+ double _inf_tol;
+};
+} // namespace opencv_test
+
+namespace
+{
+ inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_f&)
+ {
+ return os << "compare_f";
+ }
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_cpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_cpu.cpp
new file mode 100644
index 000000000..11e78bd99
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_cpu.cpp
@@ -0,0 +1,405 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+#include "../common/gapi_core_tests.hpp"
+#include "opencv2/gapi/cpu/core.hpp"
+
+#define CORE_CPU cv::gapi::core::cpu::kernels()
+
+namespace opencv_test
+{
+
+
+// FIXME: Wut? See MulTestCPU/MathOpTest below (duplicate?)
+INSTANTIATE_TEST_CASE_P(AddTestCPU, MathOpTest,
+ Combine(Values(ADD, MUL),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(1.0),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(false),
+ Values(cv::compile_args(CORE_CPU))),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(MulTestCPU, MathOpTest,
+ Combine(Values(MUL),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(1.0, 0.5, 2.0),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(false),
+ Values(cv::compile_args(CORE_CPU))),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(SubTestCPU, MathOpTest,
+ Combine(Values(SUB),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values (1.0),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(DivTestCPU, MathOpTest,
+ Combine(Values(DIV),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values (1.0, 0.5, 2.0),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(MulTestCPU, MulDoubleTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(DivTestCPU, DivTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(DivCTestCPU, DivCTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MeanTestCPU, MeanTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MaskTestCPU, MaskTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SelectTestCPU, SelectTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Polar2CartCPU, Polar2CartTest,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Cart2PolarCPU, Cart2PolarTest,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(PhaseCPU, PhaseTest,
+ Combine(Values(CV_32F, CV_32FC3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SqrtCPU, SqrtTest,
+ Combine(Values(CV_32F, CV_32FC3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(CompareTestCPU, CmpTest,
+ Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))),
+ opencv_test::PrintCmpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(BitwiseTestCPU, BitwiseTest,
+ Combine(Values(AND, OR, XOR),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))),
+ opencv_test::PrintBWCoreParams());
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotTestCPU, NotTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MinTestCPU, MinTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MaxTestCPU, MaxTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SumTestCPU, SumTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(1e-5),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffTestCPU, AbsDiffTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffCTestCPU, AbsDiffCTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+// FIXME: Comparison introduced by YL doesn't work with C3
+INSTANTIATE_TEST_CASE_P(AddWeightedTestCPU, AddWeightedTest,
+ Combine(Values( CV_8UC1/*, CV_8UC3*/, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+/*init output matrices or not*/ testing::Bool(),
+ Values(0.5000005),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(NormTestCPU, NormTest,
+ Combine(Values(NORM_INF, NORM_L1, NORM_L2),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(1e-5),
+ Values(cv::compile_args(CORE_CPU))),
+ opencv_test::PrintNormCoreParams());
+
+INSTANTIATE_TEST_CASE_P(IntegralTestCPU, IntegralTest,
+ Combine(Values( CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdTestCPU, ThresholdTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::THRESH_BINARY, cv::THRESH_BINARY_INV, cv::THRESH_TRUNC, cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdTestCPU, ThresholdOTTest,
+ Combine(Values(CV_8UC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::THRESH_OTSU, cv::THRESH_TRIANGLE),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+
+INSTANTIATE_TEST_CASE_P(InRangeTestCPU, InRangeTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Split3TestCPU, Split3Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Split4TestCPU, Split4Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTest,
+ Combine(Values(AbsSimilarPoints(2, 0.05).to_compare_f()),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::Size(64,64),
+ cv::Size(30,30)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTestFxFy,
+ Combine(Values(AbsSimilarPoints(2, 0.05).to_compare_f()),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(0.5, 0.1),
+ Values(0.5, 0.1),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Merge3TestCPU, Merge3Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Merge4TestCPU, Merge4Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(RemapTestCPU, RemapTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(FlipTestCPU, FlipTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(0,1,-1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(CropTestCPU, CropTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50)),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(LUTTestCPU, LUTTest,
+ Combine(Values(CV_8UC1, CV_8UC3),
+ Values(CV_8UC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(LUTTestCustomCPU, LUTTest,
+ Combine(Values(CV_8UC3),
+ Values(CV_8UC3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ConvertToCPU, ConvertToTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(CV_8U, CV_16U, CV_16S, CV_32F),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatHorTestCPU, ConcatHorTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatVertTestCPU, ConcatVertTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatVertVecTestCPU, ConcatVertVecTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatHorVecTestCPU, ConcatHorVecTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_CPU))));
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_fluid.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_fluid.cpp
new file mode 100644
index 000000000..c65052b36
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_core_tests_fluid.cpp
@@ -0,0 +1,506 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+#include "../common/gapi_core_tests.hpp"
+
+namespace opencv_test
+{
+
+#define CORE_FLUID cv::gapi::core::fluid::kernels()
+
+
+// FIXME: Windows accuracy problems after recent update!
+INSTANTIATE_TEST_CASE_P(MathOpTestFluid, MathOpTest,
+ Combine(Values(ADD, SUB, DIV, MUL),
+ testing::Bool(),
+ Values(CV_8UC3, CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(1.0),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+ testing::Bool(),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(MulSTestFluid, MulDoubleTest,
+ Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1), // FIXME: extend with more types
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(DivCTestFluid, DivCTest,
+ Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(CV_8U, CV_32F),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffTestFluid, AbsDiffTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffCTestFluid, AbsDiffCTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseTestFluid, BitwiseTest,
+ Combine(Values(AND, OR, XOR),
+ Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))),
+ opencv_test::PrintBWCoreParams());
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotTestFluid, NotTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(MinTestFluid, MinTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(MaxTestFluid, MaxTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(CompareTestFluid, CmpTest,
+ Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+ testing::Bool(),
+ Values(CV_8UC3, CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))),
+ opencv_test::PrintCmpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(AddWeightedTestFluid, AddWeightedTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+ testing::Bool(),
+ Values(0.5000005),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(LUTTestFluid, LUTTest,
+ Combine(Values(CV_8UC1, CV_8UC3),
+ Values(CV_8UC1),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(ConvertToFluid, ConvertToTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
+ Values(CV_8U, CV_16U, CV_32F),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(Split3TestFluid, Split3Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(Split4TestFluid, Split4Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(Merge3TestFluid, Merge3Test,
+ Combine(Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(Merge4TestFluid, Merge4Test,
+ Combine(Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(SelectTestFluid, SelectTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(Polar2CartFluid, Polar2CartTest,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(Cart2PolarFluid, Cart2PolarTest,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(PhaseFluid, PhaseTest,
+ Combine(Values(CV_32F, CV_32FC3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(SqrtFluid, SqrtTest,
+ Combine(Values(CV_32F, CV_32FC3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdTestFluid, ThresholdTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::THRESH_BINARY, cv::THRESH_BINARY_INV,
+ cv::THRESH_TRUNC,
+ cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(InRangeTestFluid, InRangeTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1920, 1080),
+ cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(
+ ResizeTestFluid, ResizeTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
+ Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128),
+ cv::Size(64, 64),
+ cv::Size(30, 30)),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128),
+ cv::Size(64, 64),
+ cv::Size(30, 30)),
+ Values(cv::compile_args(CORE_FLUID))));
+
+//----------------------------------------------------------------------
+// FIXME: Clean-up test configurations which are enabled already
+#if 0
+INSTANTIATE_TEST_CASE_P(MathOpTestCPU, MathOpTest,
+ Combine(Values(ADD, DIV, MUL),
+ testing::Bool(),
+ Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(false)),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(SubTestCPU, MathOpTest,
+ Combine(Values(SUB),
+ testing::Bool(),
+ Values(CV_8UC1, CV_16SC1 , CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ testing::Bool()),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(MulSTestCPU, MulSTest,
+ Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(DivCTestCPU, DivCTest,
+ Combine(Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(MeanTestCPU, MeanTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(SelectTestCPU, SelectTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(Polar2CartCPU, Polar2CartTest,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(Cart2PolarCPU, Cart2PolarTest,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(CompareTestCPU, CmpTest,
+ Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+ testing::Bool(),
+ Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()),
+ opencv_test::PrintCmpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(BitwiseTestCPU, BitwiseTest,
+ Combine(Values(AND, OR, XOR),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()),
+ opencv_test::PrintBWCoreParams());
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotTestCPU, NotTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ /*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(MinTestCPU, MinTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(MaxTestCPU, MaxTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(SumTestCPU, SumTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool())
+ Values(0.0),
+ );
+
+INSTANTIATE_TEST_CASE_P(AbsDiffTestCPU, AbsDiffTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffCTestCPU, AbsDiffCTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(AddWeightedTestCPU, AddWeightedTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(NormTestCPU, NormTest,
+ Combine(Values(NORM_INF, NORM_L1, NORM_L2),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128))),
+ Values(0.0),
+ opencv_test::PrintNormCoreParams());
+
+INSTANTIATE_TEST_CASE_P(IntegralTestCPU, IntegralTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdTestCPU, ThresholdTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::THRESH_BINARY, cv::THRESH_BINARY_INV, cv::THRESH_TRUNC, cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(ThresholdTestCPU, ThresholdOTTest,
+ Combine(Values(CV_8UC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::THRESH_OTSU, cv::THRESH_TRIANGLE),
+/*init output matrices or not*/ testing::Bool()));
+
+
+INSTANTIATE_TEST_CASE_P(InRangeTestCPU, InRangeTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(Split3TestCPU, Split3Test,
+ (Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128))));
+
+INSTANTIATE_TEST_CASE_P(Split4TestCPU, Split4Test,
+ (Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128))));
+
+INSTANTIATE_TEST_CASE_P(Merge3TestCPU, Merge3Test,
+ (Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128))));
+
+INSTANTIATE_TEST_CASE_P(Merge4TestCPU, Merge4Test,
+ (Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128))));
+
+INSTANTIATE_TEST_CASE_P(RemapTestCPU, RemapTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(FlipTestCPU, FlipTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(0,1,-1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(CropTestCPU, CropTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50)),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(LUTTestCPU, LUTTest,
+ Combine(Values(CV_8UC1, CV_8UC3),
+ Values(CV_8UC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(LUTTestCustomCPU, LUTTest,
+ Combine(Values(CV_8UC3),
+ Values(CV_8UC3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_P(ConvertToCPU, ConvertToTest,
+ Combine(Values(CV_8UC3, CV_8UC1, CV_16UC1, CV_32FC1),
+ Values(CV_8U, CV_16U, CV_32F),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128))));
+
+INSTANTIATE_TEST_CASE_P(ConcatHorTestCPU, ConcatHorTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128))));
+INSTANTIATE_TEST_CASE_P(ConcatVertTestCPU, ConcatVertTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128))));
+
+//----------------------------------------------------------------------
+#endif // 0
+
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp
new file mode 100644
index 000000000..beda02240
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp
@@ -0,0 +1,238 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+
+#include "../common/gapi_imgproc_tests.hpp"
+#include "opencv2/gapi/cpu/imgproc.hpp"
+
+#define IMGPROC_CPU cv::gapi::imgproc::cpu::kernels()
+
+namespace opencv_test
+{
+
+
+INSTANTIATE_TEST_CASE_P(Filter2DTestCPU, Filter2DTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 4, 5, 7),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BoxFilterTestCPU, BoxFilterTest,
+ Combine(Values(AbsTolerance(0).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3,5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SepFilterTestCPU_8U, SepFilterTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3),
+ Values(3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(-1, CV_16S, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SepFilterTestCPU_other, SepFilterTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(-1, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BlurTestCPU, BlurTest,
+ Combine(Values(AbsTolerance(0.0).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3,5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::BORDER_DEFAULT),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(gaussBlurTestCPU, GaussianBlurTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MedianBlurTestCPU, MedianBlurTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(ErodeTestCPU, ErodeTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Erode3x3TestCPU, Erode3x3Test,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(1,2,4),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(DilateTestCPU, DilateTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(Dilate3x3TestCPU, Dilate3x3Test,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(1,2,4),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SobelTestCPU, SobelTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(-1, CV_16S, CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(SobelTestCPU32F, SobelTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_32FC1),
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(EqHistTestCPU, EqHistTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(CannyTestCPU, CannyTest,
+ Combine(Values(AbsSimilarPoints(0, 0.05).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(3.0, 120.0),
+ Values(125.0, 240.0),
+ Values(3, 5),
+ testing::Bool(),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2GrayTestCPU, RGB2GrayTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2GrayTestCPU, BGR2GrayTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2YUVTestCPU, RGB2YUVTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(YUV2RGBTestCPU, YUV2RGBTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2LabTestCPU, RGB2LabTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2LUVTestCPU, BGR2LUVTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(LUV2BGRTestCPU, LUV2BGRTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2YUVTestCPU, BGR2YUVTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(YUV2BGRTestCPU, YUV2BGRTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_fluid.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_fluid.cpp
new file mode 100644
index 000000000..5dca2092a
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_imgproc_tests_fluid.cpp
@@ -0,0 +1,168 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+#include "../common/gapi_imgproc_tests.hpp"
+
+#define IMGPROC_FLUID cv::gapi::imgproc::fluid::kernels()
+
+namespace opencv_test
+{
+
+INSTANTIATE_TEST_CASE_P(RGB2GrayTestFluid, RGB2GrayTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(BGR2GrayTestFluid, BGR2GrayTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(RGB2YUVTestFluid, RGB2YUVTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(YUV2RGBTestFluid, YUV2RGBTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(RGB2LabTestFluid, RGB2LabTest,
+ Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+// FIXME: Not supported by Fluid yet (no kernel implemented)
+INSTANTIATE_TEST_CASE_P(BGR2LUVTestFluid, BGR2LUVTest,
+ Combine(Values(ToleranceColor(5e-3, 6).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(blurTestFluid, BlurTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(3), // add kernel size=5 when implementation is ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::BORDER_DEFAULT),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(gaussBlurTestFluid, GaussianBlurTest,
+ Combine(Values(ToleranceFilter(1e-3f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(3), // add kernel size=5 when implementation is ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(medianBlurTestFluid, MedianBlurTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(3), // add kernel size=5 when implementation is ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(erodeTestFluid, ErodeTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(3), // add kernel size=5 when implementation is ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(dilateTestFluid, DilateTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(3), // add kernel size=5 when implementation is ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(SobelTestFluid, SobelTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(3), // add kernel size=5 when implementation is ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(-1, CV_16S, CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(SobelTestFluid32F, SobelTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_32FC1),
+ Values(3), // add kernel size=5 when implementation is ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(boxFilterTestFluid32, BoxFilterTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(3), // add kernel size=5 when implementation is ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(sepFilterTestFluid, SepFilterTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_32FC1),
+ Values(3), // add kernel size=5 when implementation is ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(-1, CV_32F),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(filter2DTestFluid, Filter2DTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(3), // add kernel size=4,5,7 when implementation ready
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+ Values(true, false),
+ Values(cv::compile_args(IMGPROC_FLUID))));
+
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_cpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_cpu.cpp
new file mode 100644
index 000000000..435c798c6
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_cpu.cpp
@@ -0,0 +1,73 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+#include "../common/gapi_operators_tests.hpp"
+#include "opencv2/gapi/cpu/core.hpp"
+
+#define CORE_CPU cv::gapi::core::cpu::kernels()
+
+namespace opencv_test
+{
+
+
+// FIXME: CPU test runs are disabled since Fluid is an exclusive plugin now!
+INSTANTIATE_TEST_CASE_P(MathOperatorTestCPU, MathOperatorMatMatTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opPlusM, opMinusM, opDivM,
+ opGreater, opLess, opGreaterEq, opLessEq, opEq, opNotEq),
+ Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(MathOperatorTestCPU, MathOperatorMatScalarTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opPlus, opPlusR, opMinus, opMinusR, opMul, opMulR, // FIXIT avoid division by values near zero: opDiv, opDivR,
+ opGT, opLT, opGE, opLE, opEQ, opNE,
+ opGTR, opLTR, opGER, opLER, opEQR, opNER),
+ Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestCPU, MathOperatorMatMatTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opAnd, opOr, opXor ),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestCPU, MathOperatorMatScalarTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opAND, opOR, opXOR, opANDR, opORR, opXORR ),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotOperatorTestCPU, NotOperatorTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_CPU))));
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_fluid.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_fluid.cpp
new file mode 100644
index 000000000..4179fa53b
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/cpu/gapi_operators_tests_fluid.cpp
@@ -0,0 +1,72 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "../common/gapi_operators_tests.hpp"
+
+#define CORE_FLUID cv::gapi::core::fluid::kernels()
+
+namespace opencv_test
+{
+
+INSTANTIATE_TEST_CASE_P(MathOperatorTestFluid, MathOperatorMatMatTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opPlusM, opMinusM, opDivM,
+ opGreater, opLess, opGreaterEq, opLessEq, opEq, opNotEq),
+ Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+//FIXME: Some Mat/Scalar Fluid kernels are not there yet!
+INSTANTIATE_TEST_CASE_P(DISABLED_MathOperatorTestFluid, MathOperatorMatScalarTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opPlus, opPlusR, opMinus, opMinusR, opMul, opMulR, // FIXIT avoid division by values near zero: opDiv, opDivR,
+ opGT, opLT, opGE, opLE, opEQ, opNE,
+ opGTR, opLTR, opGER, opLER, opEQR, opNER),
+ Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestFluid, MathOperatorMatMatTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opAnd, opOr, opXor ),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+//FIXME: Some Mat/Scalar Fluid kernels are not there yet!
+INSTANTIATE_TEST_CASE_P(DISABLED_BitwiseOperatorTestFluid, MathOperatorMatScalarTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opAND, opOR, opXOR, opANDR, opORR, opXORR ),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotOperatorTestFluid, NotOperatorTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_FLUID))));
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_array_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_array_tests.cpp
new file mode 100644
index 000000000..e5765624c
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_array_tests.cpp
@@ -0,0 +1,166 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include <vector>
+#include <ade/util/algorithm.hpp>
+
+namespace opencv_test
+{
+
+namespace ThisTest
+{
+using GPointArray = cv::GArray<cv::Point>;
+G_TYPED_KERNEL(GeneratePoints, <GPointArray(GMat)>, "test.array.out_const")
+{
+ static GArrayDesc outMeta(const GMatDesc&) { return empty_array_desc(); }
+};
+G_TYPED_KERNEL(FindCorners, <GPointArray(GMat)>, "test.array.out")
+{
+ static GArrayDesc outMeta(const GMatDesc&) { return empty_array_desc(); }
+};
+G_TYPED_KERNEL(CountCorners, <GScalar(GPointArray)>, "test.array.in")
+{
+ static GScalarDesc outMeta(const GArrayDesc &) { return empty_scalar_desc(); }
+};
+} // namespace ThisTest
+
+namespace
+{
+GAPI_OCV_KERNEL(OCVGeneratePoints, ThisTest::GeneratePoints)
+{
+ static void run(cv::Mat, std::vector<cv::Point> &out)
+ {
+ for (int i = 0; i < 10; i++)
+ out.emplace_back(i, i);
+ }
+};
+
+GAPI_OCV_KERNEL(OCVFindCorners, ThisTest::FindCorners)
+{
+ static void run(cv::Mat in, std::vector<cv::Point> &out)
+ {
+ cv::goodFeaturesToTrack(in, out, 1024, 0.01, 3);
+ }
+};
+
+GAPI_OCV_KERNEL(OCVCountCorners, ThisTest::CountCorners)
+{
+ static void run(const std::vector<cv::Point> &in, cv::Scalar &out)
+ {
+ out[0] = static_cast<double>(in.size());
+ }
+};
+
+cv::Mat cross(int w, int h)
+{
+ cv::Mat mat = cv::Mat::eye(h, w, CV_8UC1)*255;
+ cv::Mat yee;
+ cv::flip(mat, yee, 0); // X-axis
+ mat |= yee; // make an "X" matrix;
+ return mat;
+}
+} // (anonymous namespace)
+
+TEST(GArray, TestReturnValue)
+{
+ // FIXME: Make .apply() able to take compile arguments
+ cv::GComputationT<ThisTest::GPointArray(cv::GMat)> c(ThisTest::FindCorners::on);
+ auto cc = c.compile(cv::GMatDesc{CV_8U,1,{32,32}},
+ cv::compile_args(cv::gapi::kernels<OCVFindCorners>()));
+
+ // Prepare input matrix
+ cv::Mat input = cross(32, 32);
+
+ std::vector<cv::Point> points;
+ cc(input, points);
+
+ // OCV goodFeaturesToTrack should find 5 points here (with these settings)
+ EXPECT_EQ(5u, points.size());
+ EXPECT_TRUE(ade::util::find(points, cv::Point(16,16)) != points.end());
+ EXPECT_TRUE(ade::util::find(points, cv::Point(30,30)) != points.end());
+ EXPECT_TRUE(ade::util::find(points, cv::Point( 1,30)) != points.end());
+ EXPECT_TRUE(ade::util::find(points, cv::Point(30, 1)) != points.end());
+ EXPECT_TRUE(ade::util::find(points, cv::Point( 1, 1)) != points.end());
+}
+
+TEST(GArray, TestInputArg)
+{
+ cv::GComputationT<cv::GScalar(ThisTest::GPointArray)> c(ThisTest::CountCorners::on);
+ auto cc = c.compile(cv::empty_array_desc(),
+ cv::compile_args(cv::gapi::kernels<OCVCountCorners>()));
+
+ const std::vector<cv::Point> arr = {cv::Point(1,1), cv::Point(2,2)};
+ cv::Scalar out;
+ cc(arr, out);
+ EXPECT_EQ(2, out[0]);
+}
+
+TEST(GArray, TestPipeline)
+{
+ cv::GComputationT<cv::GScalar(cv::GMat)> c([](cv::GMat in)
+ {
+ return ThisTest::CountCorners::on(ThisTest::FindCorners::on(in));
+ });
+ auto cc = c.compile(cv::GMatDesc{CV_8U,1,{32,32}},
+ cv::compile_args(cv::gapi::kernels<OCVFindCorners, OCVCountCorners>()));
+
+ cv::Mat input = cross(32, 32);
+ cv::Scalar out;
+ cc(input, out);
+ EXPECT_EQ(5, out[0]);
+}
+
+TEST(GArray, NoAggregationBetweenRuns)
+{
+ cv::GComputationT<cv::GScalar(cv::GMat)> c([](cv::GMat in)
+ {
+ return ThisTest::CountCorners::on(ThisTest::GeneratePoints::on(in));
+ });
+ auto cc = c.compile(cv::GMatDesc{CV_8U,1,{32,32}},
+ cv::compile_args(cv::gapi::kernels<OCVGeneratePoints, OCVCountCorners>()));
+
+ cv::Mat input = cv::Mat::eye(32, 32, CV_8UC1);
+ cv::Scalar out;
+
+ cc(input, out);
+ EXPECT_EQ(10, out[0]);
+
+ // Last kernel in the graph counts number of elements in array, returned by the previous kernel
+ // (in this test, this variable is constant).
+ // After 10 executions, this number MUST remain the same - 1st kernel is adding new values on every
+ // run, but it is graph's responsibility to reset internal object state.
+ cv::Scalar out2;
+ for (int i = 0; i < 10; i++)
+ {
+ cc(input, out2);
+ }
+ EXPECT_EQ(10, out2[0]);
+}
+
+TEST(GArray, TestIntermediateOutput)
+{
+ using Result = std::tuple<ThisTest::GPointArray, cv::GScalar>;
+ cv::GComputationT<Result(cv::GMat)> c([](cv::GMat in)
+ {
+ auto corners = ThisTest::GeneratePoints::on(in);
+ return std::make_tuple(corners, ThisTest::CountCorners::on(corners));
+ });
+
+ cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
+ std::vector<cv::Point> out_points;
+ cv::Scalar out_count;
+
+ auto cc = c.compile(cv::descr_of(in_mat),
+ cv::compile_args(cv::gapi::kernels<OCVGeneratePoints, OCVCountCorners>()));
+ cc(in_mat, out_points, out_count);
+
+ EXPECT_EQ(10u, out_points.size());
+ EXPECT_EQ(10, out_count[0]);
+}
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_basic_hetero_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_basic_hetero_tests.cpp
new file mode 100644
index 000000000..62069d865
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_basic_hetero_tests.cpp
@@ -0,0 +1,312 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "gapi_mock_kernels.hpp"
+
+#include "opencv2/gapi/fluid/gfluidkernel.hpp"
+
+namespace opencv_test
+{
+
+namespace
+{
+ GAPI_OCV_KERNEL(OCVFoo, I::Foo)
+ {
+ static void run(const cv::Mat &in, cv::Mat &out)
+ {
+ out = in + 2;
+ }
+ };
+
+ GAPI_OCV_KERNEL(OCVBar, I::Bar)
+ {
+ static void run(const cv::Mat &a, const cv::Mat &b, cv::Mat &out)
+ {
+ out = 4*(a + b);
+ }
+ };
+
+ void FluidFooRow(const uint8_t* in, uint8_t* out, int length)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ out[i] = in[i] + 3;
+ }
+ }
+
+ void FluidBarRow(const uint8_t* in1, const uint8_t* in2, uint8_t* out, int length)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ out[i] = 3*(in1[i] + in2[i]);
+ }
+ }
+
+ GAPI_FLUID_KERNEL(FFoo, I::Foo, false)
+ {
+ static const int Window = 1;
+
+ static void run(const cv::gapi::fluid::View &in,
+ cv::gapi::fluid::Buffer &out)
+ {
+ FluidFooRow(in.InLineB(0), out.OutLineB(), in.length());
+ }
+ };
+
+ GAPI_FLUID_KERNEL(FBar, I::Bar, false)
+ {
+ static const int Window = 1;
+
+ static void run(const cv::gapi::fluid::View &in1,
+ const cv::gapi::fluid::View &in2,
+ cv::gapi::fluid::Buffer &out)
+ {
+ FluidBarRow(in1.InLineB(0), in2.InLineB(0), out.OutLineB(), in1.length());
+ }
+ };
+
+ G_TYPED_KERNEL(FluidFooI, <cv::GMat(cv::GMat)>, "test.kernels.fluid_foo")
+ {
+ static cv::GMatDesc outMeta(const cv::GMatDesc &in) { return in; }
+ };
+
+ G_TYPED_KERNEL(FluidBarI, <cv::GMat(cv::GMat,cv::GMat)>, "test.kernels.fluid_bar")
+ {
+ static cv::GMatDesc outMeta(const cv::GMatDesc &in, const cv::GMatDesc &) { return in; }
+ };
+
+ GAPI_FLUID_KERNEL(FluidFoo, FluidFooI, false)
+ {
+ static const int Window = 1;
+
+ static void run(const cv::gapi::fluid::View &in,
+ cv::gapi::fluid::Buffer &out)
+ {
+ FluidFooRow(in.InLineB(0), out.OutLineB(), in.length());
+ }
+ };
+
+ GAPI_FLUID_KERNEL(FluidBar, FluidBarI, false)
+ {
+ static const int Window = 1;
+
+ static void run(const cv::gapi::fluid::View &in1,
+ const cv::gapi::fluid::View &in2,
+ cv::gapi::fluid::Buffer &out)
+ {
+ FluidBarRow(in1.InLineB(0), in2.InLineB(0), out.OutLineB(), in1.length());
+ }
+ };
+
+ GAPI_FLUID_KERNEL(FluidFoo2lpi, FluidFooI, false)
+ {
+ static const int Window = 1;
+ static const int LPI = 2;
+
+ static void run(const cv::gapi::fluid::View &in,
+ cv::gapi::fluid::Buffer &out)
+ {
+ for (int l = 0; l < out.lpi(); l++)
+ {
+ FluidFooRow(in.InLineB(l), out.OutLineB(l), in.length());
+ }
+ }
+ };
+
+ cv::Mat ocvFoo(const cv::Mat &in)
+ {
+ cv::Mat out;
+ OCVFoo::run(in, out);
+ return out;
+ }
+ cv::Mat ocvBar(const cv::Mat &in1, const cv::Mat &in2)
+ {
+ cv::Mat out;
+ OCVBar::run(in1, in2, out);
+ return out;
+ }
+ cv::Mat fluidFoo(const cv::Mat &in)
+ {
+ cv::Mat out(in.rows, in.cols, in.type());
+ for (int y = 0; y < in.rows; y++)
+ {
+ FluidFooRow(in.ptr(y), out.ptr(y), in.cols);
+ }
+ return out;
+ }
+ cv::Mat fluidBar(const cv::Mat &in1, const cv::Mat &in2)
+ {
+ cv::Mat out(in1.rows, in1.cols, in1.type());
+ for (int y = 0; y < in1.rows; y++)
+ {
+ FluidBarRow(in1.ptr(y), in2.ptr(y), out.ptr(y), in1.cols);
+ }
+ return out;
+ }
+} // anonymous namespace
+
+struct GAPIHeteroTest: public ::testing::Test
+{
+ cv::GComputation m_comp;
+ cv::gapi::GKernelPackage m_ocv_kernels;
+ cv::gapi::GKernelPackage m_fluid_kernels;
+ cv::gapi::GKernelPackage m_hetero_kernels;
+
+ cv::Mat m_in_mat;
+ cv::Mat m_out_mat;
+
+ GAPIHeteroTest();
+};
+
+GAPIHeteroTest::GAPIHeteroTest()
+ : m_comp([](){
+ cv::GMat in;
+ cv::GMat out = I::Bar::on(I::Foo::on(in),
+ I::Foo::on(in));
+ return cv::GComputation(in, out);
+ })
+ , m_ocv_kernels(cv::gapi::kernels<OCVFoo, OCVBar>())
+ , m_fluid_kernels(cv::gapi::kernels<FFoo, FBar>())
+ , m_hetero_kernels(cv::gapi::kernels<OCVFoo, FBar>())
+ , m_in_mat(cv::Mat::eye(cv::Size(64, 64), CV_8UC1))
+{
+}
+
+TEST_F(GAPIHeteroTest, TestOCV)
+{
+ EXPECT_TRUE(cv::gapi::cpu::backend() == m_ocv_kernels.lookup<I::Foo>());
+ EXPECT_TRUE(cv::gapi::cpu::backend() == m_ocv_kernels.lookup<I::Bar>());
+
+ cv::Mat ref = ocvBar(ocvFoo(m_in_mat), ocvFoo(m_in_mat));
+ EXPECT_NO_THROW(m_comp.apply(m_in_mat, m_out_mat, cv::compile_args(m_ocv_kernels)));
+ EXPECT_EQ(0, cv::countNonZero(ref != m_out_mat));
+}
+
+TEST_F(GAPIHeteroTest, TestFluid)
+{
+ EXPECT_TRUE(cv::gapi::fluid::backend() == m_fluid_kernels.lookup<I::Foo>());
+ EXPECT_TRUE(cv::gapi::fluid::backend() == m_fluid_kernels.lookup<I::Bar>());
+
+ cv::Mat ref = fluidBar(fluidFoo(m_in_mat), fluidFoo(m_in_mat));
+ EXPECT_NO_THROW(m_comp.apply(m_in_mat, m_out_mat, cv::compile_args(m_fluid_kernels)));
+ EXPECT_EQ(0, cv::countNonZero(ref != m_out_mat));
+}
+
+TEST_F(GAPIHeteroTest, TestBoth)
+{
+ EXPECT_TRUE(cv::gapi::cpu::backend() == m_hetero_kernels.lookup<I::Foo>());
+ EXPECT_TRUE(cv::gapi::fluid::backend() == m_hetero_kernels.lookup<I::Bar>());
+
+ cv::Mat ref = fluidBar(ocvFoo(m_in_mat), ocvFoo(m_in_mat));
+ EXPECT_NO_THROW(m_comp.apply(m_in_mat, m_out_mat, cv::compile_args(m_hetero_kernels)));
+ EXPECT_EQ(0, cv::countNonZero(ref != m_out_mat));
+}
+
+struct GAPIBigHeteroTest : public ::testing::TestWithParam<std::array<int, 9>>
+{
+ cv::GComputation m_comp;
+ cv::gapi::GKernelPackage m_kernels;
+
+ cv::Mat m_in_mat;
+ cv::Mat m_out_mat1;
+ cv::Mat m_out_mat2;
+
+ cv::Mat m_ref_mat1;
+ cv::Mat m_ref_mat2;
+
+ GAPIBigHeteroTest();
+};
+
+// Foo7
+// .-> Foo2 -> Foo3 -<
+// Foo0 -> Foo1 Bar -> Foo6
+// `-> Foo4 -> Foo5 -`
+
+GAPIBigHeteroTest::GAPIBigHeteroTest()
+ : m_comp([&](){
+ auto flags = GetParam();
+ std::array<std::function<cv::GMat(cv::GMat)>, 8> foos;
+
+ for (int i = 0; i < 8; i++)
+ {
+ foos[i] = flags[i] ? &I::Foo::on : &FluidFooI::on;
+ }
+ auto bar = flags[8] ? &I::Bar::on : &FluidBarI::on;
+
+ cv::GMat in;
+ auto foo1Out = foos[1](foos[0](in));
+ auto foo3Out = foos[3](foos[2](foo1Out));
+ auto foo6Out = foos[6](bar(foo3Out,
+ foos[5](foos[4](foo1Out))));
+ auto foo7Out = foos[7](foo3Out);
+
+ return cv::GComputation(GIn(in), GOut(foo6Out, foo7Out));
+ })
+ , m_kernels(cv::gapi::kernels<OCVFoo, OCVBar, FluidFoo, FluidBar>())
+ , m_in_mat(cv::Mat::eye(cv::Size(64, 64), CV_8UC1))
+{
+ auto flags = GetParam();
+ std::array<std::function<cv::Mat(cv::Mat)>, 8> foos;
+
+ for (int i = 0; i < 8; i++)
+ {
+ foos[i] = flags[i] ? ocvFoo : fluidFoo;
+ }
+ auto bar = flags[8] ? ocvBar : fluidBar;
+
+ cv::Mat foo1OutMat = foos[1](foos[0](m_in_mat));
+ cv::Mat foo3OutMat = foos[3](foos[2](foo1OutMat));
+
+ m_ref_mat1 = foos[6](bar(foo3OutMat,
+ foos[5](foos[4](foo1OutMat))));
+
+ m_ref_mat2 = foos[7](foo3OutMat);
+}
+
+TEST_P(GAPIBigHeteroTest, Test)
+{
+ EXPECT_NO_THROW(m_comp.apply(gin(m_in_mat), gout(m_out_mat1, m_out_mat2), cv::compile_args(m_kernels)));
+ EXPECT_EQ(0, cv::countNonZero(m_ref_mat1 != m_out_mat1));
+ EXPECT_EQ(0, cv::countNonZero(m_ref_mat2 != m_out_mat2));
+}
+
+static auto configurations = []()
+{
+ // Fill all possible configurations
+ // from 000000000 to 111111111
+ std::array<std::array<int, 9>, 512> arr;
+ for (auto n = 0; n < 512; n++)
+ {
+ for (auto i = 0; i < 9; i++)
+ {
+ arr[n][i] = (n >> (8 - i)) & 1;
+ }
+ }
+ return arr;
+}();
+
+INSTANTIATE_TEST_CASE_P(GAPIBigHeteroTest, GAPIBigHeteroTest,
+ ::testing::ValuesIn(configurations));
+
+TEST(GAPIHeteroTestLPI, Test)
+{
+ cv::GMat in;
+ auto mid = FluidFooI::on(in);
+ auto out = FluidFooI::on(mid);
+ cv::gapi::island("isl0", GIn(in), GOut(mid));
+ cv::gapi::island("isl1", GIn(mid), GOut(out));
+ cv::GComputation c(in, out);
+
+ cv::Mat in_mat = cv::Mat::eye(cv::Size(64, 64), CV_8UC1);
+ cv::Mat out_mat;
+ EXPECT_NO_THROW(c.apply(in_mat, out_mat, cv::compile_args(cv::gapi::kernels<FluidFoo2lpi>())));
+ cv::Mat ref = fluidFoo(fluidFoo(in_mat));
+ EXPECT_EQ(0, cv::countNonZero(ref != out_mat));
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_desc_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_desc_tests.cpp
new file mode 100644
index 000000000..711211da2
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_desc_tests.cpp
@@ -0,0 +1,202 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+
+namespace opencv_test
+{
+
+namespace
+{
+ G_TYPED_KERNEL(KTest, <cv::GScalar(cv::GScalar)>, "org.opencv.test.scalar_kernel") {
+ static cv::GScalarDesc outMeta(cv::GScalarDesc in) { return in; }
+ };
+ GAPI_OCV_KERNEL(GOCVScalarTest, KTest)
+ {
+ static void run(const cv::Scalar &in, cv::Scalar &out) { out = in+cv::Scalar(1); }
+ };
+}
+
+TEST(GAPI_MetaDesc, MatDesc)
+{
+ cv::Mat m1(240, 320, CV_8U);
+ const auto desc1 = cv::descr_of(m1);
+ EXPECT_EQ(CV_8U, desc1.depth);
+ EXPECT_EQ(1, desc1.chan);
+ EXPECT_EQ(320, desc1.size.width);
+ EXPECT_EQ(240, desc1.size.height);
+
+ cv::Mat m2(480, 640, CV_8UC3);
+ const auto desc2 = cv::descr_of(m2);
+ EXPECT_EQ(CV_8U, desc2.depth);
+ EXPECT_EQ(3, desc2.chan);
+ EXPECT_EQ(640, desc2.size.width);
+ EXPECT_EQ(480, desc2.size.height);
+}
+
+TEST(GAPI_MetaDesc, Compare_Equal_MatDesc)
+{
+ const auto desc1 = cv::GMatDesc{CV_8U, 1, {64, 64}};
+ const auto desc2 = cv::GMatDesc{CV_8U, 1, {64, 64}};
+
+ EXPECT_TRUE(desc1 == desc2);
+}
+
+TEST(GAPI_MetaDesc, Compare_Not_Equal_MatDesc)
+{
+ const auto desc1 = cv::GMatDesc{CV_8U, 1, {64, 64}};
+ const auto desc2 = cv::GMatDesc{CV_32F, 1, {64, 64}};
+
+ EXPECT_TRUE(desc1 != desc2);
+}
+
+TEST(GAPI_MetaDesc, Compile_MatchMetaNumber_1)
+{
+ cv::GMat in;
+ cv::GComputation cc(in, in+in);
+
+ const auto desc1 = cv::GMatDesc{CV_8U,1,{64,64}};
+ const auto desc2 = cv::GMatDesc{CV_32F,1,{128,128}};
+
+ EXPECT_NO_THROW(cc.compile(desc1));
+ EXPECT_NO_THROW(cc.compile(desc2));
+
+ // FIXME: custom exception type?
+ // It is worth checking if compilation fails with different number
+ // of meta parameters
+ EXPECT_THROW(cc.compile(desc1, desc1), std::logic_error);
+ EXPECT_THROW(cc.compile(desc1, desc2, desc2), std::logic_error);
+}
+
+TEST(GAPI_MetaDesc, Compile_MatchMetaNumber_2)
+{
+ cv::GMat a, b;
+ cv::GComputation cc(cv::GIn(a, b), cv::GOut(a+b));
+
+ const auto desc1 = cv::GMatDesc{CV_8U,1,{64,64}};
+ EXPECT_NO_THROW(cc.compile(desc1, desc1));
+
+ const auto desc2 = cv::GMatDesc{CV_32F,1,{128,128}};
+ EXPECT_NO_THROW(cc.compile(desc2, desc2));
+
+ // FIXME: custom exception type?
+ EXPECT_THROW(cc.compile(desc1), std::logic_error);
+ EXPECT_THROW(cc.compile(desc2), std::logic_error);
+ EXPECT_THROW(cc.compile(desc2, desc2, desc2), std::logic_error);
+}
+
+TEST(GAPI_MetaDesc, Compile_MatchMetaType_Mat)
+{
+ cv::GMat in;
+ cv::GComputation cc(in, in+in);
+
+ EXPECT_NO_THROW(cc.compile(cv::GMatDesc{CV_8U,1,{64,64}}));
+
+ // FIXME: custom exception type?
+ EXPECT_THROW(cc.compile(cv::empty_scalar_desc()), std::logic_error);
+}
+
+TEST(GAPI_MetaDesc, Compile_MatchMetaType_Scalar)
+{
+ cv::GScalar in;
+ cv::GComputation cc(cv::GIn(in), cv::GOut(KTest::on(in)));
+
+ const auto desc1 = cv::descr_of(cv::Scalar(128));
+ const auto desc2 = cv::GMatDesc{CV_8U,1,{64,64}};
+ const auto pkg = cv::gapi::kernels<GOCVScalarTest>();
+ EXPECT_NO_THROW(cc.compile(desc1, cv::compile_args(pkg)));
+
+ // FIXME: custom exception type?
+ EXPECT_THROW(cc.compile(desc2, cv::compile_args(pkg)), std::logic_error);
+}
+
+TEST(GAPI_MetaDesc, Compile_MatchMetaType_Mixed)
+{
+ cv::GMat a;
+ cv::GScalar v;
+ cv::GComputation cc(cv::GIn(a, v), cv::GOut(cv::gapi::addC(a, v)));
+
+ const auto desc1 = cv::GMatDesc{CV_8U,1,{64,64}};
+ const auto desc2 = cv::descr_of(cv::Scalar(4));
+
+ EXPECT_NO_THROW(cc.compile(desc1, desc2));
+
+ // FIXME: custom exception type(s)?
+ EXPECT_THROW(cc.compile(desc1), std::logic_error);
+ EXPECT_THROW(cc.compile(desc2), std::logic_error);
+ EXPECT_THROW(cc.compile(desc2, desc1), std::logic_error);
+ EXPECT_THROW(cc.compile(desc1, desc1, desc1), std::logic_error);
+ EXPECT_THROW(cc.compile(desc1, desc2, desc1), std::logic_error);
+}
+
+TEST(GAPI_MetaDesc, Typed_Compile_MatchMetaNumber_1)
+{
+ cv::GComputationT<cv::GMat(cv::GMat)> cc([](cv::GMat in)
+ {
+ return in+in;
+ });
+
+ const auto desc1 = cv::GMatDesc{CV_8U,1,{64,64}};
+ const auto desc2 = cv::GMatDesc{CV_32F,1,{128,128}};
+
+ EXPECT_NO_THROW(cc.compile(desc1));
+ EXPECT_NO_THROW(cc.compile(desc2));
+}
+
+TEST(GAPI_MetaDesc, Typed_Compile_MatchMetaNumber_2)
+{
+ cv::GComputationT<cv::GMat(cv::GMat,cv::GMat)> cc([](cv::GMat a, cv::GMat b)
+ {
+ return a + b;
+ });
+
+ const auto desc1 = cv::GMatDesc{CV_8U,1,{64,64}};
+ EXPECT_NO_THROW(cc.compile(desc1, desc1));
+
+ const auto desc2 = cv::GMatDesc{CV_32F,1,{128,128}};
+ EXPECT_NO_THROW(cc.compile(desc2, desc2));
+}
+
+TEST(GAPI_MetaDesc, Typed_Compile_MatchMetaType_Mat)
+{
+ cv::GComputationT<cv::GMat(cv::GMat)> cc([](cv::GMat in)
+ {
+ return in+in;
+ });
+
+ EXPECT_NO_THROW(cc.compile(cv::GMatDesc{CV_8U,1,{64,64}}));
+}
+
+TEST(GAPI_MetaDesc, Typed_Compile_MatchMetaType_Scalar)
+{
+ cv::GComputationT<cv::GScalar(cv::GScalar)> cc([](cv::GScalar in)
+ {
+ return KTest::on(in);
+ });
+
+ const auto desc1 = cv::descr_of(cv::Scalar(128));
+ const auto pkg = cv::gapi::kernels<GOCVScalarTest>();
+ // EXPECT_NO_THROW(cc.compile(desc1, cv::compile_args(pkg)));
+ cc.compile(desc1, cv::compile_args(pkg));
+}
+
+TEST(GAPI_MetaDesc, Typed_Compile_MatchMetaType_Mixed)
+{
+ cv::GComputationT<cv::GMat(cv::GMat,cv::GScalar)> cc([](cv::GMat a, cv::GScalar v)
+ {
+ return cv::gapi::addC(a, v);
+ });
+
+ const auto desc1 = cv::GMatDesc{CV_8U,1,{64,64}};
+ const auto desc2 = cv::descr_of(cv::Scalar(4));
+
+ EXPECT_NO_THROW(cc.compile(desc1, desc2));
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_resize_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_resize_test.cpp
new file mode 100644
index 000000000..bc0b991e6
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_resize_test.cpp
@@ -0,0 +1,720 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include "gapi_fluid_test_kernels.hpp"
+
+namespace opencv_test
+{
+
+using namespace cv::gapi_test_kernels;
+
+G_TYPED_KERNEL(TCopy, <GMat(GMat)>, "test.fluid.copy")
+{
+ static GMatDesc outMeta(const cv::GMatDesc &in) {
+ return in;
+ }
+};
+
+GAPI_FLUID_KERNEL(FCopy, TCopy, false)
+{
+ static const int Window = 1;
+
+ static void run(const cv::gapi::fluid::View &in,
+ cv::gapi::fluid::Buffer &out)
+ {
+ const uint8_t* in_row = in .InLine <uint8_t>(0);
+ uint8_t* out_row = out.OutLine<uint8_t>();
+
+ for (int i = 0, w = in.length(); i < w; i++)
+ {
+ //std::cout << std::setw(4) << int(in_row[i]);
+ out_row[i] = in_row[i];
+ }
+ //std::cout << std::endl;
+ }
+};
+
+GAPI_FLUID_KERNEL(FResizeNN1Lpi, cv::gapi::core::GResize, false)
+{
+ static const int Window = 1;
+ static const auto Kind = GFluidKernel::Kind::Resize;
+
+ static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int /*interp*/,
+ cv::gapi::fluid::Buffer& out)
+
+ {
+ auto length = out.length();
+ double vRatio = (double)in.meta().size.height / out.meta().size.height;
+ double hRatio = (double)in.length() / length;
+ auto y = out.y();
+ auto inY = in.y();
+
+ for (int l = 0; l < out.lpi(); l++)
+ {
+ auto sy = static_cast<int>((y+l) * vRatio);
+ int idx = sy - inY;
+
+ const auto src = in.InLine <unsigned char>(idx);
+ auto dst = out.OutLine<unsigned char>(l);
+
+ for (int x = 0; x < length; x++)
+ {
+ auto inX = static_cast<int>(x * hRatio);
+ dst[x] = src[inX];
+ }
+ }
+ }
+};
+
+namespace
+{
+namespace func
+{
+template <class Mapper>
+void initScratch(const cv::GMatDesc& in, cv::Size outSz, cv::gapi::fluid::Buffer &scratch)
+{
+ CV_Assert(in.depth == CV_8U && in.chan == 1);
+
+ cv::Size scratch_size{static_cast<int>(outSz.width * sizeof(typename Mapper::Unit)), 1};
+
+ cv::GMatDesc desc;
+ desc.chan = 1;
+ desc.depth = CV_8UC1;
+ desc.size = scratch_size;
+
+ cv::gapi::fluid::Buffer buffer(desc);
+ scratch = std::move(buffer);
+
+ auto mapX = scratch.OutLine<typename Mapper::Unit>();
+ double hRatio = (double)in.size.width / outSz.width;
+
+ for (int x = 0, w = outSz.width; x < w; x++)
+ {
+ mapX[x] = Mapper::map(hRatio, 0, in.size.width, x);
+ }
+}
+
+template <class Mapper>
+inline void calcRow(const cv::gapi::fluid::View& in, cv::gapi::fluid::Buffer& out, cv::gapi::fluid::Buffer &scratch)
+{
+ double vRatio = (double)in.meta().size.height / out.meta().size.height;
+ auto mapX = scratch.OutLine<typename Mapper::Unit>();
+ auto inY = in.y();
+ auto inH = in.meta().size.height;
+ auto outY = out.y();
+ auto length = out.length();
+
+ for (int l = 0; l < out.lpi(); l++)
+ {
+ auto mapY = Mapper::map(vRatio, inY, inH, outY + l);
+
+ const auto src0 = in.InLine <unsigned char>(mapY.s0);
+ const auto src1 = in.InLine <unsigned char>(mapY.s1);
+
+ auto dst = out.OutLine<unsigned char>(l);
+
+ for (int x = 0; x < length; x++)
+ {
+ auto alpha0 = mapX[x].alpha0;
+ auto alpha1 = mapX[x].alpha1;
+ auto sx0 = mapX[x].s0;
+ auto sx1 = mapX[x].s1;
+
+ int res0 = src0[sx0]*alpha0 + src0[sx1]*alpha1;
+ int res1 = src1[sx0]*alpha0 + src1[sx1]*alpha1;
+
+ dst[x] = uchar(( ((mapY.alpha0 * (res0 >> 4)) >> 16) + ((mapY.alpha1 * (res1 >> 4)) >> 16) + 2)>>2);
+ }
+ }
+}
+} // namespace func
+
+constexpr static const int INTER_RESIZE_COEF_BITS = 11;
+constexpr static const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;
+
+namespace linear
+{
+struct Mapper
+{
+ struct Unit
+ {
+ short alpha0;
+ short alpha1;
+ int s0;
+ int s1;
+ };
+
+ static inline Unit map(double ratio, int start, int max, int outCoord)
+ {
+ auto f = static_cast<float>((outCoord + 0.5f) * ratio - 0.5f);
+ int s = cvFloor(f);
+ f -= s;
+
+ Unit u;
+
+ u.s0 = std::max(s - start, 0);
+ u.s1 = ((f == 0.0) || s + 1 >= max) ? s - start : s - start + 1;
+
+ u.alpha0 = saturate_cast<short>((1.0f - f) * INTER_RESIZE_COEF_SCALE);
+ u.alpha1 = saturate_cast<short>((f) * INTER_RESIZE_COEF_SCALE);
+
+ return u;
+ }
+};
+
+} // namespace linear
+
+namespace areaUpscale
+{
+struct Mapper
+{
+ struct Unit
+ {
+ short alpha0;
+ short alpha1;
+ int s0;
+ int s1;
+ };
+
+ static inline Unit map(double ratio, int start, int max, int outCoord)
+ {
+ int s = cvFloor(outCoord*ratio);
+ float f = (float)((outCoord+1) - (s+1)/ratio);
+ f = f <= 0 ? 0.f : f - cvFloor(f);
+
+ Unit u;
+
+ u.s0 = std::max(s - start, 0);
+ u.s1 = ((f == 0.0) || s + 1 >= max) ? s - start : s - start + 1;
+
+ u.alpha0 = saturate_cast<short>((1.0f - f) * INTER_RESIZE_COEF_SCALE);
+ u.alpha1 = saturate_cast<short>((f) * INTER_RESIZE_COEF_SCALE);
+
+ return u;
+ }
+};
+} // namespace areaUpscale
+} // anonymous namespace
+
+GAPI_FLUID_KERNEL(FResizeLinear1Lpi, cv::gapi::core::GResize, true)
+{
+ static const int Window = 1;
+ static const auto Kind = GFluidKernel::Kind::Resize;
+
+ static void initScratch(const cv::GMatDesc& in,
+ cv::Size outSz, double /*fx*/, double /*fy*/, int /*interp*/,
+ cv::gapi::fluid::Buffer &scratch)
+ {
+ func::initScratch<linear::Mapper>(in, outSz, scratch);
+ }
+
+ static void resetScratch(cv::gapi::fluid::Buffer& /*scratch*/)
+ {}
+
+ static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int /*interp*/,
+ cv::gapi::fluid::Buffer& out, cv::gapi::fluid::Buffer &scratch)
+
+ {
+ func::calcRow<linear::Mapper>(in, out, scratch);
+ }
+};
+
+namespace
+{
+// FIXME
+// Move to some common place (to reuse/align with ResizeAgent)
+auto startInCoord = [](int outCoord, double ratio) {
+ return static_cast<int>(outCoord * ratio + 1e-3);
+};
+auto endInCoord = [](int outCoord, double ratio) {
+ return static_cast<int>(std::ceil((outCoord + 1) * ratio - 1e-3));
+};
+} // namespace
+
+GAPI_FLUID_KERNEL(FResizeArea1Lpi, cv::gapi::core::GResize, false)
+{
+ static const int Window = 1;
+ static const auto Kind = GFluidKernel::Kind::Resize;
+
+ static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int /*interp*/,
+ cv::gapi::fluid::Buffer& out)
+
+ {
+ auto firstOutLineIdx = out.y();
+ auto firstViewLineIdx = in.y();
+ auto length = out.length();
+ double vRatio = (double)in.meta().size.height / out.meta().size.height;
+ double hRatio = (double)in.length() / length;
+
+ for (int l = 0; l < out.lpi(); l++)
+ {
+ int outY = firstOutLineIdx + l;
+ int startY = startInCoord(outY, vRatio);
+ int endY = endInCoord (outY, vRatio);
+
+ auto dst = out.OutLine<unsigned char>(l);
+
+ for (int x = 0; x < length; x++)
+ {
+ float res = 0.0;
+
+ int startX = startInCoord(x, hRatio);
+ int endX = endInCoord (x, hRatio);
+
+ for (int inY = startY; inY < endY; inY++)
+ {
+ double startCoordY = inY / vRatio;
+ double endCoordY = startCoordY + 1/vRatio;
+
+ if (startCoordY < outY) startCoordY = outY;
+ if (endCoordY > outY + 1) endCoordY = outY + 1;
+
+ float fracY = static_cast<float>((inY == startY || inY == endY - 1) ? endCoordY - startCoordY : 1/vRatio);
+
+ const auto src = in.InLine <unsigned char>(inY - firstViewLineIdx);
+
+ float rowSum = 0.0f;
+
+ for (int inX = startX; inX < endX; inX++)
+ {
+ double startCoordX = inX / hRatio;
+ double endCoordX = startCoordX + 1/hRatio;
+
+ if (startCoordX < x) startCoordX = x;
+ if (endCoordX > x + 1) endCoordX = x + 1;
+
+ float fracX = static_cast<float>((inX == startX || inX == endX - 1) ? endCoordX - startCoordX : 1/hRatio);
+
+ rowSum += src[inX] * fracX;
+ }
+ res += rowSum * fracY;
+ }
+ dst[x] = static_cast<unsigned char>(std::rint(res));
+ }
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(FResizeAreaUpscale1Lpi, cv::gapi::core::GResize, true)
+{
+ static const int Window = 1;
+ static const auto Kind = GFluidKernel::Kind::Resize;
+
+ static void initScratch(const cv::GMatDesc& in,
+ cv::Size outSz, double /*fx*/, double /*fy*/, int /*interp*/,
+ cv::gapi::fluid::Buffer &scratch)
+ {
+ func::initScratch<areaUpscale::Mapper>(in, outSz, scratch);
+ }
+
+ static void resetScratch(cv::gapi::fluid::Buffer& /*scratch*/)
+ {}
+
+ static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int /*interp*/,
+ cv::gapi::fluid::Buffer& out, cv::gapi::fluid::Buffer &scratch)
+ {
+ func::calcRow<areaUpscale::Mapper>(in, out, scratch);
+ }
+};
+
+#define ADD_RESIZE_KERNEL_WITH_LPI(interp, lpi, scratch) \
+struct Resize##interp##lpi##LpiHelper : public FResize##interp##1Lpi { static const int LPI = lpi; }; \
+struct FResize##interp##lpi##Lpi : public cv::GFluidKernelImpl<Resize##interp##lpi##LpiHelper, cv::gapi::core::GResize, scratch>{};
+
+ADD_RESIZE_KERNEL_WITH_LPI(NN, 2, false)
+ADD_RESIZE_KERNEL_WITH_LPI(NN, 3, false)
+ADD_RESIZE_KERNEL_WITH_LPI(NN, 4, false)
+
+ADD_RESIZE_KERNEL_WITH_LPI(Linear, 2, true)
+ADD_RESIZE_KERNEL_WITH_LPI(Linear, 3, true)
+ADD_RESIZE_KERNEL_WITH_LPI(Linear, 4, true)
+
+ADD_RESIZE_KERNEL_WITH_LPI(Area, 2, false)
+ADD_RESIZE_KERNEL_WITH_LPI(Area, 3, false)
+ADD_RESIZE_KERNEL_WITH_LPI(Area, 4, false)
+
+ADD_RESIZE_KERNEL_WITH_LPI(AreaUpscale, 2, true)
+ADD_RESIZE_KERNEL_WITH_LPI(AreaUpscale, 3, true)
+ADD_RESIZE_KERNEL_WITH_LPI(AreaUpscale, 4, true)
+#undef ADD_RESIZE_KERNEL_WITH_LPI
+
+static auto fluidResizeTestPackage = [](int interpolation, cv::Size szIn, cv::Size szOut, int lpi = 1)
+{
+ using namespace cv;
+ using namespace cv::gapi;
+ bool upscale = szIn.width < szOut.width || szIn.height < szOut.height;
+
+#define RESIZE_CASE(interp, lpi) \
+ case lpi: pkg = kernels<FCopy, FResize##interp##lpi##Lpi>(); break;
+
+#define RESIZE_SWITCH(interp) \
+ switch(lpi) \
+ { \
+ RESIZE_CASE(interp, 1) \
+ RESIZE_CASE(interp, 2) \
+ RESIZE_CASE(interp, 3) \
+ RESIZE_CASE(interp, 4) \
+ default: CV_Assert(false); \
+ }
+
+ GKernelPackage pkg;
+ switch (interpolation)
+ {
+ case INTER_NEAREST: RESIZE_SWITCH(NN); break;
+ case INTER_LINEAR: RESIZE_SWITCH(Linear); break;
+ case INTER_AREA:
+ {
+ if (upscale)
+ {
+ RESIZE_SWITCH(AreaUpscale)
+ }
+ else
+ {
+ RESIZE_SWITCH(Area);
+ }
+ }break;
+ default: CV_Assert(false);
+ }
+ return combine(pkg, fluidTestPackage, unite_policy::KEEP);
+
+#undef RESIZE_SWITCH
+#undef RESIZE_CASE
+};
+
+struct ResizeTestFluid : public TestWithParam<std::tuple<int, int, cv::Size, std::tuple<cv::Size, cv::Rect>, int, double>> {};
+TEST_P(ResizeTestFluid, SanityTest)
+{
+ int type = 0, interp = 0;
+ cv::Size sz_in, sz_out;
+ int lpi = 0;
+ double tolerance = 0.0;
+ cv::Rect outRoi;
+ std::tuple<cv::Size, cv::Rect> outSizeAndRoi;
+ std::tie(type, interp, sz_in, outSizeAndRoi, lpi, tolerance) = GetParam();
+ std::tie(sz_out, outRoi) = outSizeAndRoi;
+ if (outRoi == cv::Rect{}) outRoi = {0,0,sz_out.width,sz_out.height};
+ if (outRoi.width == 0) outRoi.width = sz_out.width;
+ double fx = 0, fy = 0;
+
+ cv::Mat in_mat1 (sz_in, type );
+ cv::Scalar mean = cv::Scalar(127);
+ cv::Scalar stddev = cv::Scalar(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+
+ cv::Mat out_mat = cv::Mat::zeros(sz_out, type);
+ cv::Mat out_mat_ocv = cv::Mat::zeros(sz_out, type);
+
+ cv::GMat in;
+ auto mid = TBlur3x3::on(in, cv::BORDER_REPLICATE, {});
+ auto out = cv::gapi::resize(mid, sz_out, fx, fy, interp);
+
+ cv::GComputation c(in, out);
+ c.apply(in_mat1, out_mat, cv::compile_args(GFluidOutputRois{{outRoi}}, fluidResizeTestPackage(interp, sz_in, sz_out, lpi)));
+
+ cv::Mat mid_mat;
+ cv::blur(in_mat1, mid_mat, {3,3}, {-1,-1}, cv::BORDER_REPLICATE);
+ cv::resize(mid_mat, out_mat_ocv, sz_out, fx, fy, interp);
+
+ cv::Mat absDiff;
+ cv::absdiff(out_mat(outRoi), out_mat_ocv(outRoi), absDiff);
+ EXPECT_EQ(0, cv::countNonZero(absDiff > tolerance));
+}
+
+INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTestFluid,
+ Combine(Values(CV_8UC1),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR),
+ Values(cv::Size(8, 7),
+ cv::Size(8, 8),
+ cv::Size(8, 64),
+ cv::Size(8, 25),
+ cv::Size(16, 8),
+ cv::Size(16, 7)),
+ Values(std::make_tuple(cv::Size(5, 4), cv::Rect{}),
+ std::make_tuple(cv::Size(5, 4), cv::Rect{0, 0, 0, 2}),
+ std::make_tuple(cv::Size(5, 4), cv::Rect{0, 1, 0, 2}),
+ std::make_tuple(cv::Size(5, 4), cv::Rect{0, 2, 0, 2}),
+ std::make_tuple(cv::Size(7, 7), cv::Rect{}),
+ std::make_tuple(cv::Size(7, 7), cv::Rect{0, 0, 0, 3}),
+ std::make_tuple(cv::Size(7, 7), cv::Rect{0, 2, 0, 2}),
+ std::make_tuple(cv::Size(7, 7), cv::Rect{0, 4, 0, 3}),
+ std::make_tuple(cv::Size(8, 4), cv::Rect{}),
+ std::make_tuple(cv::Size(8, 4), cv::Rect{0, 0, 0, 3}),
+ std::make_tuple(cv::Size(8, 4), cv::Rect{0, 1, 0, 2}),
+ std::make_tuple(cv::Size(8, 4), cv::Rect{0, 3, 0, 1})),
+ Values(1, 2, 3, 4), // lpi
+ Values(0.0)));
+
+INSTANTIATE_TEST_CASE_P(ResizeAreaTestCPU, ResizeTestFluid,
+ Combine(Values(CV_8UC1),
+ Values(cv::INTER_AREA),
+ Values(cv::Size(8, 7),
+ cv::Size(8, 8),
+ cv::Size(8, 64),
+ cv::Size(8, 25),
+ cv::Size(16, 8),
+ cv::Size(16, 7)),
+ Values(std::make_tuple(cv::Size(5, 4), cv::Rect{}),
+ std::make_tuple(cv::Size(5, 4), cv::Rect{0, 0, 0, 2}),
+ std::make_tuple(cv::Size(5, 4), cv::Rect{0, 1, 0, 2}),
+ std::make_tuple(cv::Size(5, 4), cv::Rect{0, 2, 0, 2}),
+ std::make_tuple(cv::Size(7, 7), cv::Rect{}),
+ std::make_tuple(cv::Size(7, 7), cv::Rect{0, 0, 0, 3}),
+ std::make_tuple(cv::Size(7, 7), cv::Rect{0, 2, 0, 2}),
+ std::make_tuple(cv::Size(7, 7), cv::Rect{0, 4, 0, 3}),
+ std::make_tuple(cv::Size(8, 4), cv::Rect{}),
+ std::make_tuple(cv::Size(8, 4), cv::Rect{0, 0, 0, 3}),
+ std::make_tuple(cv::Size(8, 4), cv::Rect{0, 1, 0, 2}),
+ std::make_tuple(cv::Size(8, 4), cv::Rect{0, 3, 0, 1})),
+ Values(1, 2, 3, 4), // lpi
+ // Actually this tolerance only for cases where OpenCV
+ // uses ResizeAreaFast
+ Values(1.0)));
+
+INSTANTIATE_TEST_CASE_P(ResizeUpscaleTestCPU, ResizeTestFluid,
+ Combine(Values(CV_8UC1),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values(cv::Size(1, 5),
+ cv::Size(3, 5),
+ cv::Size(7, 5),
+ cv::Size(1, 7),
+ cv::Size(3, 7),
+ cv::Size(7, 7)),
+ Values(std::make_tuple(cv::Size(8, 8), cv::Rect{0,0,8,2}),
+ std::make_tuple(cv::Size(8, 8), cv::Rect{0,2,8,2}),
+ std::make_tuple(cv::Size(8, 8), cv::Rect{0,4,8,2}),
+ std::make_tuple(cv::Size(8, 8), cv::Rect{0,6,8,2}),
+ std::make_tuple(cv::Size(8, 8), cv::Rect{0,0,8,8}),
+ std::make_tuple(cv::Size(16, 8), cv::Rect{}),
+ std::make_tuple(cv::Size(16, 64), cv::Rect{0, 0,16,16}),
+ std::make_tuple(cv::Size(16, 64), cv::Rect{0,16,16,16}),
+ std::make_tuple(cv::Size(16, 64), cv::Rect{0,32,16,16}),
+ std::make_tuple(cv::Size(16, 64), cv::Rect{0,48,16,16}),
+ std::make_tuple(cv::Size(16, 64), cv::Rect{0, 0,16,64}),
+ std::make_tuple(cv::Size(16, 25), cv::Rect{0, 0,16, 7}),
+ std::make_tuple(cv::Size(16, 25), cv::Rect{0, 7,16, 6}),
+ std::make_tuple(cv::Size(16, 25), cv::Rect{0,13,16, 6}),
+ std::make_tuple(cv::Size(16, 25), cv::Rect{0,19,16, 6}),
+ std::make_tuple(cv::Size(16, 25), cv::Rect{0, 0,16, 7}),
+ std::make_tuple(cv::Size(16, 25), cv::Rect{0, 7,16, 7}),
+ std::make_tuple(cv::Size(16, 25), cv::Rect{0,14,16, 7}),
+ std::make_tuple(cv::Size(16, 25), cv::Rect{0,21,16, 4}),
+ std::make_tuple(cv::Size(16, 25), cv::Rect{0, 0,16,25}),
+ std::make_tuple(cv::Size(16, 7), cv::Rect{}),
+ std::make_tuple(cv::Size(16, 8), cv::Rect{})),
+ Values(1, 2, 3, 4), // lpi
+ Values(0.0)));
+
+INSTANTIATE_TEST_CASE_P(ResizeUpscaleOneDimDownscaleAnother, ResizeTestFluid,
+ Combine(Values(CV_8UC1),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values(cv::Size(6, 6),
+ cv::Size(8, 7),
+ cv::Size(8, 8),
+ cv::Size(8, 10),
+ cv::Size(10, 8),
+ cv::Size(10, 7)),
+ Values(std::make_tuple(cv::Size(11, 5), cv::Rect{}),
+ std::make_tuple(cv::Size(11, 5), cv::Rect{0, 0, 0, 2}),
+ std::make_tuple(cv::Size(11, 5), cv::Rect{0, 2, 0, 2}),
+ std::make_tuple(cv::Size(11, 5), cv::Rect{0, 4, 0, 1}),
+ std::make_tuple(cv::Size(12, 2), cv::Rect{}),
+ std::make_tuple(cv::Size(12, 2), cv::Rect{0, 0, 0, 1}),
+ std::make_tuple(cv::Size(12, 2), cv::Rect{0, 1, 0, 1}),
+ std::make_tuple(cv::Size(23, 3), cv::Rect{}),
+ std::make_tuple(cv::Size(23, 3), cv::Rect{0, 0, 0, 1}),
+ std::make_tuple(cv::Size(23, 3), cv::Rect{0, 1, 0, 1}),
+ std::make_tuple(cv::Size(23, 3), cv::Rect{0, 2, 0, 1}),
+ std::make_tuple(cv::Size(3, 24), cv::Rect{}),
+ std::make_tuple(cv::Size(3, 24), cv::Rect{0, 0, 0, 6}),
+ std::make_tuple(cv::Size(3, 24), cv::Rect{0, 6, 0, 6}),
+ std::make_tuple(cv::Size(3, 24), cv::Rect{0, 12, 0, 6}),
+ std::make_tuple(cv::Size(3, 24), cv::Rect{0, 18, 0, 6}),
+ std::make_tuple(cv::Size(5, 11), cv::Rect{}),
+ std::make_tuple(cv::Size(5, 11), cv::Rect{0, 0, 0, 3}),
+ std::make_tuple(cv::Size(5, 11), cv::Rect{0, 3, 0, 3}),
+ std::make_tuple(cv::Size(5, 11), cv::Rect{0, 6, 0, 3}),
+ std::make_tuple(cv::Size(5, 11), cv::Rect{0, 9, 0, 2})),
+ Values(1, 2, 3, 4), // lpi
+ Values(0.0)));
+
+INSTANTIATE_TEST_CASE_P(Resize400_384TestCPU, ResizeTestFluid,
+ Combine(Values(CV_8UC1),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values(cv::Size(128, 400)),
+ Values(std::make_tuple(cv::Size(128, 384), cv::Rect{})),
+ Values(1, 2, 3, 4), // lpi
+ Values(0.0)));
+
+INSTANTIATE_TEST_CASE_P(Resize220_400TestCPU, ResizeTestFluid,
+ Combine(Values(CV_8UC1),
+ Values(cv::INTER_LINEAR),
+ Values(cv::Size(220, 220)),
+ Values(std::make_tuple(cv::Size(400, 400), cv::Rect{})),
+ Values(1, 2, 3, 4), // lpi
+ Values(0.0)));
+
+static auto cvBlur = [](const cv::Mat& in, cv::Mat& out, int kernelSize)
+{
+ if (kernelSize == 1)
+ {
+ out = in;
+ }
+ else
+ {
+ cv::blur(in, out, {kernelSize, kernelSize});
+ }
+};
+
+using SizesWithRois = std::tuple<cv::Size, cv::Rect, cv::Size, cv::Rect>;
+struct ResizeAndAnotherReaderTest : public TestWithParam<std::tuple<int, int, bool, SizesWithRois>>{};
+TEST_P(ResizeAndAnotherReaderTest, SanityTest)
+{
+ bool readFromInput = false;
+ int interp = -1, kernelSize = -1;
+ SizesWithRois sizesWithRois;
+ std::tie(interp, kernelSize, readFromInput, sizesWithRois) = GetParam();
+
+ cv::Size sz, resizedSz;
+ cv::Rect roi, resizedRoi;
+ std::tie(sz, roi, resizedSz, resizedRoi) = sizesWithRois;
+
+ cv::Mat in_mat(sz, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127);
+ cv::Scalar stddev = cv::Scalar(40.f);
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Mat gapi_resize_out = cv::Mat::zeros(resizedSz, CV_8UC1);
+ cv::Mat gapi_blur_out = cv::Mat::zeros(sz, CV_8UC1);
+
+ auto blur = kernelSize == 1 ? &TBlur1x1::on : kernelSize == 3 ? &TBlur3x3::on : &TBlur5x5::on;
+
+ cv::GMat in, resize_out, blur_out;
+
+ if (readFromInput)
+ {
+ resize_out = gapi::resize(in, resizedSz, 0, 0, interp);
+ blur_out = blur(in, cv::BORDER_DEFAULT, {});
+ }
+ else
+ {
+ auto mid = TCopy::on(in);
+ resize_out = gapi::resize(mid, resizedSz, 0, 0, interp);
+ blur_out = blur(mid, cv::BORDER_DEFAULT, {});
+ }
+
+ cv::GComputation c(GIn(in), GOut(resize_out, blur_out));
+ c.apply(gin(in_mat), gout(gapi_resize_out, gapi_blur_out), cv::compile_args(GFluidOutputRois{{resizedRoi, roi}},
+ fluidResizeTestPackage(interp, sz, resizedSz)));
+
+ cv::Mat ocv_resize_out = cv::Mat::zeros(resizedSz, CV_8UC1);
+ cv::resize(in_mat, ocv_resize_out, resizedSz, 0, 0, interp);
+ cv::Mat ocv_blur_out = cv::Mat::zeros(sz, CV_8UC1);
+ cvBlur(in_mat, ocv_blur_out, kernelSize);
+
+ EXPECT_EQ(0, cv::countNonZero(gapi_resize_out(resizedRoi) != ocv_resize_out(resizedRoi)));
+ EXPECT_EQ(0, cv::countNonZero(gapi_blur_out(roi) != ocv_blur_out(roi)));
+}
+
+INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeAndAnotherReaderTest,
+ Combine(Values(cv::INTER_NEAREST, cv::INTER_LINEAR),
+ Values(1, 3, 5),
+ testing::Bool(), // Read from input directly or place a copy node at start
+ Values(std::make_tuple(cv::Size{8,8}, cv::Rect{0,0,8,8},
+ cv::Size{4,4}, cv::Rect{0,0,4,4}),
+ std::make_tuple(cv::Size{8,8}, cv::Rect{0,0,8,2},
+ cv::Size{4,4}, cv::Rect{0,0,4,1}),
+ std::make_tuple(cv::Size{8,8}, cv::Rect{0,2,8,4},
+ cv::Size{4,4}, cv::Rect{0,1,4,2}),
+ std::make_tuple(cv::Size{8,8}, cv::Rect{0,4,8,4},
+ cv::Size{4,4}, cv::Rect{0,2,4,2}),
+ std::make_tuple(cv::Size{64,64}, cv::Rect{0, 0,64,64},
+ cv::Size{49,49}, cv::Rect{0, 0,49,49}),
+ std::make_tuple(cv::Size{64,64}, cv::Rect{0, 0,64,15},
+ cv::Size{49,49}, cv::Rect{0, 0,49,11}),
+ std::make_tuple(cv::Size{64,64}, cv::Rect{0,11,64,23},
+ cv::Size{49,49}, cv::Rect{0, 9,49,17}),
+ std::make_tuple(cv::Size{64,64}, cv::Rect{0,50,64,14},
+ cv::Size{49,49}, cv::Rect{0,39,49,10}))));
+
+struct BlursAfterResizeTest : public TestWithParam<std::tuple<int, int, int, bool, std::tuple<cv::Size, cv::Size, cv::Rect>>>{};
+TEST_P(BlursAfterResizeTest, SanityTest)
+{
+ bool readFromInput = false;
+ int interp = -1, kernelSize1 = -1, kernelSize2 = -1;
+ std::tuple<cv::Size, cv::Size, cv::Rect> sizesWithRoi;
+ std::tie(interp, kernelSize1, kernelSize2, readFromInput, sizesWithRoi) = GetParam();
+
+ cv::Size inSz, outSz;
+ cv::Rect outRoi;
+ std::tie(inSz, outSz, outRoi) = sizesWithRoi;
+
+ cv::Mat in_mat(inSz, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127);
+ cv::Scalar stddev = cv::Scalar(40.f);
+ cv::randn(in_mat, mean, stddev);
+ cv::Mat gapi_out1 = cv::Mat::zeros(outSz, CV_8UC1);
+ cv::Mat gapi_out2 = cv::Mat::zeros(outSz, CV_8UC1);
+
+ auto blur1 = kernelSize1 == 1 ? &TBlur1x1::on : kernelSize1 == 3 ? &TBlur3x3::on : &TBlur5x5::on;
+ auto blur2 = kernelSize2 == 1 ? &TBlur1x1::on : kernelSize2 == 3 ? &TBlur3x3::on : &TBlur5x5::on;
+
+ cv::GMat in, out1, out2;
+ if (readFromInput)
+ {
+ auto resized = gapi::resize(in, outSz, 0, 0, interp);
+ out1 = blur1(resized, cv::BORDER_DEFAULT, {});
+ out2 = blur2(resized, cv::BORDER_DEFAULT, {});
+ }
+ else
+ {
+ auto mid = TCopy::on(in);
+ auto resized = gapi::resize(mid, outSz, 0, 0, interp);
+ out1 = blur1(resized, cv::BORDER_DEFAULT, {});
+ out2 = blur2(resized, cv::BORDER_DEFAULT, {});
+ }
+
+ cv::GComputation c(GIn(in), GOut(out1, out2));
+ c.apply(gin(in_mat), gout(gapi_out1, gapi_out2), cv::compile_args(GFluidOutputRois{{outRoi, outRoi}},
+ fluidResizeTestPackage(interp, inSz, outSz)));
+
+ cv::Mat ocv_out1 = cv::Mat::zeros(outSz, CV_8UC1);
+ cv::Mat ocv_out2 = cv::Mat::zeros(outSz, CV_8UC1);
+ cv::Mat resized = cv::Mat::zeros(outSz, CV_8UC1);
+ cv::resize(in_mat, resized, outSz, 0, 0, interp);
+ cvBlur(resized, ocv_out1, kernelSize1);
+ cvBlur(resized, ocv_out2, kernelSize2);
+
+ EXPECT_EQ(0, cv::countNonZero(gapi_out1(outRoi) != ocv_out1(outRoi)));
+ EXPECT_EQ(0, cv::countNonZero(gapi_out2(outRoi) != ocv_out2(outRoi)));
+}
+
+INSTANTIATE_TEST_CASE_P(ResizeTestCPU, BlursAfterResizeTest,
+ Combine(Values(cv::INTER_NEAREST, cv::INTER_LINEAR),
+ Values(1, 3, 5),
+ Values(1, 3, 5),
+ testing::Bool(), // Read from input directly or place a copy node at start
+ Values(std::make_tuple(cv::Size{8,8},
+ cv::Size{4,4}, cv::Rect{0,0,4,4}),
+ std::make_tuple(cv::Size{8,8},
+ cv::Size{4,4}, cv::Rect{0,0,4,1}),
+ std::make_tuple(cv::Size{8,8},
+ cv::Size{4,4}, cv::Rect{0,1,4,2}),
+ std::make_tuple(cv::Size{8,8},
+ cv::Size{4,4}, cv::Rect{0,2,4,2}),
+ std::make_tuple(cv::Size{64,64},
+ cv::Size{49,49}, cv::Rect{0, 0,49,49}),
+ std::make_tuple(cv::Size{64,64},
+ cv::Size{49,49}, cv::Rect{0, 0,49,11}),
+ std::make_tuple(cv::Size{64,64},
+ cv::Size{49,49}, cv::Rect{0, 9,49,17}),
+ std::make_tuple(cv::Size{64,64},
+ cv::Size{49,49}, cv::Rect{0,39,49,10}))));
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_roi_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_roi_test.cpp
new file mode 100644
index 000000000..ee8674ede
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_roi_test.cpp
@@ -0,0 +1,197 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include "gapi_fluid_test_kernels.hpp"
+
+namespace opencv_test
+{
+
+using namespace cv::gapi_test_kernels;
+
+struct PartialComputation : public TestWithParam <std::tuple<cv::Rect>> {};
+TEST_P(PartialComputation, Test)
+{
+ cv::Rect roi;
+ std::tie(roi) = GetParam();
+
+ int borderType = BORDER_REPLICATE;
+ int kernelSize = 3;
+ cv::Point anchor = {-1, -1};
+
+ cv::GMat in;
+ cv::GMat out = TBlur3x3::on(in, borderType, {});
+ cv::GComputation c(cv::GIn(in), cv::GOut(out));
+
+ const auto sz = cv::Size(8, 10);
+ cv::Mat in_mat(sz, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Mat out_mat_gapi = cv::Mat::zeros(sz, CV_8UC1);
+ cv::Mat out_mat_ocv = cv::Mat::zeros(sz, CV_8UC1);
+
+ // Run G-API
+ auto cc = c.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage, GFluidOutputRois{{to_own(roi)}}));
+ cc(cv::gin(in_mat), cv::gout(out_mat_gapi));
+
+ // Check with OpenCV
+ if (roi == cv::Rect{}) roi = cv::Rect{0,0,sz.width,sz.height};
+ cv::blur(in_mat(roi), out_mat_ocv(roi), {kernelSize, kernelSize}, anchor, borderType);
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+}
+
+INSTANTIATE_TEST_CASE_P(Fluid, PartialComputation,
+ Values(cv::Rect{}, cv::Rect{0,0,8,6}, cv::Rect{0,1,8,3},
+ cv::Rect{0,2,8,3}, cv::Rect{0,3,8,5}, cv::Rect{0,4,8,6}));
+
+struct PartialComputationAddC : public TestWithParam <std::tuple<cv::Rect>> {};
+TEST_P(PartialComputationAddC, Test)
+{
+ cv::Rect roi;
+ std::tie(roi) = GetParam();
+
+ cv::GMat in;
+ cv::GMat out = TAddCSimple::on(in, 1);
+ cv::GComputation c(cv::GIn(in), cv::GOut(out));
+
+ const auto sz = cv::Size(8, 10);
+ cv::Mat in_mat(sz, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Mat out_mat_gapi = cv::Mat::zeros(sz, CV_8UC1);
+ cv::Mat out_mat_ocv = cv::Mat::zeros(sz, CV_8UC1);
+
+ // Run G-API
+ auto cc = c.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage, GFluidOutputRois{{to_own(roi)}}));
+ cc(cv::gin(in_mat), cv::gout(out_mat_gapi));
+
+ // Check with OpenCV
+ if (roi == cv::Rect{}) roi = cv::Rect{0,0,sz.width,sz.height};
+ out_mat_ocv(roi) = in_mat(roi) + 1;
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+}
+
+INSTANTIATE_TEST_CASE_P(FluidRoi, PartialComputationAddC,
+ Values(cv::Rect{}, cv::Rect{0,0,8,6}, cv::Rect{0,1,8,3},
+ cv::Rect{0,2,8,3}, cv::Rect{0,3,8,5}, cv::Rect{0,4,8,6}));
+
+struct SequenceOfBlursRoiTest : public TestWithParam <std::tuple<int, cv::Rect>> {};
+TEST_P(SequenceOfBlursRoiTest, Test)
+{
+ cv::Size sz_in = { 320, 240 };
+
+ int borderType = 0;
+ cv::Rect roi;
+ std::tie(borderType, roi) = GetParam();
+ cv::Mat in_mat(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Point anchor = {-1, -1};
+ cv::Scalar borderValue(0);
+
+ GMat in;
+ auto mid = TBlur3x3::on(in, borderType, borderValue);
+ auto out = TBlur5x5::on(mid, borderType, borderValue);
+
+ Mat out_mat_gapi = Mat::zeros(sz_in, CV_8UC1);
+
+ GComputation c(GIn(in), GOut(out));
+ auto cc = c.compile(descr_of(in_mat), cv::compile_args(fluidTestPackage, GFluidOutputRois{{to_own(roi)}}));
+ cc(gin(in_mat), gout(out_mat_gapi));
+
+ cv::Mat mid_mat_ocv = Mat::zeros(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv = Mat::zeros(sz_in, CV_8UC1);
+
+ cv::blur(in_mat, mid_mat_ocv, {3,3}, anchor, borderType);
+
+ if (roi == cv::Rect{})
+ {
+ roi = cv::Rect{0, 0, sz_in.width, sz_in.height};
+ }
+
+ cv::blur(mid_mat_ocv(roi), out_mat_ocv(roi), {5,5}, anchor, borderType);
+
+ EXPECT_EQ(0, countNonZero(out_mat_ocv != out_mat_gapi));
+}
+
+INSTANTIATE_TEST_CASE_P(FluidRoi, SequenceOfBlursRoiTest,
+ Combine(Values(BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT_101),
+ Values(cv::Rect{0,0,320,240}, cv::Rect{0,64,320,128}, cv::Rect{0,128,320,112})));
+
+struct TwoBlursRoiTest : public TestWithParam <std::tuple<int, int, int, int, int, int, bool, cv::Rect>> {};
+TEST_P(TwoBlursRoiTest, Test)
+{
+ cv::Size sz_in = { 320, 240 };
+
+ int kernelSize1 = 0, kernelSize2 = 0;
+ int borderType1 = -1, borderType2 = -1;
+ cv::Scalar borderValue1{}, borderValue2{};
+ bool readFromInput = false;
+ cv::Rect outRoi;
+ std::tie(kernelSize1, borderType1, borderValue1, kernelSize2, borderType2, borderValue2, readFromInput, outRoi) = GetParam();
+ cv::Mat in_mat(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Point anchor = {-1, -1};
+
+ auto blur1 = kernelSize1 == 3 ? &TBlur3x3::on : TBlur5x5::on;
+ auto blur2 = kernelSize2 == 3 ? &TBlur3x3::on : TBlur5x5::on;
+
+ GMat in, out1, out2;
+ if (readFromInput)
+ {
+ out1 = blur1(in, borderType1, borderValue1);
+ out2 = blur2(in, borderType2, borderValue2);
+ }
+ else
+ {
+ auto mid = TAddCSimple::on(in, 0);
+ out1 = blur1(mid, borderType1, borderValue1);
+ out2 = blur2(mid, borderType2, borderValue2);
+ }
+
+ Mat out_mat_gapi1 = Mat::zeros(sz_in, CV_8UC1);
+ Mat out_mat_gapi2 = Mat::zeros(sz_in, CV_8UC1);
+
+ GComputation c(GIn(in), GOut(out1, out2));
+ auto cc = c.compile(descr_of(in_mat), cv::compile_args(fluidTestPackage, GFluidOutputRois{{outRoi, outRoi}}));
+ cc(gin(in_mat), gout(out_mat_gapi1, out_mat_gapi2));
+
+ cv::Mat out_mat_ocv1 = Mat::zeros(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv2 = Mat::zeros(sz_in, CV_8UC1);
+
+ cv::blur(in_mat(outRoi), out_mat_ocv1(outRoi), {kernelSize1, kernelSize1}, anchor, borderType1);
+ cv::blur(in_mat(outRoi), out_mat_ocv2(outRoi), {kernelSize2, kernelSize2}, anchor, borderType2);
+
+ EXPECT_EQ(0, countNonZero(out_mat_ocv1 != out_mat_gapi1));
+ EXPECT_EQ(0, countNonZero(out_mat_ocv2 != out_mat_gapi2));
+}
+
+INSTANTIATE_TEST_CASE_P(FluidRoi, TwoBlursRoiTest,
+ Combine(Values(3, 5),
+ Values(cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, cv::BORDER_REFLECT_101),
+ Values(0),
+ Values(3, 5),
+ Values(cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, cv::BORDER_REFLECT_101),
+ Values(0),
+ testing::Bool(), // Read from input directly or place a copy node at start
+ Values(cv::Rect{0,0,320,240}, cv::Rect{0,64,320,128}, cv::Rect{0,128,320,112})));
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test.cpp
new file mode 100644
index 000000000..5b3501175
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test.cpp
@@ -0,0 +1,713 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include "opencv2/gapi/core.hpp"
+
+#include "opencv2/gapi/fluid/gfluidbuffer.hpp"
+#include "opencv2/gapi/fluid/gfluidkernel.hpp"
+
+ // FIXME: move these tests with priv() to internal suite
+#include "backends/fluid/gfluidbuffer_priv.hpp"
+
+#include "gapi_fluid_test_kernels.hpp"
+#include "logger.hpp"
+
+namespace opencv_test
+{
+
+using namespace cv::gapi_test_kernels;
+
+namespace
+{
+ void WriteFunction(uint8_t* row, int nr, int w) {
+ for (int i = 0; i < w; i++)
+ row[i] = static_cast<uint8_t>(nr+i);
+ };
+ void ReadFunction1x1(const uint8_t* row, int w) {
+ for (int i = 0; i < w; i++)
+ std::cout << std::setw(4) << static_cast<int>(row[i]) << " ";
+ std::cout << "\n";
+ };
+ void ReadFunction3x3(const uint8_t* rows[3], int w) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = -1; j < w+1; j++) {
+ std::cout << std::setw(4) << static_cast<int>(rows[i][j]) << " ";
+ }
+ std::cout << "\n";
+ }
+ std::cout << "\n";
+ };
+}
+
+TEST(FluidBuffer, InputTest)
+{
+ const cv::Size buffer_size = {8,8};
+ cv::Mat in_mat = cv::Mat::eye(buffer_size, CV_8U);
+
+ cv::gapi::fluid::Buffer buffer(to_own(in_mat), true);
+ cv::gapi::fluid::View view = buffer.mkView(0, false);
+ view.priv().allocate(1, {});
+ view.priv().reset(1);
+ int this_y = 0;
+
+ while (this_y < buffer_size.height)
+ {
+ view.priv().prepareToRead();
+ const uint8_t* rrow = view.InLine<uint8_t>(0);
+ ReadFunction1x1(rrow, buffer_size.width);
+ view.priv().readDone(1,1);
+
+ cv::Mat from_buffer(1, buffer_size.width, CV_8U, const_cast<uint8_t*>(rrow));
+ EXPECT_EQ(0, cv::countNonZero(in_mat.row(this_y) != from_buffer));
+
+ this_y++;
+ }
+}
+
+TEST(FluidBuffer, CircularTest)
+{
+ const cv::Size buffer_size = {8,16};
+
+ cv::gapi::fluid::Buffer buffer(cv::GMatDesc{CV_8U,1,buffer_size}, 3, 1, 0, 1,
+ util::make_optional(cv::gapi::fluid::Border{cv::BORDER_CONSTANT, cv::gapi::own::Scalar(255)}));
+ cv::gapi::fluid::View view = buffer.mkView(1, {});
+ view.priv().reset(3);
+ view.priv().allocate(3, {});
+ buffer.debug(std::cout);
+
+ const auto whole_line_is = [](const uint8_t *line, int len, int value)
+ {
+ return std::all_of(line, line+len, [&](const uint8_t v){return v == value;});
+ };
+
+ // Store all read/written data in separate Mats to compare with
+ cv::Mat written_data(buffer_size, CV_8U);
+
+ // Simulate write/read process
+ int num_reads = 0, num_writes = 0;
+ while (num_reads < buffer_size.height)
+ {
+ if (num_writes < buffer_size.height)
+ {
+ uint8_t* wrow = buffer.OutLine<uint8_t>();
+ WriteFunction(wrow, num_writes, buffer_size.width);
+ buffer.priv().writeDone();
+
+ cv::Mat(1, buffer_size.width, CV_8U, wrow)
+ .copyTo(written_data.row(num_writes));
+ num_writes++;
+ }
+ buffer.debug(std::cout);
+
+ if (view.ready())
+ {
+ view.priv().prepareToRead();
+ const uint8_t* rrow[3] = {
+ view.InLine<uint8_t>(-1),
+ view.InLine<uint8_t>( 0),
+ view.InLine<uint8_t>( 1),
+ };
+ ReadFunction3x3(rrow, buffer_size.width);
+ view.priv().readDone(1,3);
+ buffer.debug(std::cout);
+
+ // Check borders right here
+ EXPECT_EQ(255u, rrow[0][-1]);
+ EXPECT_EQ(255u, rrow[0][buffer_size.width]);
+ if (num_reads == 0)
+ {
+ EXPECT_TRUE(whole_line_is(rrow[0]-1, buffer_size.width+2, 255u));
+ }
+ if (num_reads == buffer_size.height-1)
+ {
+ EXPECT_TRUE(whole_line_is(rrow[2]-1, buffer_size.width+2, 255u));
+ }
+
+ // Check window (without borders)
+ if (num_reads > 0 && num_reads < buffer_size.height-1)
+ {
+ // +1 everywhere since num_writes was just incremented above
+ cv::Mat written_lastLine2 = written_data.row(num_writes - (2+1));
+ cv::Mat written_lastLine1 = written_data.row(num_writes - (1+1));
+ cv::Mat written_lastLine0 = written_data.row(num_writes - (0+1));
+
+ cv::Mat read_prevLine(1, buffer_size.width, CV_8U, const_cast<uint8_t*>(rrow[0]));
+ cv::Mat read_thisLine(1, buffer_size.width, CV_8U, const_cast<uint8_t*>(rrow[1]));
+ cv::Mat read_nextLine(1, buffer_size.width, CV_8U, const_cast<uint8_t*>(rrow[2]));
+
+ EXPECT_EQ(0, cv::countNonZero(written_lastLine2 != read_prevLine));
+ EXPECT_EQ(0, cv::countNonZero(written_lastLine1 != read_thisLine));
+ EXPECT_EQ(0, cv::countNonZero(written_lastLine0 != read_nextLine));
+ }
+ num_reads++;
+ }
+ }
+}
+
+TEST(FluidBuffer, OutputTest)
+{
+ const cv::Size buffer_size = {8,16};
+ cv::Mat out_mat = cv::Mat(buffer_size, CV_8U);
+
+ cv::gapi::fluid::Buffer buffer(to_own(out_mat), false);
+ int num_writes = 0;
+ while (num_writes < buffer_size.height)
+ {
+ uint8_t* wrow = buffer.OutLine<uint8_t>();
+ WriteFunction(wrow, num_writes, buffer_size.width);
+ buffer.priv().writeDone();
+ num_writes++;
+ }
+
+ GAPI_LOG_INFO(NULL, "\n" << out_mat);
+
+ // Validity check
+ for (int r = 0; r < buffer_size.height; r++)
+ {
+ for (int c = 0; c < buffer_size.width; c++)
+ {
+ EXPECT_EQ(r+c, out_mat.at<uint8_t>(r, c));
+ }
+ }
+}
+
+TEST(Fluid, AddC_WithScalar)
+{
+ cv::GMat in;
+ cv::GScalar s;
+
+ cv::GComputation c(cv::GIn(in, s), cv::GOut(TAddScalar::on(in, s)));
+ cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1), out_mat(3, 3, CV_8UC1), ref_mat;
+ cv::Scalar in_s(100);
+
+ auto cc = c.compile(cv::descr_of(in_mat), cv::descr_of(in_s), cv::compile_args(fluidTestPackage));
+
+ cc(cv::gin(in_mat, in_s), cv::gout(out_mat));
+ ref_mat = in_mat + in_s;
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(Fluid, Scalar_In_Middle_Graph)
+{
+ cv::GMat in;
+ cv::GScalar s;
+
+ cv::GComputation c(cv::GIn(in, s), cv::GOut(TAddScalar::on(TAddCSimple::on(in, 5), s)));
+ cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1), out_mat(3, 3, CV_8UC1), ref_mat;
+ cv::Scalar in_s(100);
+
+ auto cc = c.compile(cv::descr_of(in_mat), cv::descr_of(in_s), cv::compile_args(fluidTestPackage));
+
+ cc(cv::gin(in_mat, in_s), cv::gout(out_mat));
+ ref_mat = (in_mat + 5) + in_s;
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(Fluid, Add_Scalar_To_Mat)
+{
+ cv::GMat in;
+ cv::GScalar s;
+
+ cv::GComputation c(cv::GIn(s, in), cv::GOut(TAddScalarToMat::on(s, in)));
+ cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1), out_mat(3, 3, CV_8UC1), ref_mat;
+ cv::Scalar in_s(100);
+
+ auto cc = c.compile(cv::descr_of(in_s), cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
+
+ cc(cv::gin(in_s, in_mat), cv::gout(out_mat));
+ ref_mat = in_mat + in_s;
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(Fluid, Sum_2_Mats_And_Scalar)
+{
+ cv::GMat a, b;
+ cv::GScalar s;
+
+ cv::GComputation c(cv::GIn(a, s, b), cv::GOut(TSum2MatsAndScalar::on(a, s, b)));
+ cv::Mat in_mat1 = cv::Mat::eye(3, 3, CV_8UC1),
+ in_mat2 = cv::Mat::eye(3, 3, CV_8UC1),
+ out_mat(3, 3, CV_8UC1),
+ ref_mat;
+ cv::Scalar in_s(100);
+
+ auto cc = c.compile(cv::descr_of(in_mat1), cv::descr_of(in_s), cv::descr_of(in_mat2), cv::compile_args(fluidTestPackage));
+
+ cc(cv::gin(in_mat1, in_s, in_mat2), cv::gout(out_mat));
+ ref_mat = in_mat1 + in_mat2 + in_s;
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(Fluid, Split3)
+{
+ cv::GMat bgr;
+ cv::GMat r,g,b;
+ std::tie(b,g,r) = cv::gapi::split3(bgr);
+ auto rr = TAddSimple::on(r, TId::on(b));
+ auto rrr = TAddSimple::on(TId::on(rr), g);
+ cv::GComputation c(bgr, TId::on(rrr));
+
+ cv::Size sz(5120, 5120);
+ cv::Mat eye_1 = cv::Mat::eye(sz, CV_8UC1);
+ std::vector<cv::Mat> eyes = {eye_1, eye_1, eye_1};
+ cv::Mat in_mat;
+ cv::merge(eyes, in_mat);
+ cv::Mat out_mat(sz, CV_8UC1);
+
+ // G-API
+ auto cc = c.compile(cv::descr_of(in_mat),
+ cv::compile_args(fluidTestPackage));
+ cc(in_mat, out_mat);
+
+ // OCV
+ std::vector<cv::Mat> chans;
+ cv::split(in_mat, chans);
+
+ // Compare
+ EXPECT_EQ(0, cv::countNonZero(out_mat != (chans[2]*3)));
+}
+
+TEST(Fluid, ScratchTest)
+{
+ cv::GMat in;
+ cv::GMat out = TPlusRow0::on(TPlusRow0::on(in));
+ cv::GComputation c(in, out);
+
+ cv::Size sz(8, 8);
+ cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
+ cv::Mat out_mat(sz, CV_8UC1);
+
+ // OpenCV (reference)
+ cv::Mat ref;
+ {
+ cv::Mat first_row = cv::Mat::zeros(1, sz.width, CV_8U);
+ cv::Mat remaining = cv::repeat(in_mat.row(0), sz.height-1, 1);
+ cv::Mat operand;
+ cv::vconcat(first_row, 2*remaining, operand);
+ ref = in_mat + operand;
+ }
+ GAPI_LOG_INFO(NULL, "\n" << ref);
+
+ // G-API
+ auto cc = c.compile(cv::descr_of(in_mat),
+ cv::compile_args(fluidTestPackage));
+ cc(in_mat, out_mat);
+ GAPI_LOG_INFO(NULL, "\n" << out_mat);
+ EXPECT_EQ(0, cv::countNonZero(ref != out_mat));
+
+ cc(in_mat, out_mat);
+ GAPI_LOG_INFO(NULL, "\n" << out_mat);
+ EXPECT_EQ(0, cv::countNonZero(ref != out_mat));
+}
+
+TEST(Fluid, MultipleOutRowsTest)
+{
+ cv::GMat in;
+ cv::GMat out = TAddCSimple::on(TAddCSimple::on(in, 1), 2);
+ cv::GComputation c(in, out);
+
+ cv::Size sz(4, 4);
+ cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
+ cv::Mat out_mat(sz, CV_8UC1);
+
+ auto cc = c.compile(cv::descr_of(in_mat),
+ cv::compile_args(fluidTestPackage));
+ cc(in_mat, out_mat);
+
+ std::cout << out_mat << std::endl;
+
+ cv::Mat ocv_ref = in_mat + 1 + 2;
+ EXPECT_EQ(0, cv::countNonZero(ocv_ref != out_mat));
+}
+
+
+TEST(Fluid, LPIWindow)
+{
+ cv::GMat in;
+ cv::GMat r,g,b;
+ std::tie(r,g,b) = cv::gapi::split3(in);
+ cv::GMat rr = TId7x7::on(r);
+ cv::GMat tmp = TAddSimple::on(rr, g);
+ cv::GMat out = TAddSimple::on(tmp, b);
+
+ cv::GComputation c(in, out);
+
+ cv::Size sz(8, 8);
+
+ cv::Mat eye_1 = cv::Mat::eye(sz, CV_8UC1);
+ std::vector<cv::Mat> eyes = {eye_1, eye_1, eye_1};
+ cv::Mat in_mat;
+ cv::merge(eyes, in_mat);
+
+ cv::Mat out_mat(sz, CV_8U);
+ auto cc = c.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
+ cc(in_mat, out_mat);
+
+ //std::cout << out_mat << std::endl;
+
+ // OpenCV reference
+ cv::Mat ocv_ref = eyes[0]+eyes[1]+eyes[2];
+
+ EXPECT_EQ(0, cv::countNonZero(ocv_ref != out_mat));
+}
+
+TEST(Fluid, MultipleReaders_SameLatency)
+{
+ // in -> AddC -> a -> AddC -> b -> Add -> out
+ // '--> AddC -> c -'
+ //
+ // b and c have the same skew
+
+ cv::GMat in;
+ cv::GMat a = TAddCSimple::on(in, 1); // FIXME - align naming (G, non-G)
+ cv::GMat b = TAddCSimple::on(a, 2);
+ cv::GMat c = TAddCSimple::on(a, 3);
+ cv::GMat out = TAddSimple::on(b, c);
+ cv::GComputation comp(in, out);
+
+ const auto sz = cv::Size(32, 32);
+ cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
+ cv::Mat out_mat_gapi(sz, CV_8UC1);
+ cv::Mat out_mat_ocv (sz, CV_8UC1);
+
+ // Run G-API
+ auto cc = comp.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
+ cc(in_mat, out_mat_gapi);
+
+ // Check with OpenCV
+ cv::Mat tmp = in_mat + 1;
+ out_mat_ocv = (tmp+2) + (tmp+3);
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+}
+
+TEST(Fluid, MultipleReaders_DifferentLatency)
+{
+ // in1 -> AddC -> a -> AddC -------------> b -> Add -> out
+ // '--------------> Add --> c -'
+ // '--> Id7x7-> d -'
+ //
+ // b and c have different skew (due to latency introduced by Id7x7)
+ // a is ready by multiple views with different latency.
+
+ cv::GMat in;
+ cv::GMat a = TAddCSimple::on(in, 1); // FIXME - align naming (G, non-G)
+ cv::GMat b = TAddCSimple::on(a, 2);
+ cv::GMat d = TId7x7::on(a);
+ cv::GMat c = TAddSimple::on(a, d);
+ cv::GMat out = TAddSimple::on(b, c);
+ cv::GComputation comp(in, out);
+
+ const auto sz = cv::Size(32, 32);
+ cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
+ cv::Mat out_mat_gapi(sz, CV_8UC1);
+
+ // Run G-API
+ auto cc = comp.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
+ cc(in_mat, out_mat_gapi);
+
+ // Check with OpenCV
+ cv::Mat ocv_a = in_mat + 1;
+ cv::Mat ocv_b = ocv_a + 2;
+ cv::Mat ocv_d = ocv_a;
+ cv::Mat ocv_c = ocv_a + ocv_d;
+ cv::Mat out_mat_ocv = ocv_b + ocv_c;
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+}
+
+TEST(Fluid, MultipleOutputs)
+{
+ // in -> AddC -> a -> AddC ------------------> out1
+ // `--> Id7x7 --> b --> AddC -> out2
+
+ cv::GMat in;
+ cv::GMat a = TAddCSimple::on(in, 1);
+ cv::GMat b = TId7x7::on(a);
+ cv::GMat out1 = TAddCSimple::on(a, 2);
+ cv::GMat out2 = TAddCSimple::on(b, 7);
+ cv::GComputation comp(cv::GIn(in), cv::GOut(out1, out2));
+
+ const auto sz = cv::Size(32, 32);
+ cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
+ cv::Mat out_mat_gapi1(sz, CV_8UC1), out_mat_gapi2(sz, CV_8UC1);
+ cv::Mat out_mat_ocv1(sz, CV_8UC1), out_mat_ocv2(sz, CV_8UC1);
+
+ // Run G-API
+ auto cc = comp.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
+ cc(cv::gin(in_mat), cv::gout(out_mat_gapi1, out_mat_gapi2));
+
+ // Check with OpenCV
+ out_mat_ocv1 = in_mat + 1 + 2;
+ out_mat_ocv2 = in_mat + 1 + 7;
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi1 != out_mat_ocv1));
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi2 != out_mat_ocv2));
+}
+
+TEST(Fluid, EmptyOutputMatTest)
+{
+ cv::GMat in;
+ cv::GMat out = TAddCSimple::on(in, 2);
+ cv::GComputation c(in, out);
+
+ cv::Mat in_mat = cv::Mat::eye(cv::Size(32, 24), CV_8UC1);
+ cv::Mat out_mat;
+
+ auto cc = c.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
+
+ cc(in_mat, out_mat);
+ EXPECT_EQ(CV_8UC1, out_mat.type());
+ EXPECT_EQ(32, out_mat.cols);
+ EXPECT_EQ(24, out_mat.rows);
+ EXPECT_TRUE(out_mat.ptr() != nullptr);
+}
+
+struct LPISequenceTest : public TestWithParam<int>{};
+TEST_P(LPISequenceTest, LPISequenceTest)
+{
+ // in -> AddC -> a -> Blur (2lpi) -> out
+
+ int kernelSize = GetParam();
+ cv::GMat in;
+ cv::GMat a = TAddCSimple::on(in, 1);
+ auto blur = kernelSize == 3 ? &TBlur3x3_2lpi::on : &TBlur5x5_2lpi::on;
+ cv::GMat out = blur(a, cv::BORDER_CONSTANT, cv::Scalar(0));
+ cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+
+ const auto sz = cv::Size(8, 10);
+ cv::Mat in_mat = cv::Mat::eye(sz, CV_8UC1);
+ cv::Mat out_mat_gapi(sz, CV_8UC1);
+ cv::Mat out_mat_ocv(sz, CV_8UC1);
+
+ // Run G-API
+ auto cc = comp.compile(cv::descr_of(in_mat), cv::compile_args(fluidTestPackage));
+ cc(cv::gin(in_mat), cv::gout(out_mat_gapi));
+
+ // Check with OpenCV
+ cv::blur(in_mat + 1, out_mat_ocv, {kernelSize,kernelSize}, {-1,-1}, cv::BORDER_CONSTANT);
+ EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
+}
+
+INSTANTIATE_TEST_CASE_P(Fluid, LPISequenceTest,
+ Values(3, 5));
+
+struct InputImageBorderTest : public TestWithParam <std::tuple<int, int>> {};
+TEST_P(InputImageBorderTest, InputImageBorderTest)
+{
+ cv::Size sz_in = { 320, 240 };
+
+ int ks = 0;
+ int borderType = 0;
+ std::tie(ks, borderType) = GetParam();
+ cv::Mat in_mat1(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+
+ cv::Size kernelSize = {ks, ks};
+ cv::Point anchor = {-1, -1};
+ cv::Scalar borderValue(0);
+
+ auto gblur = ks == 3 ? &TBlur3x3::on : &TBlur5x5::on;
+
+ GMat in;
+ auto out = gblur(in, borderType, borderValue);
+
+ Mat out_mat_gapi = Mat::zeros(sz_in, CV_8UC1);
+
+ GComputation c(GIn(in), GOut(out));
+ auto cc = c.compile(descr_of(in_mat1), cv::compile_args(fluidTestPackage));
+ cc(gin(in_mat1), gout(out_mat_gapi));
+
+ cv::Mat out_mat_ocv = Mat::zeros(sz_in, CV_8UC1);
+ cv::blur(in_mat1, out_mat_ocv, kernelSize, anchor, borderType);
+
+ EXPECT_EQ(0, countNonZero(out_mat_ocv != out_mat_gapi));
+}
+
+INSTANTIATE_TEST_CASE_P(Fluid, InputImageBorderTest,
+ Combine(Values(3, 5),
+ Values(BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT_101)));
+
+struct SequenceOfBlursTest : public TestWithParam <std::tuple<int>> {};
+TEST_P(SequenceOfBlursTest, Test)
+{
+ cv::Size sz_in = { 320, 240 };
+
+ int borderType = 0;;
+ std::tie(borderType) = GetParam();
+ cv::Mat in_mat(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Point anchor = {-1, -1};
+ cv::Scalar borderValue(0);
+
+ GMat in;
+ auto mid = TBlur3x3::on(in, borderType, borderValue);
+ auto out = TBlur5x5::on(mid, borderType, borderValue);
+
+ Mat out_mat_gapi = Mat::zeros(sz_in, CV_8UC1);
+
+ GComputation c(GIn(in), GOut(out));
+ auto cc = c.compile(descr_of(in_mat), cv::compile_args(fluidTestPackage));
+ cc(gin(in_mat), gout(out_mat_gapi));
+
+ cv::Mat mid_mat_ocv = Mat::zeros(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv = Mat::zeros(sz_in, CV_8UC1);
+ cv::blur(in_mat, mid_mat_ocv, {3,3}, anchor, borderType);
+ cv::blur(mid_mat_ocv, out_mat_ocv, {5,5}, anchor, borderType);
+
+ EXPECT_EQ(0, countNonZero(out_mat_ocv != out_mat_gapi));
+}
+
+INSTANTIATE_TEST_CASE_P(Fluid, SequenceOfBlursTest,
+ Values(BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT_101));
+
+struct TwoBlursTest : public TestWithParam <std::tuple<int, int, int, int, int, int, bool>> {};
+TEST_P(TwoBlursTest, Test)
+{
+ cv::Size sz_in = { 320, 240 };
+
+ int kernelSize1 = 0, kernelSize2 = 0;
+ int borderType1 = -1, borderType2 = -1;
+ cv::Scalar borderValue1{}, borderValue2{};
+ bool readFromInput = false;
+ std::tie(kernelSize1, borderType1, borderValue1, kernelSize2, borderType2, borderValue2, readFromInput) = GetParam();
+ cv::Mat in_mat(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Point anchor = {-1, -1};
+
+ auto blur1 = kernelSize1 == 3 ? &TBlur3x3::on : TBlur5x5::on;
+ auto blur2 = kernelSize2 == 3 ? &TBlur3x3::on : TBlur5x5::on;
+
+ GMat in, out1, out2;
+ if (readFromInput)
+ {
+ out1 = blur1(in, borderType1, borderValue1);
+ out2 = blur2(in, borderType2, borderValue2);
+ }
+ else
+ {
+ auto mid = TAddCSimple::on(in, 0);
+ out1 = blur1(mid, borderType1, borderValue1);
+ out2 = blur2(mid, borderType2, borderValue2);
+ }
+
+ Mat out_mat_gapi1 = Mat::zeros(sz_in, CV_8UC1);
+ Mat out_mat_gapi2 = Mat::zeros(sz_in, CV_8UC1);
+
+ GComputation c(GIn(in), GOut(out1, out2));
+ auto cc = c.compile(descr_of(in_mat), cv::compile_args(fluidTestPackage));
+ cc(gin(in_mat), gout(out_mat_gapi1, out_mat_gapi2));
+
+ cv::Mat out_mat_ocv1 = Mat::zeros(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv2 = Mat::zeros(sz_in, CV_8UC1);
+ cv::blur(in_mat, out_mat_ocv1, {kernelSize1, kernelSize1}, anchor, borderType1);
+ cv::blur(in_mat, out_mat_ocv2, {kernelSize2, kernelSize2}, anchor, borderType2);
+
+ EXPECT_EQ(0, countNonZero(out_mat_ocv1 != out_mat_gapi1));
+ EXPECT_EQ(0, countNonZero(out_mat_ocv2 != out_mat_gapi2));
+}
+
+INSTANTIATE_TEST_CASE_P(Fluid, TwoBlursTest,
+ Combine(Values(3, 5),
+ Values(cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, cv::BORDER_REFLECT_101),
+ Values(0),
+ Values(3, 5),
+ Values(cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, cv::BORDER_REFLECT_101),
+ Values(0),
+ testing::Bool())); // Read from input directly or place a copy node at start
+
+struct TwoReadersTest : public TestWithParam <std::tuple<int, int, int, bool>> {};
+TEST_P(TwoReadersTest, Test)
+{
+ cv::Size sz_in = { 320, 240 };
+
+ int kernelSize = 0;
+ int borderType = -1;
+ cv::Scalar borderValue;
+ bool readFromInput = false;
+ std::tie(kernelSize, borderType, borderValue, readFromInput) = GetParam();
+ cv::Mat in_mat(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Point anchor = {-1, -1};
+
+ auto blur = kernelSize == 3 ? &TBlur3x3::on : TBlur5x5::on;
+
+ GMat in, out1, out2;
+ if (readFromInput)
+ {
+ out1 = TAddCSimple::on(in, 0);
+ out2 = blur(in, borderType, borderValue);
+ }
+ else
+ {
+ auto mid = TAddCSimple::on(in, 0);
+ out1 = TAddCSimple::on(mid, 0);
+ out2 = blur(mid, borderType, borderValue);
+ }
+
+ Mat out_mat_gapi1 = Mat::zeros(sz_in, CV_8UC1);
+ Mat out_mat_gapi2 = Mat::zeros(sz_in, CV_8UC1);
+
+ GComputation c(GIn(in), GOut(out1, out2));
+ auto cc = c.compile(descr_of(in_mat), cv::compile_args(fluidTestPackage));
+ cc(gin(in_mat), gout(out_mat_gapi1, out_mat_gapi2));
+
+ cv::Mat out_mat_ocv1 = Mat::zeros(sz_in, CV_8UC1);
+ cv::Mat out_mat_ocv2 = Mat::zeros(sz_in, CV_8UC1);
+ out_mat_ocv1 = in_mat;
+ cv::blur(in_mat, out_mat_ocv2, {kernelSize, kernelSize}, anchor, borderType);
+
+ EXPECT_EQ(0, countNonZero(out_mat_ocv1 != out_mat_gapi1));
+ EXPECT_EQ(0, countNonZero(out_mat_ocv2 != out_mat_gapi2));
+}
+
+INSTANTIATE_TEST_CASE_P(Fluid, TwoReadersTest,
+ Combine(Values(3, 5),
+ Values(cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, cv::BORDER_REFLECT_101),
+ Values(0),
+ testing::Bool())); // Read from input directly or place a copy node at start
+
+TEST(FluidTwoIslands, SanityTest)
+{
+ cv::Size sz_in{8,8};
+
+ GMat in1, in2;
+ auto out1 = TAddScalar::on(in1, {0});
+ auto out2 = TAddScalar::on(in2, {0});
+
+ cv::Mat in_mat1(sz_in, CV_8UC1);
+ cv::Mat in_mat2(sz_in, CV_8UC1);
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+
+ cv::randn(in_mat1, mean, stddev);
+ cv::randn(in_mat2, mean, stddev);
+
+ Mat out_mat1 = Mat::zeros(sz_in, CV_8UC1);
+ Mat out_mat2 = Mat::zeros(sz_in, CV_8UC1);
+
+ GComputation c(GIn(in1, in2), GOut(out1, out2));
+ EXPECT_NO_THROW(c.apply(gin(in_mat1, in_mat2), gout(out_mat1, out_mat2), cv::compile_args(fluidTestPackage)));
+ EXPECT_EQ(0, countNonZero(in_mat1 != out_mat1));
+ EXPECT_EQ(0, countNonZero(in_mat2 != out_mat2));
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test_kernels.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test_kernels.cpp
new file mode 100644
index 000000000..6bd06fe27
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test_kernels.cpp
@@ -0,0 +1,436 @@
+// 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) 2018 Intel Corporation
+
+#include "test_precomp.hpp"
+
+#include <iomanip>
+#include "gapi_fluid_test_kernels.hpp"
+#include <opencv2/gapi/core.hpp>
+
+namespace cv
+{
+namespace gapi_test_kernels
+{
+
+GAPI_FLUID_KERNEL(FAddSimple, TAddSimple, false)
+{
+ static const int Window = 1;
+
+ static void run(const cv::gapi::fluid::View &a,
+ const cv::gapi::fluid::View &b,
+ cv::gapi::fluid::Buffer &o)
+ {
+ // std::cout << "AddSimple {{{\n";
+ // std::cout << " a - "; a.debug(std::cout);
+ // std::cout << " b - "; b.debug(std::cout);
+ // std::cout << " o - "; o.debug(std::cout);
+
+ const uint8_t* in1 = a.InLine<uint8_t>(0);
+ const uint8_t* in2 = b.InLine<uint8_t>(0);
+ uint8_t* out = o.OutLine<uint8_t>();
+
+ // std::cout << "a: ";
+ // for (int i = 0, w = a.length(); i < w; i++)
+ // {
+ // std::cout << std::setw(4) << int(in1[i]);
+ // }
+ // std::cout << "\n";
+
+ // std::cout << "b: ";
+ // for (int i = 0, w = a.length(); i < w; i++)
+ // {
+ // std::cout << std::setw(4) << int(in2[i]);
+ // }
+ // std::cout << "\n";
+
+ for (int i = 0, w = a.length(); i < w; i++)
+ {
+ out[i] = in1[i] + in2[i];
+ }
+
+ // std::cout << "}}} " << std::endl;;
+ }
+};
+
+GAPI_FLUID_KERNEL(FAddCSimple, TAddCSimple, false)
+{
+ static const int Window = 1;
+ static const int LPI = 2;
+
+ static void run(const cv::gapi::fluid::View &in,
+ const int cval,
+ cv::gapi::fluid::Buffer &out)
+ {
+ for (int l = 0, lpi = out.lpi(); l < lpi; l++)
+ {
+ const uint8_t* in_row = in .InLine <uint8_t>(l);
+ uint8_t* out_row = out.OutLine<uint8_t>(l);
+ //std::cout << "l=" << l << ": ";
+ for (int i = 0, w = in.length(); i < w; i++)
+ {
+ //std::cout << std::setw(4) << int(in_row[i]);
+ out_row[i] = static_cast<uint8_t>(in_row[i] + cval);
+ }
+ //std::cout << std::endl;
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(FAddScalar, TAddScalar, false)
+{
+ static const int Window = 1;
+ static const int LPI = 2;
+
+ static void run(const cv::gapi::fluid::View &in,
+ const cv::Scalar &cval,
+ cv::gapi::fluid::Buffer &out)
+ {
+ for (int l = 0, lpi = out.lpi(); l < lpi; l++)
+ {
+ const uint8_t* in_row = in .InLine <uint8_t>(l);
+ uint8_t* out_row = out.OutLine<uint8_t>(l);
+ std::cout << "l=" << l << ": ";
+ for (int i = 0, w = in.length(); i < w; i++)
+ {
+ std::cout << std::setw(4) << int(in_row[i]);
+ out_row[i] = static_cast<uint8_t>(in_row[i] + cval[0]);
+ }
+ std::cout << std::endl;
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(FAddScalarToMat, TAddScalarToMat, false)
+{
+ static const int Window = 1;
+ static const int LPI = 2;
+
+ static void run(const cv::Scalar &cval,
+ const cv::gapi::fluid::View &in,
+ cv::gapi::fluid::Buffer &out)
+ {
+ for (int l = 0, lpi = out.lpi(); l < lpi; l++)
+ {
+ const uint8_t* in_row = in .InLine <uint8_t>(l);
+ uint8_t* out_row = out.OutLine<uint8_t>(l);
+ std::cout << "l=" << l << ": ";
+ for (int i = 0, w = in.length(); i < w; i++)
+ {
+ std::cout << std::setw(4) << int(in_row[i]);
+ out_row[i] = static_cast<uint8_t>(in_row[i] + cval[0]);
+ }
+ std::cout << std::endl;
+ }
+ }
+};
+
+template<int kernelSize, int lpi = 1>
+static void runBlur(const cv::gapi::fluid::View& src, cv::gapi::fluid::Buffer& dst)
+{
+ const auto borderSize = (kernelSize - 1) / 2;
+ const unsigned char* ins[kernelSize];
+
+ for (int l = 0; l < lpi; l++)
+ {
+ for (int i = 0; i < kernelSize; i++)
+ {
+ ins[i] = src.InLine<unsigned char>(i - borderSize + l);
+ }
+
+ auto out = dst.OutLine<unsigned char>(l);
+ const auto width = dst.length();
+
+ for (int w = 0; w < width; w++)
+ {
+ float res = 0.0f;
+ for (int i = 0; i < kernelSize; i++)
+ {
+ for (int j = -borderSize; j < borderSize + 1; j++)
+ {
+ res += ins[i][w+j];
+ }
+ }
+ out[w] = static_cast<unsigned char>(std::rint(res / (kernelSize * kernelSize)));
+ }
+ }
+}
+
+GAPI_FLUID_KERNEL(FBlur1x1, TBlur1x1, false)
+{
+ static const int Window = 1;
+
+ static void run(const cv::gapi::fluid::View &src, int /*borderType*/,
+ cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst)
+ {
+ runBlur<Window>(src, dst);
+ }
+};
+
+GAPI_FLUID_KERNEL(FBlur3x3, TBlur3x3, false)
+{
+ static const int Window = 3;
+
+ static void run(const cv::gapi::fluid::View &src, int /*borderType*/,
+ cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst)
+ {
+ runBlur<Window>(src, dst);
+ }
+
+ static cv::gapi::fluid::Border getBorder(const cv::GMatDesc &/*src*/, int borderType, cv::Scalar borderValue)
+ {
+ return { borderType, to_own(borderValue)};
+ }
+};
+
+GAPI_FLUID_KERNEL(FBlur5x5, TBlur5x5, false)
+{
+ static const int Window = 5;
+
+ static void run(const cv::gapi::fluid::View &src, int /*borderType*/,
+ cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst)
+ {
+ runBlur<Window>(src, dst);
+ }
+
+ static cv::gapi::fluid::Border getBorder(const cv::GMatDesc &/*src*/, int borderType, cv::Scalar borderValue)
+ {
+ return { borderType, to_own(borderValue)};
+ }
+};
+
+GAPI_FLUID_KERNEL(FBlur3x3_2lpi, TBlur3x3_2lpi, false)
+{
+ static const int Window = 3;
+ static const int LPI = 2;
+
+ static void run(const cv::gapi::fluid::View &src, int /*borderType*/,
+ cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst)
+ {
+ runBlur<Window, LPI>(src, dst);
+ }
+
+ static cv::gapi::fluid::Border getBorder(const cv::GMatDesc &/*src*/, int borderType, cv::Scalar borderValue)
+ {
+ return { borderType, to_own(borderValue)};
+ }
+};
+
+GAPI_FLUID_KERNEL(FBlur5x5_2lpi, TBlur5x5_2lpi, false)
+{
+ static const int Window = 5;
+ static const int LPI = 2;
+
+ static void run(const cv::gapi::fluid::View &src, int /*borderType*/,
+ cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst)
+ {
+ runBlur<Window, LPI>(src, dst);
+ }
+
+ static cv::gapi::fluid::Border getBorder(const cv::GMatDesc &/*src*/, int borderType, cv::Scalar borderValue)
+ {
+ return { borderType, to_own(borderValue )};
+ }
+};
+
+GAPI_FLUID_KERNEL(FIdentity, TId, false)
+{
+ static const int Window = 3;
+
+ static void run(const cv::gapi::fluid::View &a,
+ cv::gapi::fluid::Buffer &o)
+ {
+ const uint8_t* in[3] = {
+ a.InLine<uint8_t>(-1),
+ a.InLine<uint8_t>( 0),
+ a.InLine<uint8_t>(+1)
+ };
+ uint8_t* out = o.OutLine<uint8_t>();
+
+ // ReadFunction3x3(in, a.length());
+ for (int i = 0, w = a.length(); i < w; i++)
+ {
+ out[i] = in[1][i];
+ }
+ }
+
+ static gapi::fluid::Border getBorder(const cv::GMatDesc &)
+ {
+ return { cv::BORDER_REPLICATE, cv::gapi::own::Scalar{} };
+ }
+};
+
+GAPI_FLUID_KERNEL(FId7x7, TId7x7, false)
+{
+ static const int Window = 7;
+ static const int LPI = 2;
+
+ static void run(const cv::gapi::fluid::View &a,
+ cv::gapi::fluid::Buffer &o)
+ {
+ for (int l = 0, lpi = o.lpi(); l < lpi; l++)
+ {
+ const uint8_t* in[Window] = {
+ a.InLine<uint8_t>(-3 + l),
+ a.InLine<uint8_t>(-2 + l),
+ a.InLine<uint8_t>(-1 + l),
+ a.InLine<uint8_t>( 0 + l),
+ a.InLine<uint8_t>(+1 + l),
+ a.InLine<uint8_t>(+2 + l),
+ a.InLine<uint8_t>(+3 + l),
+ };
+ uint8_t* out = o.OutLine<uint8_t>(l);
+
+ // std::cout << "Id7x7 " << l << " of " << lpi << " {{{\n";
+ // std::cout << " a - "; a.debug(std::cout);
+ // std::cout << " o - "; o.debug(std::cout);
+ // std::cout << "}}} " << std::endl;;
+
+ // // std::cout << "Id7x7 at " << a.y() << "/L" << l << " {{{" << std::endl;
+ // for (int j = 0; j < Window; j++)
+ // {
+ // // std::cout << std::setw(2) << j-(Window-1)/2 << ": ";
+ // for (int i = 0, w = a.length(); i < w; i++)
+ // std::cout << std::setw(4) << int(in[j][i]);
+ // std::cout << std::endl;
+ // }
+ // std::cout << "}}}" << std::endl;
+
+ for (int i = 0, w = a.length(); i < w; i++)
+ out[i] = in[(Window-1)/2][i];
+ }
+ }
+
+ static cv::gapi::fluid::Border getBorder(const cv::GMatDesc&/* src*/)
+ {
+ return { cv::BORDER_REPLICATE, cv::gapi::own::Scalar{} };
+ }
+};
+
+GAPI_FLUID_KERNEL(FPlusRow0, TPlusRow0, true)
+{
+ static const int Window = 1;
+
+ static void initScratch(const cv::GMatDesc &in,
+ cv::gapi::fluid::Buffer &scratch)
+ {
+ cv::Size scratch_size{in.size.width, 1};
+ cv::gapi::fluid::Buffer buffer(in.withSize(scratch_size));
+ scratch = std::move(buffer);
+ }
+
+ static void resetScratch(cv::gapi::fluid::Buffer &scratch)
+ {
+ // FIXME: only 1 line can be used!
+ uint8_t* out_row = scratch.OutLine<uint8_t>();
+ for (int i = 0, w = scratch.length(); i < w; i++)
+ {
+ out_row[i] = 0;
+ }
+ }
+
+ static void run(const cv::gapi::fluid::View &in,
+ cv::gapi::fluid::Buffer &out,
+ cv::gapi::fluid::Buffer &scratch)
+ {
+ const uint8_t* in_row = in .InLine <uint8_t>(0);
+ uint8_t* out_row = out .OutLine<uint8_t>();
+ uint8_t* tmp_row = scratch.OutLine<uint8_t>();
+
+ if (in.y() == 0)
+ {
+ // Copy 1st row to scratch buffer
+ for (int i = 0, w = in.length(); i < w; i++)
+ {
+ out_row[i] = in_row[i];
+ tmp_row[i] = in_row[i];
+ }
+ }
+ else
+ {
+ // Output is 1st row + in
+ for (int i = 0, w = in.length(); i < w; i++)
+ {
+ out_row[i] = in_row[i] + tmp_row[i];
+ }
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(FTestSplit3, cv::gapi::core::GSplit3, false)
+{
+ static const int Window = 1;
+
+ static void run(const cv::gapi::fluid::View &in,
+ cv::gapi::fluid::Buffer &o1,
+ cv::gapi::fluid::Buffer &o2,
+ cv::gapi::fluid::Buffer &o3)
+ {
+ // std::cout << "Split3 {{{\n";
+ // std::cout << " a - "; in.debug(std::cout);
+ // std::cout << " 1 - "; o1.debug(std::cout);
+ // std::cout << " 2 - "; o2.debug(std::cout);
+ // std::cout << " 3 - "; o3.debug(std::cout);
+ // std::cout << "}}} " << std::endl;;
+
+ const uint8_t* in_rgb = in.InLine<uint8_t>(0);
+ uint8_t* out_r = o1.OutLine<uint8_t>();
+ uint8_t* out_g = o2.OutLine<uint8_t>();
+ uint8_t* out_b = o3.OutLine<uint8_t>();
+
+ for (int i = 0, w = in.length(); i < w; i++)
+ {
+ out_r[i] = in_rgb[3*i];
+ out_g[i] = in_rgb[3*i+1];
+ out_b[i] = in_rgb[3*i+2];
+ }
+ }
+};
+
+GAPI_FLUID_KERNEL(FSum2MatsAndScalar, TSum2MatsAndScalar, false)
+{
+ static const int Window = 1;
+ static const int LPI = 2;
+
+ static void run(const cv::gapi::fluid::View &a,
+ const cv::Scalar &cval,
+ const cv::gapi::fluid::View &b,
+ cv::gapi::fluid::Buffer &out)
+ {
+ for (int l = 0, lpi = out.lpi(); l < lpi; l++)
+ {
+ const uint8_t* in_row1 = a .InLine <uint8_t>(l);
+ const uint8_t* in_row2 = b .InLine <uint8_t>(l);
+ uint8_t* out_row = out.OutLine<uint8_t>(l);
+ std::cout << "l=" << l << ": ";
+ for (int i = 0, w = a.length(); i < w; i++)
+ {
+ std::cout << std::setw(4) << int(in_row1[i]);
+ std::cout << std::setw(4) << int(in_row2[i]);
+ out_row[i] = static_cast<uint8_t>(in_row1[i] + in_row2[i] + cval[0]);
+ }
+ std::cout << std::endl;
+ }
+ }
+};
+
+cv::gapi::GKernelPackage fluidTestPackage = cv::gapi::kernels
+ <FAddSimple
+ ,FAddCSimple
+ ,FAddScalar
+ ,FAddScalarToMat
+ ,FBlur1x1
+ ,FBlur3x3
+ ,FBlur5x5
+ ,FBlur3x3_2lpi
+ ,FBlur5x5_2lpi
+ ,FIdentity
+ ,FId7x7
+ ,FPlusRow0
+ ,FSum2MatsAndScalar
+ ,FTestSplit3
+ >();
+} // namespace gapi_test_kernels
+} // namespace cv
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test_kernels.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test_kernels.hpp
new file mode 100644
index 000000000..f5d83edf5
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_fluid_test_kernels.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) 2018 Intel Corporation
+
+
+#ifndef GAPI_FLUID_TEST_KERNELS_HPP
+#define GAPI_FLUID_TEST_KERNELS_HPP
+
+#include "opencv2/gapi/fluid/gfluidkernel.hpp"
+
+namespace cv
+{
+namespace gapi_test_kernels
+{
+
+G_TYPED_KERNEL(TAddSimple, <GMat(GMat, GMat)>, "test.fluid.add_simple") {
+ static cv::GMatDesc outMeta(cv::GMatDesc a, cv::GMatDesc) {
+ return a;
+ }
+};
+
+G_TYPED_KERNEL(TAddCSimple, <GMat(GMat,int)>, "test.fluid.addc_simple")
+{
+ static GMatDesc outMeta(const cv::GMatDesc &in, int) {
+ return in;
+ }
+};
+
+G_TYPED_KERNEL(TAddScalar, <GMat(GMat,GScalar)>, "test.fluid.addc_scalar")
+{
+ static GMatDesc outMeta(const cv::GMatDesc &in, const cv::GScalarDesc&) {
+ return in;
+ }
+};
+
+G_TYPED_KERNEL(TAddScalarToMat, <GMat(GScalar,GMat)>, "test.fluid.add_scalar_to_mat")
+{
+ static GMatDesc outMeta(const cv::GScalarDesc&, const cv::GMatDesc &in) {
+ return in;
+ }
+};
+
+G_TYPED_KERNEL(TBlur1x1, <GMat(GMat,int,Scalar)>, "org.opencv.imgproc.filters.blur1x1"){
+ static GMatDesc outMeta(GMatDesc in, int, Scalar) {
+ return in;
+ }
+};
+
+G_TYPED_KERNEL(TBlur3x3, <GMat(GMat,int,Scalar)>, "org.opencv.imgproc.filters.blur3x3"){
+ static GMatDesc outMeta(GMatDesc in, int, Scalar) {
+ return in;
+ }
+};
+
+G_TYPED_KERNEL(TBlur5x5, <GMat(GMat,int,Scalar)>, "org.opencv.imgproc.filters.blur5x5"){
+ static GMatDesc outMeta(GMatDesc in, int, Scalar) {
+ return in;
+ }
+};
+
+G_TYPED_KERNEL(TBlur3x3_2lpi, <GMat(GMat,int,Scalar)>, "org.opencv.imgproc.filters.blur3x3_2lpi"){
+ static GMatDesc outMeta(GMatDesc in, int, Scalar) {
+ return in;
+ }
+};
+
+G_TYPED_KERNEL(TBlur5x5_2lpi, <GMat(GMat,int,Scalar)>, "org.opencv.imgproc.filters.blur5x5_2lpi"){
+ static GMatDesc outMeta(GMatDesc in, int, Scalar) {
+ return in;
+ }
+};
+
+G_TYPED_KERNEL(TId, <GMat(GMat)>, "test.fluid.identity") {
+ static cv::GMatDesc outMeta(cv::GMatDesc a) {
+ return a;
+ }
+};
+
+G_TYPED_KERNEL(TId7x7, <GMat(GMat)>, "test.fluid.identity7x7") {
+ static cv::GMatDesc outMeta(cv::GMatDesc a) {
+ return a;
+ }
+};
+
+G_TYPED_KERNEL(TPlusRow0, <GMat(GMat)>, "test.fluid.plus_row0") {
+ static cv::GMatDesc outMeta(cv::GMatDesc a) {
+ return a;
+ }
+};
+
+G_TYPED_KERNEL(TSum2MatsAndScalar, <GMat(GMat,GScalar,GMat)>, "test.fluid.sum_2_mats_and_scalar")
+{
+ static GMatDesc outMeta(const cv::GMatDesc &in, const cv::GScalarDesc&, const cv::GMatDesc&) {
+ return in;
+ }
+};
+
+extern cv::gapi::GKernelPackage fluidTestPackage;
+
+} // namespace gapi_test_kernels
+} // namespace cv
+
+#endif // GAPI_FLUID_TEST_KERNELS_HPP
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_gcompiled_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_gcompiled_tests.cpp
new file mode 100644
index 000000000..e482e2e36
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_gcompiled_tests.cpp
@@ -0,0 +1,173 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+namespace opencv_test
+{
+
+namespace
+{
+ static cv::GMat DemoCC(cv::GMat in, cv::GScalar scale)
+ {
+ return cv::gapi::medianBlur(in + in*scale, 3);
+ }
+
+ struct GCompiledValidateMetaTyped: public ::testing::Test
+ {
+ cv::GComputationT<cv::GMat(cv::GMat,cv::GScalar)> m_cc;
+
+ GCompiledValidateMetaTyped() : m_cc(DemoCC)
+ {
+ }
+ };
+
+ struct GCompiledValidateMetaUntyped: public ::testing::Test
+ {
+ cv::GMat in;
+ cv::GScalar scale;
+ cv::GComputation m_ucc;
+
+ GCompiledValidateMetaUntyped() : m_ucc(cv::GIn(in, scale),
+ cv::GOut(DemoCC(in, scale)))
+ {
+ }
+ };
+} // anonymous namespace
+
+TEST_F(GCompiledValidateMetaTyped, ValidMeta)
+{
+ cv::Mat in = cv::Mat::eye(cv::Size(128, 32), CV_8UC1);
+ cv::Scalar sc(127);
+
+ auto f = m_cc.compile(cv::descr_of(in),
+ cv::descr_of(sc));
+
+ // Correct operation when meta is exactly the same
+ cv::Mat out;
+ EXPECT_NO_THROW(f(in, sc, out));
+
+ // Correct operation on next invocation with same meta
+ // taken from different input objects
+ cv::Mat in2 = cv::Mat::zeros(cv::Size(128, 32), CV_8UC1);
+ cv::Scalar sc2(64);
+ cv::Mat out2;
+ EXPECT_NO_THROW(f(in2, sc2, out2));
+}
+
+TEST_F(GCompiledValidateMetaTyped, InvalidMeta)
+{
+ auto f = m_cc.compile(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(64,32)},
+ cv::empty_scalar_desc());
+
+ cv::Scalar sc(33);
+ cv::Mat out;
+
+ // 3 channels intead 1
+ cv::Mat in1 = cv::Mat::eye(cv::Size(64,32), CV_8UC3);
+ EXPECT_THROW(f(in1, sc, out), std::logic_error);
+
+ // 32f intead 8u
+ cv::Mat in2 = cv::Mat::eye(cv::Size(64,32), CV_32F);
+ EXPECT_THROW(f(in2, sc, out), std::logic_error);
+
+ // 32x32 instead of 64x32
+ cv::Mat in3 = cv::Mat::eye(cv::Size(32,32), CV_8UC1);
+ EXPECT_THROW(f(in3, sc, out), std::logic_error);
+
+ // All is wrong
+ cv::Mat in4 = cv::Mat::eye(cv::Size(128,64), CV_32FC3);
+ EXPECT_THROW(f(in4, sc, out), std::logic_error);
+}
+
+TEST_F(GCompiledValidateMetaUntyped, ValidMeta)
+{
+ cv::Mat in1 = cv::Mat::eye(cv::Size(128, 32), CV_8UC1);
+ cv::Scalar sc(127);
+
+ auto f = m_ucc.compile(cv::descr_of(in1),
+ cv::descr_of(sc));
+
+ // Correct operation when meta is exactly the same
+ cv::Mat out1;
+ EXPECT_NO_THROW(f(cv::gin(in1, sc), cv::gout(out1)));
+
+ // Correct operation on next invocation with same meta
+ // taken from different input objects
+ cv::Mat in2 = cv::Mat::zeros(cv::Size(128, 32), CV_8UC1);
+ cv::Scalar sc2(64);
+ cv::Mat out2;
+ EXPECT_NO_THROW(f(cv::gin(in2, sc2), cv::gout(out2)));
+}
+
+TEST_F(GCompiledValidateMetaUntyped, InvalidMetaValues)
+{
+ auto f = m_ucc.compile(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(64,32)},
+ cv::empty_scalar_desc());
+
+ cv::Scalar sc(33);
+ cv::Mat out;
+
+ // 3 channels intead 1
+ cv::Mat in1 = cv::Mat::eye(cv::Size(64,32), CV_8UC3);
+ EXPECT_THROW(f(cv::gin(in1, sc), cv::gout(out)), std::logic_error);
+
+ // 32f intead 8u
+ cv::Mat in2 = cv::Mat::eye(cv::Size(64,32), CV_32F);
+ EXPECT_THROW(f(cv::gin(in2, sc), cv::gout(out)), std::logic_error);
+
+ // 32x32 instead of 64x32
+ cv::Mat in3 = cv::Mat::eye(cv::Size(32,32), CV_8UC1);
+ EXPECT_THROW(f(cv::gin(in3, sc), cv::gout(out)), std::logic_error);
+
+ // All is wrong
+ cv::Mat in4 = cv::Mat::eye(cv::Size(128,64), CV_32FC3);
+ EXPECT_THROW(f(cv::gin(in4, sc), cv::gout(out)), std::logic_error);
+}
+
+TEST_F(GCompiledValidateMetaUntyped, InvalidMetaShape)
+{
+ auto f = m_ucc.compile(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(64,32)},
+ cv::empty_scalar_desc());
+
+ cv::Mat in1 = cv::Mat::eye(cv::Size(64,32), CV_8UC1);
+ cv::Scalar sc(33);
+ cv::Mat out1;
+
+ // call as f(Mat,Mat) while f(Mat,Scalar) is expected
+ EXPECT_THROW(f(cv::gin(in1, in1), cv::gout(out1)), std::logic_error);
+
+ // call as f(Scalar,Mat) while f(Mat,Scalar) is expected
+ EXPECT_THROW(f(cv::gin(sc, in1), cv::gout(out1)), std::logic_error);
+
+ // call as f(Scalar,Scalar) while f(Mat,Scalar) is expected
+ EXPECT_THROW(f(cv::gin(sc, sc), cv::gout(out1)), std::logic_error);
+}
+
+TEST_F(GCompiledValidateMetaUntyped, InvalidMetaNumber)
+{
+ auto f = m_ucc.compile(cv::GMatDesc{CV_8U,1,cv::Size(64,32)},
+ cv::empty_scalar_desc());
+
+ cv::Mat in1 = cv::Mat::eye(cv::Size(64,32), CV_8UC1);
+ cv::Scalar sc(33);
+ cv::Mat out1, out2;
+
+ // call as f(Mat,Scalar,Scalar) while f(Mat,Scalar) is expected
+ EXPECT_THROW(f(cv::gin(in1, sc, sc), cv::gout(out1)), std::logic_error);
+
+ // call as f(Scalar,Mat,Scalar) while f(Mat,Scalar) is expected
+ EXPECT_THROW(f(cv::gin(sc, in1, sc), cv::gout(out1)), std::logic_error);
+
+ // call as f(Scalar) while f(Mat,Scalar) is expected
+ EXPECT_THROW(f(cv::gin(sc), cv::gout(out1)), std::logic_error);
+
+ // call as f(Mat,Scalar,[out1],[out2]) while f(Mat,Scalar,[out]) is expected
+ EXPECT_THROW(f(cv::gin(in1, sc), cv::gout(out1, out2)), std::logic_error);
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_gcomputation_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_gcomputation_tests.cpp
new file mode 100644
index 000000000..070cea692
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_gcomputation_tests.cpp
@@ -0,0 +1,68 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+
+namespace opencv_test
+{
+
+ namespace
+ {
+ G_TYPED_KERNEL(CustomResize, <cv::GMat(cv::GMat, cv::Size, double, double, int)>, "org.opencv.customk.resize")
+ {
+ static cv::GMatDesc outMeta(cv::GMatDesc in, cv::Size sz, double fx, double fy, int) {
+ if (sz.width != 0 && sz.height != 0)
+ {
+ return in.withSize(to_own(sz));
+ }
+ else
+ {
+ GAPI_Assert(fx != 0. && fy != 0.);
+ return in.withSize
+ (cv::gapi::own::Size(static_cast<int>(std::round(in.size.width * fx)),
+ static_cast<int>(std::round(in.size.height * fy))));
+ }
+ }
+ };
+
+ GAPI_OCV_KERNEL(CustomResizeImpl, CustomResize)
+ {
+ static void run(const cv::Mat& in, cv::Size sz, double fx, double fy, int interp, cv::Mat &out)
+ {
+ cv::resize(in, out, sz, fx, fy, interp);
+ }
+ };
+
+ struct GComputationApplyTest: public ::testing::Test
+ {
+ cv::GMat in;
+ cv::Mat in_mat;
+ cv::Mat out_mat;
+ cv::GComputation m_c;
+
+ GComputationApplyTest() : in_mat(300, 300, CV_8UC1),
+ m_c(cv::GIn(in), cv::GOut(CustomResize::on(in, cv::Size(100, 100),
+ 0.0, 0.0, cv::INTER_LINEAR)))
+ {
+ }
+ };
+ }
+
+ TEST_F(GComputationApplyTest, ThrowDontPassCustomKernel)
+ {
+ EXPECT_THROW(m_c.apply(in_mat, out_mat), std::logic_error);
+ }
+
+ TEST_F(GComputationApplyTest, NoThrowPassCustomKernel)
+ {
+ const auto pkg = cv::gapi::kernels<CustomResizeImpl>();
+
+ ASSERT_NO_THROW(m_c.apply(in_mat, out_mat, cv::compile_args(pkg)));
+ }
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_kernel_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_kernel_tests.cpp
new file mode 100644
index 000000000..aeb47628e
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_kernel_tests.cpp
@@ -0,0 +1,284 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+#include "gapi_mock_kernels.hpp"
+
+namespace opencv_test
+{
+
+namespace
+{
+ G_TYPED_KERNEL(GClone, <GMat(GMat)>, "org.opencv.test.clone")
+ {
+ static GMatDesc outMeta(GMatDesc in) { return in; }
+
+ };
+
+ GAPI_OCV_KERNEL(GCloneImpl, GClone)
+ {
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ out = in.clone();
+ }
+ };
+}
+
+TEST(KernelPackage, Create)
+{
+ namespace J = Jupiter;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
+ EXPECT_EQ(3u, pkg.size());
+}
+
+TEST(KernelPackage, Includes)
+{
+ namespace J = Jupiter;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
+ EXPECT_TRUE (pkg.includes<J::Foo>());
+ EXPECT_TRUE (pkg.includes<J::Bar>());
+ EXPECT_TRUE (pkg.includes<J::Baz>());
+ EXPECT_FALSE(pkg.includes<J::Qux>());
+}
+
+TEST(KernelPackage, IncludesAPI)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto pkg = cv::gapi::kernels<J::Foo, S::Bar>();
+ EXPECT_TRUE (pkg.includesAPI<I::Foo>());
+ EXPECT_TRUE (pkg.includesAPI<I::Bar>());
+ EXPECT_FALSE(pkg.includesAPI<I::Baz>());
+ EXPECT_FALSE(pkg.includesAPI<I::Qux>());
+}
+
+TEST(KernelPackage, IncludesAPI_Overlapping)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar, S::Foo, S::Bar>();
+ EXPECT_TRUE (pkg.includesAPI<I::Foo>());
+ EXPECT_TRUE (pkg.includesAPI<I::Bar>());
+ EXPECT_FALSE(pkg.includesAPI<I::Baz>());
+ EXPECT_FALSE(pkg.includesAPI<I::Qux>());
+}
+
+TEST(KernelPackage, Include_Add)
+{
+ namespace J = Jupiter;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
+ EXPECT_FALSE(pkg.includes<J::Qux>());
+
+ pkg.include<J::Qux>();
+ EXPECT_TRUE(pkg.includes<J::Qux>());
+}
+
+TEST(KernelPackage, Include_KEEP)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
+ EXPECT_FALSE(pkg.includes<S::Foo>());
+ EXPECT_FALSE(pkg.includes<S::Bar>());
+
+ pkg.include<S::Bar>(); // default (KEEP)
+ EXPECT_TRUE(pkg.includes<J::Bar>());
+ EXPECT_TRUE(pkg.includes<S::Bar>());
+
+ pkg.include<S::Foo>(cv::unite_policy::KEEP); // explicit (KEEP)
+ EXPECT_TRUE(pkg.includes<J::Foo>());
+ EXPECT_TRUE(pkg.includes<S::Foo>());
+}
+
+TEST(KernelPackage, Include_REPLACE)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
+ EXPECT_FALSE(pkg.includes<S::Bar>());
+
+ pkg.include<S::Bar>(cv::unite_policy::REPLACE);
+ EXPECT_FALSE(pkg.includes<J::Bar>());
+ EXPECT_TRUE(pkg.includes<S::Bar>());
+}
+
+TEST(KernelPackage, RemoveBackend)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar, S::Foo>();
+ EXPECT_TRUE(pkg.includes<J::Foo>());
+ EXPECT_TRUE(pkg.includes<J::Bar>());
+ EXPECT_TRUE(pkg.includes<S::Foo>());
+
+ pkg.remove(J::backend());
+ EXPECT_FALSE(pkg.includes<J::Foo>());
+ EXPECT_FALSE(pkg.includes<J::Bar>());
+ EXPECT_TRUE(pkg.includes<S::Foo>());
+};
+
+TEST(KernelPackage, RemoveAPI)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar, S::Foo, S::Bar>();
+ EXPECT_TRUE(pkg.includes<J::Foo>());
+ EXPECT_TRUE(pkg.includes<J::Bar>());
+ EXPECT_TRUE(pkg.includes<S::Foo>());
+
+ pkg.remove<I::Foo>();
+ EXPECT_TRUE(pkg.includes<J::Bar>());
+ EXPECT_TRUE(pkg.includes<S::Bar>());
+ EXPECT_FALSE(pkg.includes<J::Foo>());
+ EXPECT_FALSE(pkg.includes<S::Foo>());
+};
+
+TEST(KernelPackage, CreateHetero)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz, S::Qux>();
+ EXPECT_EQ(4u, pkg.size());
+}
+
+TEST(KernelPackage, IncludesHetero)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz, S::Qux>();
+ EXPECT_TRUE (pkg.includes<J::Foo>());
+ EXPECT_TRUE (pkg.includes<J::Bar>());
+ EXPECT_TRUE (pkg.includes<J::Baz>());
+ EXPECT_FALSE(pkg.includes<J::Qux>());
+ EXPECT_TRUE (pkg.includes<S::Qux>());
+}
+
+TEST(KernelPackage, IncludeHetero)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
+ EXPECT_FALSE(pkg.includes<J::Qux>());
+ EXPECT_FALSE(pkg.includes<S::Qux>());
+
+ pkg.include<S::Qux>();
+ EXPECT_FALSE(pkg.includes<J::Qux>());
+ EXPECT_TRUE (pkg.includes<S::Qux>());
+}
+
+TEST(KernelPackage, Combine_REPLACE_Full)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
+ auto s_pkg = cv::gapi::kernels<S::Foo, S::Bar, S::Baz>();
+ auto u_pkg = cv::gapi::combine(j_pkg, s_pkg, cv::unite_policy::REPLACE);
+
+ EXPECT_EQ(3u, u_pkg.size());
+ EXPECT_FALSE(u_pkg.includes<J::Foo>());
+ EXPECT_FALSE(u_pkg.includes<J::Bar>());
+ EXPECT_FALSE(u_pkg.includes<J::Baz>());
+ EXPECT_TRUE (u_pkg.includes<S::Foo>());
+ EXPECT_TRUE (u_pkg.includes<S::Bar>());
+ EXPECT_TRUE (u_pkg.includes<S::Baz>());
+}
+
+TEST(KernelPackage, Combine_REPLACE_Partial)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar>();
+ auto s_pkg = cv::gapi::kernels<S::Bar>();
+ auto u_pkg = cv::gapi::combine(j_pkg, s_pkg, cv::unite_policy::REPLACE);
+
+ EXPECT_EQ(2u, u_pkg.size());
+ EXPECT_TRUE (u_pkg.includes<J::Foo>());
+ EXPECT_FALSE(u_pkg.includes<J::Bar>());
+ EXPECT_TRUE (u_pkg.includes<S::Bar>());
+}
+
+TEST(KernelPackage, Combine_REPLACE_Append)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar>();
+ auto s_pkg = cv::gapi::kernels<S::Qux>();
+ auto u_pkg = cv::gapi::combine(j_pkg, s_pkg, cv::unite_policy::REPLACE);
+
+ EXPECT_EQ(3u, u_pkg.size());
+ EXPECT_TRUE(u_pkg.includes<J::Foo>());
+ EXPECT_TRUE(u_pkg.includes<J::Bar>());
+ EXPECT_TRUE(u_pkg.includes<S::Qux>());
+}
+
+TEST(KernelPackage, Combine_KEEP_AllDups)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
+ auto s_pkg = cv::gapi::kernels<S::Foo, S::Bar, S::Baz>();
+ auto u_pkg = cv::gapi::combine(j_pkg ,s_pkg, cv::unite_policy::KEEP);
+
+ EXPECT_EQ(6u, u_pkg.size());
+ EXPECT_TRUE(u_pkg.includes<J::Foo>());
+ EXPECT_TRUE(u_pkg.includes<J::Bar>());
+ EXPECT_TRUE(u_pkg.includes<J::Baz>());
+ EXPECT_TRUE(u_pkg.includes<S::Foo>());
+ EXPECT_TRUE(u_pkg.includes<S::Bar>());
+ EXPECT_TRUE(u_pkg.includes<S::Baz>());
+}
+
+TEST(KernelPackage, Combine_KEEP_Append_NoDups)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ auto j_pkg = cv::gapi::kernels<J::Foo, J::Bar>();
+ auto s_pkg = cv::gapi::kernels<S::Qux>();
+ auto u_pkg = cv::gapi::combine(j_pkg, s_pkg, cv::unite_policy::KEEP);
+
+ EXPECT_EQ(3u, u_pkg.size());
+ EXPECT_TRUE(u_pkg.includes<J::Foo>());
+ EXPECT_TRUE(u_pkg.includes<J::Bar>());
+ EXPECT_TRUE(u_pkg.includes<S::Qux>());
+}
+
+TEST(KernelPackage, TestWithEmptyLHS)
+{
+ namespace J = Jupiter;
+ auto lhs = cv::gapi::kernels<>();
+ auto rhs = cv::gapi::kernels<J::Foo>();
+ auto pkg = cv::gapi::combine(lhs, rhs, cv::unite_policy::KEEP);
+
+ EXPECT_EQ(1u, pkg.size());
+ EXPECT_TRUE(pkg.includes<J::Foo>());
+}
+
+TEST(KernelPackage, TestWithEmptyRHS)
+{
+ namespace J = Jupiter;
+ auto lhs = cv::gapi::kernels<J::Foo>();
+ auto rhs = cv::gapi::kernels<>();
+ auto pkg = cv::gapi::combine(lhs, rhs, cv::unite_policy::KEEP);
+
+ EXPECT_EQ(1u, pkg.size());
+ EXPECT_TRUE(pkg.includes<J::Foo>());
+}
+
+TEST(KernelPackage, Can_Use_Custom_Kernel)
+{
+ cv::GMat in[2];
+ auto out = GClone::on(cv::gapi::add(in[0], in[1]));
+ const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
+
+ auto pkg = cv::gapi::kernels<GCloneImpl>();
+
+ EXPECT_NO_THROW(cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out)).
+ compile({in_meta, in_meta}, cv::compile_args(pkg)));
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_mock_kernels.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_mock_kernels.hpp
new file mode 100644
index 000000000..cd876efdb
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_mock_kernels.hpp
@@ -0,0 +1,123 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+
+#include "api/gbackend_priv.hpp" // directly instantiate GBackend::Priv
+
+namespace opencv_test
+{
+namespace {
+ // FIXME: Currently every Kernel implementation in this test file has
+ // its own backend() method and it is incorrect! API classes should
+ // provide it out of the box.
+
+namespace I
+{
+ G_TYPED_KERNEL(Foo, <cv::GMat(cv::GMat)>, "test.kernels.foo")
+ {
+ static cv::GMatDesc outMeta(const cv::GMatDesc &in) { return in; }
+ };
+
+ G_TYPED_KERNEL(Bar, <cv::GMat(cv::GMat,cv::GMat)>, "test.kernels.bar")
+ {
+ static cv::GMatDesc outMeta(const cv::GMatDesc &in, const cv::GMatDesc &) { return in; }
+ };
+
+ G_TYPED_KERNEL(Baz, <cv::GScalar(cv::GMat)>, "test.kernels.baz")
+ {
+ static cv::GScalarDesc outMeta(const cv::GMatDesc &) { return cv::empty_scalar_desc(); }
+ };
+
+ G_TYPED_KERNEL(Qux, <cv::GMat(cv::GMat, cv::GScalar)>, "test.kernels.qux")
+ {
+ static cv::GMatDesc outMeta(const cv::GMatDesc &in, const cv::GScalarDesc &) { return in; }
+ };
+
+ G_TYPED_KERNEL(Quux, <cv::GMat(cv::GScalar, cv::GMat)>, "test.kernels.quux")
+ {
+ static cv::GMatDesc outMeta(const cv::GScalarDesc &, const cv::GMatDesc& in) { return in; }
+ };
+}
+
+// Kernel implementations for imaginary Jupiter device
+namespace Jupiter
+{
+ namespace detail
+ {
+ static cv::gapi::GBackend backend(std::make_shared<cv::gapi::GBackend::Priv>());
+ }
+
+ inline cv::gapi::GBackend backend() { return detail::backend; }
+
+ GAPI_OCV_KERNEL(Foo, I::Foo)
+ {
+ static void run(const cv::Mat &, cv::Mat &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+ GAPI_OCV_KERNEL(Bar, I::Bar)
+ {
+ static void run(const cv::Mat &, const cv::Mat &, cv::Mat &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+ GAPI_OCV_KERNEL(Baz, I::Baz)
+ {
+ static void run(const cv::Mat &, cv::Scalar &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+ GAPI_OCV_KERNEL(Qux, I::Qux)
+ {
+ static void run(const cv::Mat &, const cv::Scalar&, cv::Mat &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+
+ GAPI_OCV_KERNEL(Quux, I::Quux)
+ {
+ static void run(const cv::Scalar&, const cv::Mat&, cv::Mat &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+} // namespace Jupiter
+
+// Kernel implementations for imaginary Saturn device
+namespace Saturn
+{
+ namespace detail
+ {
+ static cv::gapi::GBackend backend(std::make_shared<cv::gapi::GBackend::Priv>());
+ }
+
+ inline cv::gapi::GBackend backend() { return detail::backend; }
+
+ GAPI_OCV_KERNEL(Foo, I::Foo)
+ {
+ static void run(const cv::Mat &, cv::Mat &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+ GAPI_OCV_KERNEL(Bar, I::Bar)
+ {
+ static void run(const cv::Mat &, const cv::Mat &, cv::Mat &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+ GAPI_OCV_KERNEL(Baz, I::Baz)
+ {
+ static void run(const cv::Mat &, cv::Scalar &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+ GAPI_OCV_KERNEL(Qux, I::Qux)
+ {
+ static void run(const cv::Mat &, const cv::Scalar&, cv::Mat &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+
+ GAPI_OCV_KERNEL(Quux, I::Quux)
+ {
+ static void run(const cv::Scalar&, const cv::Mat&, cv::Mat &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return detail::backend; } // FIXME: Must be removed
+ };
+} // namespace Saturn
+} // anonymous namespace
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_sample_pipelines.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_sample_pipelines.cpp
new file mode 100644
index 000000000..815aa0d87
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_sample_pipelines.cpp
@@ -0,0 +1,301 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include <stdexcept>
+#include <ade/util/iota_range.hpp>
+#include "logger.hpp"
+
+namespace opencv_test
+{
+
+namespace
+{
+ G_TYPED_KERNEL(GInvalidResize, <GMat(GMat,Size,double,double,int)>, "org.opencv.test.invalid_resize")
+ {
+ static GMatDesc outMeta(GMatDesc in, Size, double, double, int) { return in; }
+ };
+
+ GAPI_OCV_KERNEL(GOCVInvalidResize, GInvalidResize)
+ {
+ static void run(const cv::Mat& in, cv::Size sz, double fx, double fy, int interp, cv::Mat &out)
+ {
+ cv::resize(in, out, sz, fx, fy, interp);
+ }
+ };
+
+ G_TYPED_KERNEL(GReallocatingCopy, <GMat(GMat)>, "org.opencv.test.reallocating_copy")
+ {
+ static GMatDesc outMeta(GMatDesc in) { return in; }
+ };
+
+ GAPI_OCV_KERNEL(GOCVReallocatingCopy, GReallocatingCopy)
+ {
+ static void run(const cv::Mat& in, cv::Mat &out)
+ {
+ out = in.clone();
+ }
+ };
+}
+
+TEST(GAPI_Pipeline, OverloadUnary_MatMat)
+{
+ cv::GMat in;
+ cv::GComputation comp(in, cv::gapi::bitwise_not(in));
+
+ cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
+ cv::Mat ref_mat = ~in_mat;
+
+ cv::Mat out_mat;
+ comp.apply(in_mat, out_mat);
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+
+ out_mat = cv::Mat();
+ auto cc = comp.compile(cv::descr_of(in_mat));
+ cc(in_mat, out_mat);
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GAPI_Pipeline, OverloadUnary_MatScalar)
+{
+ cv::GMat in;
+ cv::GComputation comp(in, cv::gapi::sum(in));
+
+ cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
+ cv::Scalar ref_scl = cv::sum(in_mat);
+
+ cv::Scalar out_scl;
+ comp.apply(in_mat, out_scl);
+ EXPECT_EQ(out_scl, ref_scl);
+
+ out_scl = cv::Scalar();
+ auto cc = comp.compile(cv::descr_of(in_mat));
+ cc(in_mat, out_scl);
+ EXPECT_EQ(out_scl, ref_scl);
+}
+
+TEST(GAPI_Pipeline, OverloadBinary_Mat)
+{
+ cv::GMat a, b;
+ cv::GComputation comp(a, b, cv::gapi::add(a, b));
+
+ cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
+ cv::Mat ref_mat = (in_mat+in_mat);
+
+ cv::Mat out_mat;
+ comp.apply(in_mat, in_mat, out_mat);
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+
+ out_mat = cv::Mat();
+ auto cc = comp.compile(cv::descr_of(in_mat), cv::descr_of(in_mat));
+ cc(in_mat, in_mat, out_mat);
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GAPI_Pipeline, OverloadBinary_Scalar)
+{
+ cv::GMat a, b;
+ cv::GComputation comp(a, b, cv::gapi::sum(a + b));
+
+ cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
+ cv::Scalar ref_scl = cv::sum(in_mat+in_mat);
+
+ cv::Scalar out_scl;
+ comp.apply(in_mat, in_mat, out_scl);
+ EXPECT_EQ(out_scl, ref_scl);
+
+ out_scl = cv::Scalar();
+ auto cc = comp.compile(cv::descr_of(in_mat), cv::descr_of(in_mat));
+ cc(in_mat, in_mat, out_scl);
+ EXPECT_EQ(out_scl, ref_scl);
+}
+
+TEST(GAPI_Pipeline, Sharpen)
+{
+ const cv::Size sz_in (1280, 720);
+ const cv::Size sz_out( 640, 480);
+ cv::Mat in_mat (sz_in, CV_8UC3);
+ in_mat = cv::Scalar(128, 33, 53);
+
+ cv::Mat out_mat(sz_out, CV_8UC3);
+ cv::Mat out_mat_y;
+ cv::Mat out_mat_ocv(sz_out, CV_8UC3);
+
+ float sharpen_coeffs[] = {
+ 0.0f, -1.f, 0.0f,
+ -1.0f, 5.f, -1.0f,
+ 0.0f, -1.f, 0.0f
+ };
+ cv::Mat sharpen_kernel(3, 3, CV_32F, sharpen_coeffs);
+
+ // G-API code //////////////////////////////////////////////////////////////
+
+ cv::GMat in;
+ auto vga = cv::gapi::resize(in, sz_out);
+ auto yuv = cv::gapi::RGB2YUV(vga);
+ auto yuv_p = cv::gapi::split3(yuv);
+ auto y_sharp = cv::gapi::filter2D(std::get<0>(yuv_p), -1, sharpen_kernel);
+ auto yuv_new = cv::gapi::merge3(y_sharp, std::get<1>(yuv_p), std::get<2>(yuv_p));
+ auto out = cv::gapi::YUV2RGB(yuv_new);
+
+ cv::GComputation c(cv::GIn(in), cv::GOut(y_sharp, out));
+ c.apply(cv::gin(in_mat), cv::gout(out_mat_y, out_mat));
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::Mat smaller;
+ cv::resize(in_mat, smaller, sz_out);
+
+ cv::Mat yuv_mat;
+ cv::cvtColor(smaller, yuv_mat, cv::COLOR_RGB2YUV);
+ std::vector<cv::Mat> yuv_planar(3);
+ cv::split(yuv_mat, yuv_planar);
+ cv::filter2D(yuv_planar[0], yuv_planar[0], -1, sharpen_kernel);
+ cv::merge(yuv_planar, yuv_mat);
+ cv::cvtColor(yuv_mat, out_mat_ocv, cv::COLOR_YUV2RGB);
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ cv::Mat diff = out_mat_ocv != out_mat;
+ std::vector<cv::Mat> diffBGR(3);
+ cv::split(diff, diffBGR);
+ EXPECT_EQ(0, cv::countNonZero(diffBGR[0]));
+ EXPECT_EQ(0, cv::countNonZero(diffBGR[1]));
+ EXPECT_EQ(0, cv::countNonZero(diffBGR[2]));
+ }
+
+ // Metadata check /////////////////////////////////////////////////////////
+ {
+ auto cc = c.compile(cv::descr_of(in_mat));
+ auto metas = cc.outMetas();
+ ASSERT_EQ(2u, metas.size());
+
+ auto out_y_meta = cv::util::get<cv::GMatDesc>(metas[0]);
+ auto out_meta = cv::util::get<cv::GMatDesc>(metas[1]);
+
+ // Y-output
+ EXPECT_EQ(CV_8U, out_y_meta.depth);
+ EXPECT_EQ(1, out_y_meta.chan);
+ EXPECT_EQ(640, out_y_meta.size.width);
+ EXPECT_EQ(480, out_y_meta.size.height);
+
+ // Final output
+ EXPECT_EQ(CV_8U, out_meta.depth);
+ EXPECT_EQ(3, out_meta.chan);
+ EXPECT_EQ(640, out_meta.size.width);
+ EXPECT_EQ(480, out_meta.size.height);
+ }
+}
+
+TEST(GAPI_Pipeline, CustomRGB2YUV)
+{
+ const cv::Size sz(1280, 720);
+
+ // BEWARE:
+ //
+ // std::vector<cv::Mat> out_mats_cv(3, cv::Mat(sz, CV_8U))
+ //
+ // creates a vector of 3 elements pointing to the same Mat!
+ // FIXME: Make a G-API check for that
+ const int INS = 3;
+ std::vector<cv::Mat> in_mats(INS);
+ for (auto i : ade::util::iota(INS))
+ {
+ in_mats[i].create(sz, CV_8U);
+ cv::randu(in_mats[i], cv::Scalar::all(0), cv::Scalar::all(255));
+ }
+
+ const int OUTS = 3;
+ std::vector<cv::Mat> out_mats_cv(OUTS);
+ std::vector<cv::Mat> out_mats_gapi(OUTS);
+ for (auto i : ade::util::iota(OUTS))
+ {
+ out_mats_cv [i].create(sz, CV_8U);
+ out_mats_gapi[i].create(sz, CV_8U);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ {
+ cv::GMat r, g, b;
+ cv::GMat y = 0.299f*r + 0.587f*g + 0.114f*b;
+ cv::GMat u = 0.492f*(b - y);
+ cv::GMat v = 0.877f*(r - y);
+
+ cv::GComputation customCvt({r, g, b}, {y, u, v});
+ customCvt.apply(in_mats, out_mats_gapi);
+ }
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::Mat r = in_mats[0], g = in_mats[1], b = in_mats[2];
+ cv::Mat y = 0.299f*r + 0.587f*g + 0.114f*b;
+ cv::Mat u = 0.492f*(b - y);
+ cv::Mat v = 0.877f*(r - y);
+
+ out_mats_cv[0] = y;
+ out_mats_cv[1] = u;
+ out_mats_cv[2] = v;
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ const auto diff = [](cv::Mat m1, cv::Mat m2, int t) {
+ return cv::abs(m1-m2) > t;
+ };
+
+ // FIXME: Not bit-accurate even now!
+ cv::Mat
+ diff_y = diff(out_mats_cv[0], out_mats_gapi[0], 2),
+ diff_u = diff(out_mats_cv[1], out_mats_gapi[1], 2),
+ diff_v = diff(out_mats_cv[2], out_mats_gapi[2], 2);
+
+ EXPECT_EQ(0, cv::countNonZero(diff_y));
+ EXPECT_EQ(0, cv::countNonZero(diff_u));
+ EXPECT_EQ(0, cv::countNonZero(diff_v));
+ }
+}
+
+TEST(GAPI_Pipeline, PipelineWithInvalidKernel)
+{
+ cv::GMat in, out;
+ cv::Mat in_mat(500, 500, CV_8UC1), out_mat;
+ out = GInvalidResize::on(in, cv::Size(300, 300), 0.0, 0.0, cv::INTER_LINEAR);
+
+ const auto pkg = cv::gapi::kernels<GOCVInvalidResize>();
+ cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+
+ EXPECT_THROW(comp.apply(in_mat, out_mat, cv::compile_args(pkg)), std::logic_error);
+}
+
+TEST(GAPI_Pipeline, InvalidOutputComputation)
+{
+ cv::GMat in1, out1, out2, out3;
+
+ std::tie(out1, out2, out2) = cv::gapi::split3(in1);
+ cv::GComputation c({in1}, {out1, out2, out3});
+ cv::Mat in_mat;
+ cv::Mat out_mat1, out_mat2, out_mat3, out_mat4;
+ std::vector<cv::Mat> u_outs = {out_mat1, out_mat2, out_mat3, out_mat4};
+ std::vector<cv::Mat> u_ins = {in_mat};
+
+ EXPECT_THROW(c.apply(u_ins, u_outs), std::logic_error);
+}
+
+TEST(GAPI_Pipeline, PipelineAllocatingKernel)
+{
+ cv::GMat in, out;
+ cv::Mat in_mat(500, 500, CV_8UC1), out_mat;
+ out = GReallocatingCopy::on(in);
+
+ const auto pkg = cv::gapi::kernels<GOCVReallocatingCopy>();
+ cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+
+ EXPECT_THROW(comp.apply(in_mat, out_mat, cv::compile_args(pkg)), std::logic_error);
+}
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_scalar_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_scalar_tests.cpp
new file mode 100644
index 000000000..7b4baa01d
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_scalar_tests.cpp
@@ -0,0 +1,117 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include <iostream>
+
+namespace opencv_test
+{
+
+TEST(GAPI_Scalar, Argument)
+{
+ cv::Size sz(2, 2);
+ cv::Mat in_mat(sz, CV_8U);
+ cv::randn(in_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));
+
+ cv::GComputationT<cv::GMat (cv::GMat, cv::GScalar)> mulS([](cv::GMat in, cv::GScalar c)
+ {
+ return in*c;
+ });
+
+ cv::Mat out_mat(sz, CV_8U);
+ mulS.apply(in_mat, cv::Scalar(2), out_mat);
+
+ cv::Mat reference = in_mat*2;
+ EXPECT_EQ(0, cv::countNonZero(cv::abs(out_mat - reference)));
+}
+
+TEST(GAPI_Scalar, ReturnValue)
+{
+ const cv::Size sz(2, 2);
+ cv::Mat in_mat(sz, CV_8U, cv::Scalar(1));
+
+ cv::GComputationT<cv::GScalar (cv::GMat)> sum_of_sum([](cv::GMat in)
+ {
+ return cv::gapi::sum(in + in);
+ });
+
+ cv::Scalar out;
+ sum_of_sum.apply(in_mat, out);
+
+ EXPECT_EQ(8, out[0]);
+}
+
+TEST(GAPI_Scalar, TmpScalar)
+{
+ const cv::Size sz(2, 2);
+ cv::Mat in_mat(sz, CV_8U, cv::Scalar(1));
+
+ cv::GComputationT<cv::GMat (cv::GMat)> mul_by_sum([](cv::GMat in)
+ {
+ return in * cv::gapi::sum(in);
+ });
+
+ cv::Mat out_mat(sz, CV_8U);
+ mul_by_sum.apply(in_mat, out_mat);
+
+ cv::Mat reference = cv::Mat(sz, CV_8U, cv::Scalar(4));
+ EXPECT_EQ(0, cv::countNonZero(cv::abs(out_mat - reference)));
+}
+
+TEST(GAPI_ScalarWithValue, Simple_Arithmetic_Pipeline)
+{
+ GMat in;
+ GMat out = (in + 1) * 2;
+ cv::GComputation comp(in, out);
+
+ cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1);
+ cv::Mat ref_mat, out_mat;
+
+ ref_mat = (in_mat + 1) * 2;
+ comp.apply(in_mat, out_mat);
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GAPI_ScalarWithValue, GScalar_Initilization)
+{
+ cv::Scalar sc(2);
+ cv::GMat in;
+ cv::GScalar s(sc);
+ cv::GComputation comp(in, cv::gapi::mulC(in, s));
+
+ cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1);
+ cv::Mat ref_mat, out_mat;
+ cv::multiply(in_mat, sc, ref_mat, 1, CV_8UC1);
+ comp.apply(cv::gin(in_mat), cv::gout(out_mat));
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+TEST(GAPI_ScalarWithValue, Constant_GScalar_In_Middle_Graph)
+{
+ cv::Scalar sc(5);
+ cv::GMat in1;
+ cv::GScalar in2;
+ cv::GScalar s(sc);
+
+ auto add_out = cv::gapi::addC(in1, in2);
+ cv::GComputation comp(cv::GIn(in1, in2), cv::GOut(cv::gapi::mulC(add_out, s)));
+
+ cv::Mat in_mat = cv::Mat::eye(3, 3, CV_8UC1);
+ cv::Scalar in_scalar(3);
+
+ cv::Mat ref_mat, out_mat, add_mat;
+ cv::add(in_mat, in_scalar, add_mat);
+ cv::multiply(add_mat, sc, ref_mat, 1, CV_8UC1);
+ comp.apply(cv::gin(in_mat, in_scalar), cv::gout(out_mat));
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_smoke_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_smoke_test.cpp
new file mode 100644
index 000000000..9ac47f6d7
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_smoke_test.cpp
@@ -0,0 +1,97 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+namespace opencv_test
+{
+
+TEST(GAPI, Mat_Create_NoLink)
+{
+ cv::Mat m1;
+ cv::Mat m2 = m1;
+ m2.create(32, 32, CV_8U);
+
+ EXPECT_NE(m1.rows, m2.rows);
+ EXPECT_NE(m1.cols, m2.cols);
+ EXPECT_NE(m1.data, m2.data);
+}
+
+TEST(GAPI, Mat_Recreate)
+{
+ cv::Mat m1 = cv::Mat::zeros(480, 640, CV_8U);
+ m1.at<uchar>(0, 0) = 128;
+ cv::Mat m2 = m1;
+
+ EXPECT_EQ(m1.rows, m2.rows);
+ EXPECT_EQ(m1.cols, m2.cols);
+ EXPECT_EQ(m1.data, m2.data);
+ EXPECT_EQ(m1.at<uchar>(0, 0), m2.at<uchar>(0, 0));
+
+ // Calling "create" with the same meta is NOOP - both m1 and m2 are the same
+ m1.create(480, 640, CV_8U);
+ EXPECT_EQ(m1.rows, m2.rows);
+ EXPECT_EQ(m1.cols, m2.cols);
+ EXPECT_EQ(m1.data, m2.data);
+ EXPECT_EQ(m1.at<uchar>(0, 0), m2.at<uchar>(0, 0));
+
+ // Calling "create" on m2 with different meta doesn't update original m1
+ // Now m1 and m2 are distinct
+ m2.create(720, 1280, CV_8U);
+ m2.at<uchar>(0, 0) = 64; // Initialize 0,0 element since m2 is a new buffer
+ EXPECT_NE(m1.rows, m2.rows);
+ EXPECT_NE(m1.cols, m2.cols);
+ EXPECT_NE(m1.data, m2.data);
+ EXPECT_NE(m1.at<uchar>(0, 0), m2.at<uchar>(0, 0));
+
+ // What if a Mat is created from handle?
+ uchar data[] = {
+ 32, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0
+ };
+ cv::Mat m3(3, 3, CV_8U, data);
+ cv::Mat m4 = m3;
+ EXPECT_EQ(m3.rows, m4.rows);
+ EXPECT_EQ(m3.cols, m4.cols);
+ EXPECT_EQ(m3.data, m4.data);
+ EXPECT_EQ(data, m3.data);
+ EXPECT_EQ(data, m4.data);
+ EXPECT_EQ(m3.at<uchar>(0, 0), m4.at<uchar>(0, 0));
+
+ // cv::Mat::create must be NOOP if we don't change the meta,
+ // even if the origianl mat is created from handle.
+ m4.create(3, 3, CV_8U);
+ EXPECT_EQ(m3.rows, m4.rows);
+ EXPECT_EQ(m3.cols, m4.cols);
+ EXPECT_EQ(m3.data, m4.data);
+ EXPECT_EQ(data, m3.data);
+ EXPECT_EQ(data, m4.data);
+ EXPECT_EQ(m3.at<uchar>(0, 0), m4.at<uchar>(0, 0));
+}
+
+TEST(GAPI, EmptyOutMat)
+{
+ cv::Mat in_mat = cv::Mat(480, 640, CV_8U, cv::Scalar(64));
+
+ cv::GComputation cc([]()
+ {
+ cv::GMat in;
+ cv::GMat out = in + in;
+ return cv::GComputation(in, out);
+ });
+
+ cv::Mat out;
+ cc.apply(in_mat, out);
+
+ EXPECT_EQ(640, out.cols);
+ EXPECT_EQ(480, out.rows);
+ EXPECT_EQ(CV_8U, out.type());
+ EXPECT_EQ(0, cv::countNonZero(out - (in_mat+in_mat)));
+}
+
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_typed_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_typed_tests.cpp
new file mode 100644
index 000000000..1716b5505
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_typed_tests.cpp
@@ -0,0 +1,185 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+namespace opencv_test
+{
+
+namespace
+{
+ cv::Mat diff(cv::Mat m1, cv::Mat m2, int t)
+ {
+ return cv::abs(m1-m2) > t;
+ }
+
+ int non_zero3(cv::Mat m3c)
+ {
+ std::vector<cv::Mat> mm(3);
+ cv::split(m3c, mm);
+ return ( cv::countNonZero(mm[0])
+ + cv::countNonZero(mm[1])
+ + cv::countNonZero(mm[2]));
+ }
+}
+
+TEST(GAPI_Typed, UnaryOp)
+{
+ // Initialization //////////////////////////////////////////////////////////
+ const cv::Size sz(32, 32);
+ cv::Mat
+ in_mat (sz, CV_8UC3),
+ out_mat_untyped(sz, CV_8UC3),
+ out_mat_typed1 (sz, CV_8UC3),
+ out_mat_typed2 (sz, CV_8UC3),
+ out_mat_cv (sz, CV_8UC3);
+ cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ // Untyped G-API ///////////////////////////////////////////////////////////
+ cv::GComputation cvtU([]()
+ {
+ cv::GMat in;
+ cv::GMat out = cv::gapi::RGB2YUV(in);
+ return cv::GComputation(in, out);
+ });
+ cvtU.apply(in_mat, out_mat_untyped);
+
+ // Typed G-API /////////////////////////////////////////////////////////////
+ cv::GComputationT<cv::GMat (cv::GMat)> cvtT(cv::gapi::RGB2YUV);
+ auto cvtTComp = cvtT.compile(cv::descr_of(in_mat));
+
+ cvtT.apply(in_mat, out_mat_typed1);
+ cvtTComp(in_mat, out_mat_typed2);
+
+ // Plain OpenCV ////////////////////////////////////////////////////////////
+ cv::cvtColor(in_mat, out_mat_cv, cv::COLOR_RGB2YUV);
+
+ // Comparison //////////////////////////////////////////////////////////////
+ // FIXME: There must be OpenCV comparison test functions already available!
+ cv::Mat
+ diff_u = diff(out_mat_cv, out_mat_untyped, 0),
+ diff_t = diff(out_mat_cv, out_mat_typed1, 0),
+ diff_tc = diff(out_mat_cv, out_mat_typed2, 0);
+
+ EXPECT_EQ(0, non_zero3(diff_u));
+ EXPECT_EQ(0, non_zero3(diff_t));
+ EXPECT_EQ(0, non_zero3(diff_tc));
+}
+
+TEST(GAPI_Typed, BinaryOp)
+{
+ // Initialization //////////////////////////////////////////////////////////
+ const cv::Size sz(32, 32);
+ cv::Mat
+ in_mat1 (sz, CV_8UC1),
+ in_mat2 (sz, CV_8UC1),
+ out_mat_untyped(sz, CV_8UC1),
+ out_mat_typed1 (sz, CV_8UC1),
+ out_mat_typed2 (sz, CV_8UC1),
+ out_mat_cv (sz, CV_8UC1);
+ cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ // Untyped G-API ///////////////////////////////////////////////////////////
+ cv::GComputation cvtU([]()
+ {
+ cv::GMat in1, in2;
+ cv::GMat out = cv::gapi::add(in1, in2);
+ return cv::GComputation({in1, in2}, {out});
+ });
+ std::vector<cv::Mat> u_ins = {in_mat1, in_mat2};
+ std::vector<cv::Mat> u_outs = {out_mat_untyped};
+ cvtU.apply(u_ins, u_outs);
+
+ // Typed G-API /////////////////////////////////////////////////////////////
+ cv::GComputationT<cv::GMat (cv::GMat, cv::GMat)> cvtT([](cv::GMat m1, cv::GMat m2)
+ {
+ return m1+m2;
+ });
+ auto cvtTC = cvtT.compile(cv::descr_of(in_mat1),
+ cv::descr_of(in_mat2));
+
+ cvtT.apply(in_mat1, in_mat2, out_mat_typed1);
+ cvtTC(in_mat1, in_mat2, out_mat_typed2);
+
+ // Plain OpenCV ////////////////////////////////////////////////////////////
+ cv::add(in_mat1, in_mat2, out_mat_cv);
+
+ // Comparison //////////////////////////////////////////////////////////////
+ // FIXME: There must be OpenCV comparison test functions already available!
+ cv::Mat
+ diff_u = diff(out_mat_cv, out_mat_untyped, 0),
+ diff_t = diff(out_mat_cv, out_mat_typed1, 0),
+ diff_tc = diff(out_mat_cv, out_mat_typed2, 0);
+
+ EXPECT_EQ(0, cv::countNonZero(diff_u));
+ EXPECT_EQ(0, cv::countNonZero(diff_t));
+ EXPECT_EQ(0, cv::countNonZero(diff_tc));
+}
+
+
+TEST(GAPI_Typed, MultipleOuts)
+{
+ // Initialization //////////////////////////////////////////////////////////
+ const cv::Size sz(32, 32);
+ cv::Mat
+ in_mat (sz, CV_8UC1),
+ out_mat_unt1 (sz, CV_8UC1),
+ out_mat_unt2 (sz, CV_8UC1),
+ out_mat_typed1(sz, CV_8UC1),
+ out_mat_typed2(sz, CV_8UC1),
+ out_mat_comp1 (sz, CV_8UC1),
+ out_mat_comp2 (sz, CV_8UC1),
+ out_mat_cv1 (sz, CV_8UC1),
+ out_mat_cv2 (sz, CV_8UC1);
+ cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar::all(255));
+
+ // Untyped G-API ///////////////////////////////////////////////////////////
+ cv::GComputation cvtU([]()
+ {
+ cv::GMat in;
+ cv::GMat out1 = in * 2.f;
+ cv::GMat out2 = in * 4.f;
+ return cv::GComputation({in}, {out1, out2});
+ });
+ std::vector<cv::Mat> u_ins = {in_mat};
+ std::vector<cv::Mat> u_outs = {out_mat_unt1, out_mat_unt2};
+ cvtU.apply(u_ins, u_outs);
+
+ // Typed G-API /////////////////////////////////////////////////////////////
+ cv::GComputationT<std::tuple<cv::GMat, cv::GMat> (cv::GMat)> cvtT([](cv::GMat in)
+ {
+ return std::make_tuple(in*2.f, in*4.f);
+ });
+ auto cvtTC = cvtT.compile(cv::descr_of(in_mat));
+
+ cvtT.apply(in_mat, out_mat_typed1, out_mat_typed2);
+ cvtTC(in_mat, out_mat_comp1, out_mat_comp2);
+
+ // Plain OpenCV ////////////////////////////////////////////////////////////
+ out_mat_cv1 = in_mat * 2.f;
+ out_mat_cv2 = in_mat * 4.f;
+
+ // Comparison //////////////////////////////////////////////////////////////
+ // FIXME: There must be OpenCV comparison test functions already available!
+ cv::Mat
+ diff_u1 = diff(out_mat_cv1, out_mat_unt1, 0),
+ diff_u2 = diff(out_mat_cv2, out_mat_unt2, 0),
+ diff_t1 = diff(out_mat_cv1, out_mat_typed1, 0),
+ diff_t2 = diff(out_mat_cv2, out_mat_typed2, 0),
+ diff_c1 = diff(out_mat_cv1, out_mat_comp1, 0),
+ diff_c2 = diff(out_mat_cv2, out_mat_comp2, 0);
+
+ EXPECT_EQ(0, cv::countNonZero(diff_u1));
+ EXPECT_EQ(0, cv::countNonZero(diff_u2));
+ EXPECT_EQ(0, cv::countNonZero(diff_t1));
+ EXPECT_EQ(0, cv::countNonZero(diff_t2));
+ EXPECT_EQ(0, cv::countNonZero(diff_c1));
+ EXPECT_EQ(0, cv::countNonZero(diff_c2));
+}
+
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_util_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_util_tests.cpp
new file mode 100644
index 000000000..574c0ab54
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gapi_util_tests.cpp
@@ -0,0 +1,43 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include <type_traits>
+
+#include "opencv2/gapi/util/util.hpp"
+
+namespace opencv_test
+{
+
+TEST(GAPIUtil, AllSatisfy)
+{
+ static_assert(true == cv::detail::all_satisfy<std::is_integral, long, int, char>::value,
+ "[long, int, char] are all integral types");
+ static_assert(true == cv::detail::all_satisfy<std::is_integral, char>::value,
+ "char is an integral type");
+
+ static_assert(false == cv::detail::all_satisfy<std::is_integral, float, int, char>::value,
+ "[float, int, char] are NOT all integral types");
+ static_assert(false == cv::detail::all_satisfy<std::is_integral, int, char, float>::value,
+ "[int, char, float] are NOT all integral types");
+ static_assert(false == cv::detail::all_satisfy<std::is_integral, float>::value,
+ "float is not an integral types");
+}
+
+TEST(GAPIUtil, AllButLast)
+{
+ using test1 = cv::detail::all_but_last<long, int, float>::type;
+ static_assert(true == cv::detail::all_satisfy<std::is_integral, test1>::value,
+ "[long, int] are all integral types (float skipped)");
+
+ using test2 = cv::detail::all_but_last<int, float, char>::type;
+ static_assert(false == cv::detail::all_satisfy<std::is_integral, test2>::value,
+ "[int, float] are NOT all integral types");
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_core_tests_gpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_core_tests_gpu.cpp
new file mode 100644
index 000000000..6c331c033
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_core_tests_gpu.cpp
@@ -0,0 +1,395 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+#include "../common/gapi_core_tests.hpp"
+#include "opencv2/gapi/gpu/core.hpp"
+
+#define CORE_GPU cv::gapi::core::gpu::kernels()
+
+namespace opencv_test
+{
+
+// FIXME: Wut? See MulTestGPU/MathOpTest below (duplicate?)
+INSTANTIATE_TEST_CASE_P(AddTestGPU, MathOpTest,
+ Combine(Values(ADD, MUL),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(1.0),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(false),
+ Values(cv::compile_args(CORE_GPU))),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(MulTestGPU, MathOpTest,
+ Combine(Values(MUL),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(1.0, 0.5, 2.0),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(false),
+ Values(cv::compile_args(CORE_GPU))),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(SubTestGPU, MathOpTest,
+ Combine(Values(SUB),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values (1.0),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(DivTestGPU, MathOpTest,
+ Combine(Values(DIV),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values (1.0, 0.5, 2.0),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))),
+ opencv_test::PrintMathOpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(MulTestGPU, MulDoubleTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(DivTestGPU, DivTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(DivCTestGPU, DivCTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MeanTestGPU, MeanTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+//TODO: mask test doesn't work
+#if 0
+INSTANTIATE_TEST_CASE_P(MaskTestGPU, MaskTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+#endif
+
+INSTANTIATE_TEST_CASE_P(SelectTestGPU, SelectTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Polar2CartGPU, Polar2CartTest,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Cart2PolarGPU, Cart2PolarTest,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(CompareTestGPU, CmpTest,
+ Combine(Values(CMP_EQ, CMP_GE, CMP_NE, CMP_GT, CMP_LT, CMP_LE),
+ testing::Bool(),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))),
+ opencv_test::PrintCmpCoreParams());
+
+INSTANTIATE_TEST_CASE_P(BitwiseTestGPU, BitwiseTest,
+ Combine(Values(AND, OR, XOR),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))),
+ opencv_test::PrintBWCoreParams());
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotTestGPU, NotTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ /*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MinTestGPU, MinTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MaxTestGPU, MaxTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SumTestGPU, SumTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(1e-3), //TODO: too relaxed?
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffTestGPU, AbsDiffTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(AbsDiffCTestGPU, AbsDiffCTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+// FIXME: Comparison introduced by YL doesn't work with C3
+INSTANTIATE_TEST_CASE_P(AddWeightedTestGPU, AddWeightedTest,
+ Combine(Values( CV_8UC1/*, CV_8UC3*/, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values( -1, CV_8U, CV_16U, CV_32F ),
+/*init output matrices or not*/ testing::Bool(),
+ Values(0.50005),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(NormTestGPU, NormTest,
+ Combine(Values(NORM_INF, NORM_L1, NORM_L2),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(1e-3), //TODO: too relaxed?
+ Values(cv::compile_args(CORE_GPU))),
+ opencv_test::PrintNormCoreParams());
+
+INSTANTIATE_TEST_CASE_P(IntegralTestGPU, IntegralTest,
+ Combine(Values( CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdTestGPU, ThresholdTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::THRESH_BINARY, cv::THRESH_BINARY_INV, cv::THRESH_TRUNC, cv::THRESH_TOZERO, cv::THRESH_TOZERO_INV),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ThresholdTestGPU, ThresholdOTTest,
+ Combine(Values(CV_8UC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::THRESH_OTSU, cv::THRESH_TRIANGLE),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+
+INSTANTIATE_TEST_CASE_P(InRangeTestGPU, InRangeTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Split3TestGPU, Split3Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Split4TestGPU, Split4Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ResizeTestGPU, ResizeTest,
+ Combine(Values(AbsSimilarPoints(2, 0.05).to_compare_f()),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::Size(64,64),
+ cv::Size(30,30)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ResizeTestGPU, ResizeTestFxFy,
+ Combine(Values(AbsSimilarPoints(2, 0.05).to_compare_f()),
+ Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(0.5, 0.1),
+ Values(0.5, 0.1),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Merge3TestGPU, Merge3Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Merge4TestGPU, Merge4Test,
+ Combine(Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(RemapTestGPU, RemapTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(FlipTestGPU, FlipTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(0,1,-1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(CropTestGPU, CropTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50)),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(LUTTestGPU, LUTTest,
+ Combine(Values(CV_8UC1, CV_8UC3),
+ Values(CV_8UC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(LUTTestCustomGPU, LUTTest,
+ Combine(Values(CV_8UC3),
+ Values(CV_8UC3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ConvertToGPU, ConvertToTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(CV_8U, CV_16U, CV_16S, CV_32F),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatHorTestGPU, ConcatHorTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatVertTestGPU, ConcatVertTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+
+//TODO: fix this backend to allow ConcatVertVec ConcatHorVec
+#if 0
+INSTANTIATE_TEST_CASE_P(ConcatVertVecTestGPU, ConcatVertVecTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ConcatHorVecTestGPU, ConcatHorVecTest,
+ Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::compile_args(CORE_GPU))));
+#endif
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_imgproc_tests_gpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_imgproc_tests_gpu.cpp
new file mode 100644
index 000000000..65d452c34
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_imgproc_tests_gpu.cpp
@@ -0,0 +1,227 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+
+#include "../common/gapi_imgproc_tests.hpp"
+#include "opencv2/gapi/gpu/imgproc.hpp"
+
+#define IMGPROC_GPU cv::gapi::imgproc::gpu::kernels()
+
+namespace opencv_test
+{
+
+
+INSTANTIATE_TEST_CASE_P(Filter2DTestGPU, Filter2DTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 4, 5, 7),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BoxFilterTestGPU, BoxFilterTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_f()),
+ Values(/*CV_8UC1,*/ CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3,5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::BORDER_DEFAULT),
+ Values(-1, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU)))); //TODO: 8UC1 doesn't work
+
+INSTANTIATE_TEST_CASE_P(SepFilterTestGPU_8U, SepFilterTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3),
+ Values(3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(-1, CV_16S, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SepFilterTestGPU_other, SepFilterTest,
+ Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
+ Values(CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(-1, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BlurTestGPU, BlurTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-4, 2).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3,5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::BORDER_DEFAULT),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(gaussBlurTestGPU, GaussianBlurTest,
+ Combine(Values(ToleranceFilter(1e-5f, 0.01).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3), // FIXIT 5
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MedianBlurTestGPU, MedianBlurTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(ErodeTestGPU, ErodeTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Erode3x3TestGPU, Erode3x3Test,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(1,2,4),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(DilateTestGPU, DilateTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::MorphShapes::MORPH_RECT,
+ cv::MorphShapes::MORPH_CROSS,
+ cv::MorphShapes::MORPH_ELLIPSE),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(Dilate3x3TestGPU, Dilate3x3Test,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(1,2,4),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(SobelTestGPU, SobelTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-4, 2).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1/*, CV_32FC1*/), //TODO: CV_32FC1 fails accuracy
+ Values(3, 5),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(-1, CV_32F),
+ Values(0, 1),
+ Values(1, 2),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(EqHistTestGPU, EqHistTest,
+ Combine(Values(AbsExact().to_compare_f()), // FIXIT Non reliable check
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(CannyTestGPU, CannyTest,
+ Combine(Values(AbsSimilarPoints(0, 0.05).to_compare_f()),
+ Values(CV_8UC1, CV_8UC3),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(3.0, 120.0),
+ Values(125.0, 240.0),
+ Values(3, 5),
+ testing::Bool(),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2GrayTestGPU, RGB2GrayTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2GrayTestGPU, BGR2GrayTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2YUVTestGPU, RGB2YUVTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(YUV2RGBTestGPU, YUV2RGBTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(RGB2LabTestGPU, RGB2LabTest,
+ Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2LUVTestGPU, BGR2LUVTest,
+ Combine(Values(ToleranceColor(5e-3, 6).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(LUV2BGRTestGPU, LUV2BGRTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BGR2YUVTestGPU, BGR2YUVTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+INSTANTIATE_TEST_CASE_P(YUV2BGRTestGPU, YUV2BGRTest,
+ Combine(Values(ToleranceColor(1e-3).to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(IMGPROC_GPU))));
+
+
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_operators_tests_gpu.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_operators_tests_gpu.cpp
new file mode 100644
index 000000000..5a116bd35
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/gpu/gapi_operators_tests_gpu.cpp
@@ -0,0 +1,72 @@
+// 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) 2018 Intel Corporation
+
+
+#include "../test_precomp.hpp"
+#include "../common/gapi_operators_tests.hpp"
+#include "opencv2/gapi/gpu/core.hpp"
+
+#define CORE_GPU cv::gapi::core::gpu::kernels()
+
+namespace opencv_test
+{
+
+
+INSTANTIATE_TEST_CASE_P(MathOperatorTestGPU, MathOperatorMatMatTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 2).to_compare_f()),
+ Values( opPlusM, opMinusM, opDivM,
+ opGreater, opLess, opGreaterEq, opLessEq, opEq, opNotEq),
+ Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(MathOperatorTestGPU, MathOperatorMatScalarTest,
+ Combine(Values(Tolerance_FloatRel_IntAbs(1e-4, 2).to_compare_f()),
+ Values( opPlus, opPlusR, opMinus, opMinusR, opMul, opMulR, // FIXIT avoid division by values near zero: opDiv, opDivR,
+ opGT, opLT, opGE, opLE, opEQ, opNE,
+ opGTR, opLTR, opGER, opLER, opEQR, opNER),
+ Values(CV_8UC1, CV_16SC1, CV_32FC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1, CV_8U, CV_32F),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestGPU, MathOperatorMatMatTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opAnd, opOr, opXor ),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseOperatorTestGPU, MathOperatorMatScalarTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values( opAND, opOR, opXOR, opANDR, opORR, opXORR ),
+ Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+ Values(-1),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+
+INSTANTIATE_TEST_CASE_P(BitwiseNotOperatorTestGPU, NotOperatorTest,
+ Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480),
+ cv::Size(128, 128)),
+/*init output matrices or not*/ testing::Bool(),
+ Values(cv::compile_args(CORE_GPU))));
+}
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_backend_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_backend_tests.cpp
new file mode 100644
index 000000000..67b627313
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_backend_tests.cpp
@@ -0,0 +1,86 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "gapi_mock_kernels.hpp"
+
+#include "compiler/gmodel.hpp"
+#include "compiler/gcompiler.hpp"
+
+namespace opencv_test {
+
+namespace {
+
+struct MockMeta
+{
+ static const char* name() { return "MockMeta"; }
+};
+
+class GMockBackendImpl final: public cv::gapi::GBackend::Priv
+{
+ virtual void unpackKernel(ade::Graph &,
+ const ade::NodeHandle &,
+ const cv::GKernelImpl &) override
+ {
+ // Do nothing here
+ }
+
+ virtual EPtr compile(const ade::Graph &,
+ const cv::GCompileArgs &,
+ const std::vector<ade::NodeHandle> &) const override
+ {
+ // Do nothing here as well
+ return {};
+ }
+
+ virtual void addBackendPasses(ade::ExecutionEngineSetupContext &ectx) override
+ {
+ ectx.addPass("transform", "set_mock_meta", [](ade::passes::PassContext &ctx) {
+ ade::TypedGraph<MockMeta> me(ctx.graph);
+ for (const auto &nh : me.nodes())
+ {
+ me.metadata(nh).set(MockMeta{});
+ }
+ });
+ }
+};
+
+static cv::gapi::GBackend mock_backend(std::make_shared<GMockBackendImpl>());
+
+GAPI_OCV_KERNEL(MockFoo, I::Foo)
+{
+ static void run(const cv::Mat &, cv::Mat &) { /*Do nothing*/ }
+ static cv::gapi::GBackend backend() { return mock_backend; } // FIXME: Must be removed
+};
+
+} // anonymous namespace
+
+TEST(GBackend, CustomPassesExecuted)
+{
+ cv::GMat in;
+ cv::GMat out = I::Foo::on(in);
+ cv::GComputation c(in, out);
+
+ // Prepare compilation parameters manually
+ const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
+ const auto pkg = cv::gapi::kernels<MockFoo>();
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(c, {in_meta}, cv::compile_args(pkg));
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ compiler.runPasses(*graph);
+
+ // Inspect the graph and verify the metadata written by Mock backend
+ ade::TypedGraph<MockMeta> me(*graph);
+ EXPECT_LT(0u, static_cast<std::size_t>(me.nodes().size()));
+ for (const auto &nh : me.nodes())
+ {
+ EXPECT_TRUE(me.metadata(nh).contains<MockMeta>());
+ }
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_executor_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_executor_tests.cpp
new file mode 100644
index 000000000..20aad89b6
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_executor_tests.cpp
@@ -0,0 +1,83 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+namespace opencv_test
+{
+
+// FIXME: avoid code duplication
+// The below graph and config is taken from ComplexIslands test suite
+TEST(GExecutor, SmokeTest)
+{
+ cv::GMat in[2];
+ cv::GMat tmp[4];
+ cv::GScalar scl;
+ cv::GMat out[2];
+
+ tmp[0] = cv::gapi::bitwise_not(cv::gapi::bitwise_not(in[0]));
+ tmp[1] = cv::gapi::boxFilter(in[1], -1, cv::Size(3,3));
+ tmp[2] = tmp[0] + tmp[1]; // FIXME: handle tmp[2] = tmp[0]+tmp[2] typo
+ scl = cv::gapi::sum(tmp[1]);
+ tmp[3] = cv::gapi::medianBlur(tmp[1], 3);
+ out[0] = tmp[2] + scl;
+ out[1] = cv::gapi::boxFilter(tmp[3], -1, cv::Size(3,3));
+
+ // isl0 #internal1
+ // ........................... .........
+ // (in1) -> NotNot ->(tmp0) --> Add ---------> (tmp2) --> AddC -------> (out1)
+ // :.....................^...: :..^....:
+ // : :
+ // : :
+ // #internal0 : :
+ // .....................:......... :
+ // (in2) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
+ // :..........:..................: isl1
+ // : ..............................
+ // `------------> Median -> (tmp3) --> Blur -------> (out2)
+ // :............................:
+
+ cv::gapi::island("isl0", cv::GIn(in[0], tmp[1]), cv::GOut(tmp[2]));
+ cv::gapi::island("isl1", cv::GIn(tmp[1]), cv::GOut(out[1]));
+
+ cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
+ cv::Mat in_mat2 = cv::Mat::eye(32, 32, CV_8UC1);
+ cv::Mat out_gapi[2];
+
+ // Run G-API:
+ cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
+ .apply(cv::gin(in_mat1, in_mat2), cv::gout(out_gapi[0], out_gapi[1]));
+
+ // Run OpenCV
+ cv::Mat out_ocv[2];
+ {
+ cv::Mat ocv_tmp0;
+ cv::Mat ocv_tmp1;
+ cv::Mat ocv_tmp2;
+ cv::Mat ocv_tmp3;
+ cv::Scalar ocv_scl;
+
+ ocv_tmp0 = in_mat1; // skip !(!)
+ cv::boxFilter(in_mat2, ocv_tmp1, -1, cv::Size(3,3));
+ ocv_tmp2 = ocv_tmp0 + ocv_tmp1;
+ ocv_scl = cv::sum(ocv_tmp1);
+ cv::medianBlur(ocv_tmp1, ocv_tmp3, 3);
+ out_ocv[0] = ocv_tmp2 + ocv_scl;
+ cv::boxFilter(ocv_tmp3, out_ocv[1], -1, cv::Size(3,3));
+ }
+
+ EXPECT_EQ(0, cv::countNonZero(out_gapi[0] != out_ocv[0]));
+ EXPECT_EQ(0, cv::countNonZero(out_gapi[1] != out_ocv[1]));
+
+ // FIXME: check that GIslandModel has more than 1 island (e.g. fusion
+ // with breakdown worked)
+}
+
+// FIXME: Add explicit tests on GMat/GScalar/GArray<T> being connectors
+// between executed islands
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_garg_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_garg_test.cpp
new file mode 100644
index 000000000..67696dbb0
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_garg_test.cpp
@@ -0,0 +1,100 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+namespace opencv_test {
+// Tests on T/Kind matching ////////////////////////////////////////////////////
+// {{
+
+template<class T, cv::detail::ArgKind Exp>
+struct Expected
+{
+ using type = T;
+ static const constexpr cv::detail::ArgKind kind = Exp;
+};
+
+template<typename T>
+struct GArgKind: public ::testing::Test
+{
+ using Type = typename T::type;
+ const cv::detail::ArgKind Kind = T::kind;
+};
+
+// The reason here is to _manually_ list types and their kinds
+// (and NOT reuse cv::detail::ArgKind::Traits<>, since it is a subject of testing)
+using GArg_Test_Types = ::testing::Types
+ <
+ // G-API types
+ Expected<cv::GMat, cv::detail::ArgKind::GMAT>
+ , Expected<cv::GScalar, cv::detail::ArgKind::GSCALAR>
+ , Expected<cv::GArray<int>, cv::detail::ArgKind::GARRAY>
+ , Expected<cv::GArray<float>, cv::detail::ArgKind::GARRAY>
+ , Expected<cv::GArray<cv::Point>, cv::detail::ArgKind::GARRAY>
+ , Expected<cv::GArray<cv::Rect>, cv::detail::ArgKind::GARRAY>
+
+ // Built-in types
+ , Expected<int, cv::detail::ArgKind::OPAQUE>
+ , Expected<float, cv::detail::ArgKind::OPAQUE>
+ , Expected<int*, cv::detail::ArgKind::OPAQUE>
+ , Expected<cv::Point, cv::detail::ArgKind::OPAQUE>
+ , Expected<std::string, cv::detail::ArgKind::OPAQUE>
+ , Expected<cv::Mat, cv::detail::ArgKind::OPAQUE>
+ , Expected<std::vector<int>, cv::detail::ArgKind::OPAQUE>
+ , Expected<std::vector<cv::Point>, cv::detail::ArgKind::OPAQUE>
+ >;
+
+TYPED_TEST_CASE(GArgKind, GArg_Test_Types);
+
+TYPED_TEST(GArgKind, LocalVar)
+{
+ typename TestFixture::Type val{};
+ cv::GArg arg(val);
+ EXPECT_EQ(TestFixture::Kind, arg.kind);
+}
+
+TYPED_TEST(GArgKind, ConstLocalVar)
+{
+ const typename TestFixture::Type val{};
+ cv::GArg arg(val);
+ EXPECT_EQ(TestFixture::Kind, arg.kind);
+}
+
+TYPED_TEST(GArgKind, RValue)
+{
+ cv::GArg arg = cv::GArg(typename TestFixture::Type());
+ EXPECT_EQ(TestFixture::Kind, arg.kind);
+}
+
+// }}
+////////////////////////////////////////////////////////////////////////////////
+
+TEST(GArg, HasWrap)
+{
+ static_assert(!cv::detail::has_custom_wrap<cv::GMat>::value,
+ "GMat has no custom marshalling logic");
+ static_assert(!cv::detail::has_custom_wrap<cv::GScalar>::value,
+ "GScalar has no custom marshalling logic");
+
+ static_assert(cv::detail::has_custom_wrap<cv::GArray<int> >::value,
+ "GArray<int> has custom marshalling logic");
+ static_assert(cv::detail::has_custom_wrap<cv::GArray<std::string> >::value,
+ "GArray<int> has custom marshalling logic");
+}
+
+TEST(GArg, GArrayU)
+{
+ // Placing a GArray<T> into GArg automatically strips it to GArrayU
+ cv::GArg arg1 = cv::GArg(cv::GArray<int>());
+ EXPECT_NO_THROW(arg1.get<cv::detail::GArrayU>());
+
+ cv::GArg arg2 = cv::GArg(cv::GArray<cv::Point>());
+ EXPECT_NO_THROW(arg2.get<cv::detail::GArrayU>());
+}
+
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_gmetaarg_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_gmetaarg_test.cpp
new file mode 100644
index 000000000..6dbf7778f
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_gmetaarg_test.cpp
@@ -0,0 +1,136 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include "api/gcomputation_priv.hpp"
+
+namespace opencv_test
+{
+
+TEST(GMetaArg, Traits_Is_Positive)
+{
+ using namespace cv::detail;
+
+ static_assert(is_meta_descr<cv::GScalarDesc>::value,
+ "GScalarDesc is a meta description type");
+
+ static_assert(is_meta_descr<cv::GMatDesc>::value,
+ "GMatDesc is a meta description type");
+}
+
+TEST(GMetaArg, Traits_Is_Negative)
+{
+ using namespace cv::detail;
+
+ static_assert(!is_meta_descr<cv::GCompileArgs>::value,
+ "GCompileArgs is NOT a meta description type");
+
+ static_assert(!is_meta_descr<int>::value,
+ "int is NOT a meta description type");
+
+ static_assert(!is_meta_descr<std::string>::value,
+ "str::string is NOT a meta description type");
+}
+
+TEST(GMetaArg, Traits_Are_EntireList_Positive)
+{
+ using namespace cv::detail;
+
+ static_assert(are_meta_descrs<cv::GScalarDesc>::value,
+ "GScalarDesc is a meta description type");
+
+ static_assert(are_meta_descrs<cv::GMatDesc>::value,
+ "GMatDesc is a meta description type");
+
+ static_assert(are_meta_descrs<cv::GMatDesc, cv::GScalarDesc>::value,
+ "Both GMatDesc and GScalarDesc are meta types");
+}
+
+TEST(GMetaArg, Traits_Are_EntireList_Negative)
+{
+ using namespace cv::detail;
+
+ static_assert(!are_meta_descrs<cv::GCompileArgs>::value,
+ "GCompileArgs is NOT among meta types");
+
+ static_assert(!are_meta_descrs<int, std::string>::value,
+ "Both int and std::string is NOT among meta types");
+
+ static_assert(!are_meta_descrs<cv::GMatDesc, cv::GScalarDesc, int>::value,
+ "List of type is not valid for meta as there\'s int");
+
+ static_assert(!are_meta_descrs<cv::GMatDesc, cv::GScalarDesc, cv::GCompileArgs>::value,
+ "List of type is not valid for meta as there\'s GCompileArgs");
+}
+
+TEST(GMetaArg, Traits_Are_ButLast_Positive)
+{
+ using namespace cv::detail;
+
+ static_assert(are_meta_descrs_but_last<cv::GScalarDesc, int>::value,
+ "List is valid (int is ommitted)");
+
+ static_assert(are_meta_descrs_but_last<cv::GMatDesc, cv::GScalarDesc, cv::GCompileArgs>::value,
+ "List is valid (GCompileArgs are omitted)");
+}
+
+TEST(GMetaArg, Traits_Are_ButLast_Negative)
+{
+ using namespace cv::detail;
+
+ static_assert(!are_meta_descrs_but_last<int, std::string>::value,
+ "Both int is NOT among meta types (std::string is omitted)");
+
+ static_assert(!are_meta_descrs_but_last<cv::GMatDesc, cv::GScalarDesc, int, int>::value,
+ "List of type is not valid for meta as there\'s two ints");
+
+ static_assert(!are_meta_descrs_but_last<cv::GMatDesc, cv::GScalarDesc, cv::GCompileArgs, float>::value,
+ "List of type is not valid for meta as there\'s GCompileArgs");
+}
+
+TEST(GMetaArg, Can_Get_Metas_From_Input_Run_Args)
+{
+ cv::Mat m(3, 3, CV_8UC3);
+ cv::Scalar s;
+ std::vector<int> v;
+
+ GMatDesc m_desc;
+ GMetaArgs meta_args = descr_of(cv::gin(m, s, v));
+
+ EXPECT_EQ(meta_args.size(), 3u);
+ EXPECT_NO_THROW(m_desc = util::get<cv::GMatDesc>(meta_args[0]));
+ EXPECT_NO_THROW(util::get<cv::GScalarDesc>(meta_args[1]));
+ EXPECT_NO_THROW(util::get<cv::GArrayDesc>(meta_args[2]));
+
+ EXPECT_EQ(CV_8U, m_desc.depth);
+ EXPECT_EQ(3, m_desc.chan);
+ EXPECT_EQ(cv::gapi::own::Size(3, 3), m_desc.size);
+}
+
+TEST(GMetaArg, Can_Get_Metas_From_Output_Run_Args)
+{
+ cv::Mat m(3, 3, CV_8UC3);
+ cv::Scalar s;
+ std::vector<int> v;
+
+ GMatDesc m_desc;
+ GRunArgsP out_run_args = cv::gout(m, s, v);
+ GMetaArg m_meta = descr_of(out_run_args[0]);
+ GMetaArg s_meta = descr_of(out_run_args[1]);
+ GMetaArg v_meta = descr_of(out_run_args[2]);
+
+ EXPECT_NO_THROW(m_desc = util::get<cv::GMatDesc>(m_meta));
+ EXPECT_NO_THROW(util::get<cv::GScalarDesc>(s_meta));
+ EXPECT_NO_THROW(util::get<cv::GArrayDesc>(v_meta));
+
+ EXPECT_EQ(CV_8U, m_desc.depth);
+ EXPECT_EQ(3, m_desc.chan);
+ EXPECT_EQ(cv::Size(3, 3), m_desc.size);
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp
new file mode 100644
index 000000000..a815e0d22
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp
@@ -0,0 +1,364 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include <ade/util/zip_range.hpp> // util::indexed
+
+#include "opencv2/gapi/gkernel.hpp"
+#include "compiler/gmodelbuilder.hpp"
+#include "compiler/gmodel.hpp" // RcDesc, GModel::init
+
+namespace opencv_test
+{
+
+namespace test
+{
+
+namespace
+{
+ cv::GMat unaryOp(cv::GMat m)
+ {
+ return cv::GCall(cv::GKernel{"gapi.test.unaryop", nullptr, { GShape::GMAT } }).pass(m).yield(0);
+ }
+
+ cv::GMat binaryOp(cv::GMat m1, cv::GMat m2)
+ {
+ return cv::GCall(cv::GKernel{"gapi.test.binaryOp", nullptr, { GShape::GMAT } }).pass(m1, m2).yield(0);
+ }
+
+ std::vector<ade::NodeHandle> collectOperations(const cv::gimpl::GModel::Graph& gr)
+ {
+ std::vector<ade::NodeHandle> ops;
+ for (const auto& nh : gr.nodes())
+ {
+ if (gr.metadata(nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP)
+ ops.push_back(nh);
+ }
+ return ops;
+ }
+
+ ade::NodeHandle inputOf(cv::gimpl::GModel::Graph& gm, ade::NodeHandle nh, std::size_t port)
+ {
+ for (const auto& eh : nh->inEdges())
+ {
+ if (gm.metadata(eh).get<cv::gimpl::Input>().port == port)
+ {
+ return eh->srcNode();
+ }
+ }
+ util::throw_error(std::logic_error("port " + std::to_string(port) + " not found"));
+ }
+}
+}// namespace opencv_test::test
+
+TEST(GModelBuilder, Unroll_TestUnary)
+{
+ cv::GMat in;
+ cv::GMat out = test::unaryOp(in);
+
+ auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args);
+
+ EXPECT_EQ(1u, unrolled.all_ops.size()); // There is one operation
+ EXPECT_EQ(2u, unrolled.all_data.size()); // And two data objects (in, out)
+
+ // TODO check what the operation is, and so on, and so on
+}
+
+TEST(GModelBuilder, Unroll_TestUnaryOfUnary)
+{
+ cv::GMat in;
+ cv::GMat out = test::unaryOp(test::unaryOp(in));
+
+ auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args);
+
+ EXPECT_EQ(2u, unrolled.all_ops.size()); // There're two operations
+ EXPECT_EQ(3u, unrolled.all_data.size()); // And three data objects (in, out)
+
+ // TODO check what the operation is, and so on, and so on
+}
+
+TEST(GModelBuilder, Unroll_Not_All_Protocol_Inputs_Are_Reached)
+{
+ cv::GMat in1, in2; // in1 -> unaryOp() -> u_op1 -> unaryOp() -> out
+ auto u_op1 = test::unaryOp(in1); // in2 -> unaryOp() -> u_op2
+ auto u_op2 = test::unaryOp(in2);
+ auto out = test::unaryOp(u_op1);
+
+ EXPECT_THROW(cv::gimpl::unrollExpr(cv::GIn(in1, in2).m_args, cv::GOut(out).m_args), std::logic_error);
+}
+
+TEST(GModelBuilder, Unroll_Parallel_Path)
+{
+ cv::GMat in1, in2; // in1 -> unaryOp() -> out1
+ auto out1 = test::unaryOp(in1); // in2 -> unaryOp() -> out2
+ auto out2 = test::unaryOp(in2);
+
+ auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in1, in2).m_args, cv::GOut(out1, out2).m_args);
+
+ EXPECT_EQ(unrolled.all_ops.size(), 2u);
+ EXPECT_EQ(unrolled.all_data.size(), 4u);
+}
+
+TEST(GModelBuilder, Unroll_WithBranch)
+{
+ // in -> unaryOp() -> tmp -->unaryOp() -> out1
+ // `---->unaryOp() -> out2
+
+ GMat in;
+ auto tmp = test::unaryOp(in);
+ auto out1 = test::unaryOp(tmp);
+ auto out2 = test::unaryOp(tmp);
+
+ auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out1, out2).m_args);
+
+ EXPECT_EQ(unrolled.all_ops.size(), 3u);
+ EXPECT_EQ(unrolled.all_data.size(), 4u);
+}
+
+TEST(GModelBuilder, Build_Unary)
+{
+ cv::GMat in;
+ cv::GMat out = test::unaryOp(in);
+
+ ade::Graph g;
+ cv::gimpl::GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out).m_args);
+
+ EXPECT_EQ(3u, static_cast<std::size_t>(g.nodes().size())); // Generated graph should have three nodes
+
+ // TODO: Check what the nodes are
+}
+
+TEST(GModelBuilder, Constant_GScalar)
+{
+ // in -> addC()-----(GMat)---->mulC()-----(GMat)---->unaryOp()----out
+ // ^ ^
+ // | |
+ // 3-------` c_s-------'
+
+ cv::GMat in;
+ cv::GScalar c_s = 5;
+ auto out = test::unaryOp((in + 3) * c_s); // 3 converted to GScalar
+
+ ade::Graph g;
+ cv::gimpl::GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out).m_args);
+ cv::gimpl::Protocol p;
+ std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
+
+ auto in_nh = p.in_nhs.front();
+ auto addC_nh = in_nh->outNodes().front();
+ auto mulC_nh = addC_nh->outNodes().front()->outNodes().front();
+
+ ASSERT_TRUE(gm.metadata(addC_nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP);
+ ASSERT_TRUE(gm.metadata(mulC_nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP);
+
+ auto s_3 = test::inputOf(gm, addC_nh, 1);
+ auto s_5 = test::inputOf(gm, mulC_nh, 1);
+
+ EXPECT_EQ(9u, static_cast<std::size_t>(g.nodes().size())); // 6 data nodes (1 -input, 1 output, 2 constant, 2 temp) and 3 op nodes
+ EXPECT_EQ(2u, static_cast<std::size_t>(addC_nh->inNodes().size())); // in and 3
+ EXPECT_EQ(2u, static_cast<std::size_t>(mulC_nh->inNodes().size())); // addC output and c_s
+ EXPECT_EQ(3, (util::get<cv::gapi::own::Scalar>(gm.metadata(s_3).get<cv::gimpl::ConstValue>().arg))[0]);
+ EXPECT_EQ(5, (util::get<cv::gapi::own::Scalar>(gm.metadata(s_5).get<cv::gimpl::ConstValue>().arg))[0]);
+}
+
+TEST(GModelBuilder, Check_Multiple_Outputs)
+{
+ // ------------------------------> r
+ // '
+ // ' -----------> i_out1
+ // ' '
+ // in ----> split3() ---> g ---> integral()
+ // ' '
+ // ' -----------> i_out2
+ // '
+ // '---------> b ---> unaryOp() ---> u_out
+
+ cv::GMat in, r, g, b, i_out1, i_out2, u_out;
+ std::tie(r, g, b) = cv::gapi::split3(in);
+ std::tie(i_out1, i_out2) = cv::gapi::integral(g, 1, 1);
+ u_out = test::unaryOp(b);
+
+ ade::Graph gr;
+ cv::gimpl::GModel::Graph gm(gr);
+ cv::gimpl::GModel::init(gm);
+ auto proto_slots = cv::gimpl::GModelBuilder(gr).put(cv::GIn(in).m_args, cv::GOut(r, i_out1, i_out2, u_out).m_args);
+ cv::gimpl::Protocol p;
+ std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
+
+ EXPECT_EQ(4u, static_cast<std::size_t>(p.out_nhs.size()));
+ EXPECT_EQ(0u, gm.metadata(p.out_nhs[0]->inEdges().front()).get<cv::gimpl::Output>().port);
+ EXPECT_EQ(0u, gm.metadata(p.out_nhs[1]->inEdges().front()).get<cv::gimpl::Output>().port);
+ EXPECT_EQ(1u, gm.metadata(p.out_nhs[2]->inEdges().front()).get<cv::gimpl::Output>().port);
+ EXPECT_EQ(0u, gm.metadata(p.out_nhs[3]->inEdges().front()).get<cv::gimpl::Output>().port);
+ for (const auto& it : ade::util::indexed(p.out_nhs))
+ {
+ const auto& out_nh = ade::util::value(it);
+
+ EXPECT_EQ(cv::gimpl::NodeType::DATA, gm.metadata(out_nh).get<cv::gimpl::NodeType>().t);
+ EXPECT_EQ(GShape::GMAT, gm.metadata(out_nh).get<cv::gimpl::Data>().shape);
+ }
+}
+
+TEST(GModelBuilder, Unused_Outputs)
+{
+ cv::GMat in;
+ auto yuv_p = cv::gapi::split3(in);
+
+ ade::Graph g;
+ cv::gimpl::GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(std::get<0>(yuv_p)).m_args);
+
+ EXPECT_EQ(5u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 1 operation, 3 outputs
+}
+
+TEST(GModelBuilder, Work_With_One_Channel_From_Split3)
+{
+ cv::GMat in, y, u, v;
+ std::tie(y, u, v) = cv::gapi::split3(in);
+ auto y_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
+
+ ade::Graph g;
+ cv::gimpl::GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(y_blur).m_args);
+
+ EXPECT_EQ(7u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 2 operation, 3 nodes from split3, 1 output
+}
+
+TEST(GModelBuilder, Add_Nodes_To_Unused_Nodes)
+{
+ cv::GMat in, y, u, v;
+ std::tie(y, u, v) = cv::gapi::split3(in);
+ auto y_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
+ // unused nodes
+ auto u_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
+ auto v_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
+
+ ade::Graph g;
+ cv::gimpl::GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(y_blur).m_args);
+
+ EXPECT_EQ(7u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 2 operation, 3 nodes from split3, 1 output
+}
+
+TEST(GModelBuilder, Unlisted_Inputs)
+{
+ // in1 -> binaryOp() -> out
+ // ^
+ // |
+ // in2 ----'
+
+ cv::GMat in1, in2;
+ auto out = test::binaryOp(in1, in2);
+
+ ade::Graph g;
+ cv::gimpl::GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ // add required 2 inputs but pass 1
+ EXPECT_THROW(cv::gimpl::GModelBuilder(g).put(cv::GIn(in1).m_args, cv::GOut(out).m_args), std::logic_error);
+}
+
+TEST(GModelBuilder, Unroll_No_Link_Between_In_And_Out)
+{
+ // in -> unaryOp() -> u_op
+ // other -> unaryOp() -> out
+
+ cv::GMat in, other;
+ auto u_op = test::unaryOp(in);
+ auto out = test::unaryOp(other);
+
+ EXPECT_THROW(cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args), std::logic_error);
+}
+
+
+TEST(GModel_builder, Check_Binary_Op)
+{
+ // in1 -> binaryOp() -> out
+ // ^
+ // |
+ // in2 -----'
+
+ cv::GMat in1, in2;
+ auto out = test::binaryOp(in1, in2);
+
+ ade::Graph g;
+ cv::gimpl::GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in1, in2).m_args, cv::GOut(out).m_args);
+
+ cv::gimpl::Protocol p;
+ std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
+ auto ops = test::collectOperations(g);
+
+ EXPECT_EQ(1u, ops.size());
+ EXPECT_EQ("gapi.test.binaryOp", gm.metadata(ops.front()).get<cv::gimpl::Op>().k.name);
+ EXPECT_EQ(2u, static_cast<std::size_t>(ops.front()->inEdges().size()));
+ EXPECT_EQ(1u, static_cast<std::size_t>(ops.front()->outEdges().size()));
+ EXPECT_EQ(1u, static_cast<std::size_t>(ops.front()->outNodes().size()));
+}
+
+TEST(GModelBuilder, Add_Operation_With_Two_Out_One_Time)
+{
+ // in -> integral() --> out_b1 -> unaryOp() -> out1
+ // |
+ // '-------> out_b2 -> unaryOp() -> out2
+
+ cv::GMat in, out_b1, out_b2;
+ std::tie(out_b1, out_b2) = cv::gapi::integral(in, 1, 1);
+ auto out1 = test::unaryOp(out_b1);
+ auto out2 = test::unaryOp(out_b1);
+
+ ade::Graph g;
+ cv::gimpl::GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out1, out2).m_args);
+
+ auto ops = test::collectOperations(gm);
+
+ cv::gimpl::Protocol p;
+ std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
+ auto integral_nh = p.in_nhs.front()->outNodes().front();
+
+ EXPECT_EQ(3u, ops.size());
+ EXPECT_EQ("org.opencv.core.matrixop.integral", gm.metadata(integral_nh).get<cv::gimpl::Op>().k.name);
+ EXPECT_EQ(1u, static_cast<std::size_t>(integral_nh->inEdges().size()));
+ EXPECT_EQ(2u, static_cast<std::size_t>(integral_nh->outEdges().size()));
+ EXPECT_EQ(2u, static_cast<std::size_t>(integral_nh->outNodes().size()));
+}
+TEST(GModelBuilder, Add_Operation_With_One_Out_One_Time)
+{
+ // in1 -> binaryOp() -> b_out -> unaryOp() -> out1
+ // ^ |
+ // | |
+ // in2 ------- '----> unaryOp() -> out2
+
+ cv::GMat in1, in2;
+ auto b_out = test::binaryOp(in1, in2);
+ auto out1 = test::unaryOp(b_out);
+ auto out2 = test::unaryOp(b_out);
+
+ ade::Graph g;
+ cv::gimpl::GModel::Graph gm(g);
+ cv::gimpl::GModel::init(gm);
+ auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in1, in2).m_args, cv::GOut(out1, out2).m_args);
+ cv::gimpl::Protocol p;
+ std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
+ cv::gimpl::GModel::Graph gr(g);
+ auto binaryOp_nh = p.in_nhs.front()->outNodes().front();
+
+ EXPECT_EQ(2u, static_cast<std::size_t>(binaryOp_nh->inEdges().size()));
+ EXPECT_EQ(1u, static_cast<std::size_t>(binaryOp_nh->outEdges().size()));
+ EXPECT_EQ(8u, static_cast<std::size_t>(g.nodes().size()));
+}
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_island_fusion_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_island_fusion_tests.cpp
new file mode 100644
index 000000000..91e55bed7
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_island_fusion_tests.cpp
@@ -0,0 +1,527 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "compiler/transactions.hpp"
+
+#include "gapi_mock_kernels.hpp"
+
+#include "compiler/gmodel.hpp"
+#include "compiler/gislandmodel.hpp"
+#include "compiler/gcompiler.hpp"
+
+namespace opencv_test
+{
+
+TEST(IslandFusion, TwoOps_OneIsland)
+{
+ namespace J = Jupiter; // see mock_kernels.cpp
+
+ // Define a computation:
+ //
+ // (in) -> J::Foo1 -> (tmp0) -> J::Foo2 -> (out)
+ // : :
+ // : "island0" :
+ // :<----------------------------->:
+
+ cv::GMat in;
+ cv::GMat tmp0 = I::Foo::on(in);
+ cv::GMat out = I::Foo::on(tmp0);
+ cv::GComputation cc(in, out);
+
+ // Prepare compilation parameters manually
+ const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
+ const auto pkg = cv::gapi::kernels<J::Foo>();
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ compiler.runPasses(*graph);
+
+ // Inspect the graph and verify the islands configuration
+ cv::gimpl::GModel::ConstGraph gm(*graph);
+
+ auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
+ auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
+ auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
+
+ // in/out mats shouldn't be assigned to any Island
+ EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
+
+ // Since tmp is surrounded by two J kernels, tmp should be assigned
+ // to island J
+ EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
+}
+
+TEST(IslandFusion, TwoOps_TwoIslands)
+{
+ namespace J = Jupiter; // see mock_kernels.cpp
+ namespace S = Saturn; // see mock_kernels.cpp
+
+ // Define a computation:
+ //
+ // (in) -> J::Foo --> (tmp0) -> S::Bar --> (out)
+ // : : -> :
+ // : : : :
+ // :<-------->: :<-------->:
+
+ cv::GMat in;
+ cv::GMat tmp0 = I::Foo::on(in);
+ cv::GMat out = I::Bar::on(tmp0, tmp0);
+ cv::GComputation cc(in, out);
+
+ // Prepare compilation parameters manually
+ const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
+ const auto pkg = cv::gapi::kernels<J::Foo, S::Bar>();
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ compiler.runPasses(*graph);
+
+ // Inspect the graph and verify the islands configuration
+ cv::gimpl::GModel::ConstGraph gm(*graph);
+
+ auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
+ auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
+ auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
+
+ // in/tmp/out mats shouldn't be assigned to any Island
+ EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
+
+ auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
+ cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
+
+ // There should be two islands in the GIslandModel
+ const auto is_island = [&](ade::NodeHandle nh) {
+ return (cv::gimpl::NodeKind::ISLAND
+ == gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
+ };
+ const std::size_t num_isl = std::count_if(gim.nodes().begin(),
+ gim.nodes().end(),
+ is_island);
+ EXPECT_EQ(2u, num_isl);
+
+ auto isl_foo_nh = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
+ auto isl_bar_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
+ ASSERT_NE(nullptr, isl_foo_nh);
+ ASSERT_NE(nullptr, isl_bar_nh);
+
+ // Islands should be different
+ auto isl_foo_obj = gim.metadata(isl_foo_nh).get<cv::gimpl::FusedIsland>().object;
+ auto isl_bar_obj = gim.metadata(isl_bar_nh).get<cv::gimpl::FusedIsland>().object;
+ EXPECT_FALSE(isl_foo_obj == isl_bar_obj);
+}
+
+TEST(IslandFusion, ConsumerHasTwoInputs)
+{
+ namespace J = Jupiter; // see mock_kernels.cpp
+
+ // Define a computation: island
+ // ............................
+ // (in0) ->:J::Foo -> (tmp) -> S::Bar :--> (out)
+ // :....................^.....:
+ // |
+ // (in1) -----------------------`
+ //
+
+ // Check that island is build correctly, when consumer has two inputs
+
+ GMat in[2];
+ GMat tmp = I::Foo::on(in[0]);
+ GMat out = I::Bar::on(tmp, in[1]);
+
+ cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
+
+ // Prepare compilation parameters manually
+ cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)}),
+ GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)})};
+ const auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ compiler.runPasses(*graph);
+
+ cv::gimpl::GModel::ConstGraph gm(*graph);
+
+ auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
+ auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
+ auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
+ auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
+
+ EXPECT_FALSE(gm.metadata(in0_nh ).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(in1_nh ).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
+ EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
+
+ auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
+ cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
+
+ const auto is_island = [&](ade::NodeHandle nh) {
+ return (cv::gimpl::NodeKind::ISLAND
+ == gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
+ };
+ const std::size_t num_isl = std::count_if(gim.nodes().begin(),
+ gim.nodes().end(),
+ is_island);
+ EXPECT_EQ(1u, num_isl);
+
+ auto isl_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
+ auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
+
+ EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp_nh));
+
+ EXPECT_EQ(2u, static_cast<std::size_t>(isl_nh->inNodes().size()));
+ EXPECT_EQ(1u, static_cast<std::size_t>(isl_nh->outNodes().size()));
+}
+
+TEST(IslandFusion, DataNodeUsedDifferentBackend)
+{
+ // Define a computation:
+ //
+ // internal isl isl0
+ // ...........................
+ // (in1) -> :J::Foo--> (tmp) -> J::Foo: --> (out0)
+ // :............|............:
+ // | ........
+ // `---->:S::Baz: --> (out1)
+ // :......:
+
+ // Check that the node was not dropped out of the island
+ // because it is used by the kernel from another backend
+
+ namespace J = Jupiter;
+ namespace S = Saturn;
+
+ cv::GMat in, tmp, out0;
+ cv::GScalar out1;
+ tmp = I::Foo::on(in);
+ out0 = I::Foo::on(tmp);
+ out1 = I::Baz::on(tmp);
+
+ cv::GComputation cc(cv::GIn(in), cv::GOut(out0, out1));
+
+ // Prepare compilation parameters manually
+ const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
+ const auto pkg = cv::gapi::kernels<J::Foo, S::Baz>();
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ compiler.runPasses(*graph);
+
+ // Inspect the graph and verify the islands configuration
+ cv::gimpl::GModel::ConstGraph gm(*graph);
+
+ auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
+ auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
+ auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out0);
+ auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out1);
+
+ EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
+
+ auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
+ cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
+
+ auto isl_nh = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
+ auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
+
+ EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp_nh));
+
+ EXPECT_EQ(2u, static_cast<std::size_t>(isl_nh->outNodes().size()));
+ EXPECT_EQ(7u, static_cast<std::size_t>(gm.nodes().size()));
+ EXPECT_EQ(6u, static_cast<std::size_t>(gim.nodes().size()));
+}
+
+TEST(IslandFusion, LoopBetweenDifferentBackends)
+{
+ // Define a computation:
+ //
+ //
+ // .............................
+ // (in) -> :J::Baz -> (tmp0) -> J::Quux: -> (out0)
+ // | :............|..........^....
+ // | ........ | | ........
+ // `---->:S::Foo: `----------|-------->:S::Qux:-> (out1)
+ // :....|.: | :....^.:
+ // | | |
+ // `-------------- (tmp1) -----------`
+
+ // Kernels S::Foo and S::Qux cannot merge, because there will be a cycle between islands
+
+ namespace J = Jupiter;
+ namespace S = Saturn;
+
+ cv::GScalar tmp0;
+ cv::GMat in, tmp1, out0, out1;
+
+ tmp0 = I::Baz::on(in);
+ tmp1 = I::Foo::on(in);
+ out1 = I::Qux::on(tmp1, tmp0);
+ out0 = I::Quux::on(tmp0, tmp1);
+
+ cv::GComputation cc(cv::GIn(in), cv::GOut(out1, out0));
+
+ // Prepare compilation parameters manually
+ const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
+ const auto pkg = cv::gapi::kernels<J::Baz, J::Quux, S::Foo, S::Qux>();
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ compiler.runPasses(*graph);
+
+ cv::gimpl::GModel::ConstGraph gm(*graph);
+ auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
+ cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
+
+ auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
+ auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
+ auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp1);
+ auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out0);
+ auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out1);
+
+ EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
+ // The node does not belong to the island so as not to form a cycle
+ EXPECT_FALSE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
+
+ EXPECT_TRUE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
+
+ // There should be three islands in the GIslandModel
+ const auto is_island = [&](ade::NodeHandle nh) {
+ return (cv::gimpl::NodeKind::ISLAND
+ == gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
+ };
+ const std::size_t num_isl = std::count_if(gim.nodes().begin(),
+ gim.nodes().end(),
+ is_island);
+ EXPECT_EQ(3u, num_isl);
+}
+
+TEST(IslandsFusion, PartionOverlapUserIsland)
+{
+ // Define a computation:
+ //
+ // internal isl isl0
+ // ........ ........
+ // (in0) -> :J::Foo:--> (tmp) ->:S::Bar: --> (out)
+ // :......: :......:
+ // ^
+ // |
+ // (in1) --------------------------`
+
+ // Check that internal islands does't overlap user island
+
+ namespace J = Jupiter;
+ namespace S = Saturn;
+
+ GMat in[2];
+ GMat tmp = I::Foo::on(in[0]);
+ GMat out = I::Bar::on(tmp, in[1]);
+
+ cv::gapi::island("isl0", cv::GIn(tmp, in[1]), cv::GOut(out));
+ cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
+
+ // Prepare compilation parameters manually
+ cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)}),
+ GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)})};
+ const auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ compiler.runPasses(*graph);
+
+ cv::gimpl::GModel::ConstGraph gm(*graph);
+ auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
+ cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
+
+ auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
+ auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
+ auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
+ auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
+
+ auto foo_nh = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
+ auto foo_obj = gim.metadata(foo_nh).get<cv::gimpl::FusedIsland>().object;
+
+ auto bar_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
+ auto bar_obj = gim.metadata(bar_nh).get<cv::gimpl::FusedIsland>().object;
+
+ EXPECT_FALSE(gm.metadata(in0_nh ).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(in1_nh ).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(foo_obj->is_user_specified());
+ EXPECT_TRUE(bar_obj->is_user_specified());
+}
+
+TEST(IslandsFusion, DISABLED_IslandContainsDifferentBackends)
+{
+ // Define a computation:
+ //
+ // isl0
+ // ............................
+ // (in0) -> :J::Foo:--> (tmp) -> S::Bar: --> (out)
+ // :..........................:
+ // ^
+ // |
+ // (in1) --------------------------`
+
+ // Try create island contains different backends
+
+ namespace J = Jupiter;
+ namespace S = Saturn;
+
+ GMat in[2];
+ GMat tmp = I::Foo::on(in[0]);
+ GMat out = I::Bar::on(tmp, in[1]);
+
+ cv::gapi::island("isl0", cv::GIn(in[0], in[1]), cv::GOut(out));
+ cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
+
+ // Prepare compilation parameters manually
+ cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)}),
+ GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)})};
+ const auto pkg = cv::gapi::kernels<J::Foo, S::Bar>();
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ EXPECT_ANY_THROW(compiler.runPasses(*graph));
+}
+
+TEST(IslandFusion, WithLoop)
+{
+ namespace J = Jupiter; // see mock_kernels.cpp
+
+ // Define a computation:
+ //
+ // (in) -> J::Foo --> (tmp0) -> J::Foo --> (tmp1) -> J::Qux -> (out)
+ // : ^
+ // '--> J::Baz --> (scl0) --'
+ //
+ // The whole thing should be merged to a single island
+ // There's a cycle warning if Foo/Foo/Qux are merged first
+ // Then this island both produces data for Baz and consumes data
+ // from Baz. This is a cycle and it should be avoided by the merging code.
+ //
+ cv::GMat in;
+ cv::GMat tmp0 = I::Foo::on(in);
+ cv::GMat tmp1 = I::Foo::on(tmp0);
+ cv::GScalar scl0 = I::Baz::on(tmp0);
+ cv::GMat out = I::Qux::on(tmp1, scl0);
+ cv::GComputation cc(in, out);
+
+ // Prepare compilation parameters manually
+ const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::gapi::own::Size(32,32)});
+ const auto pkg = cv::gapi::kernels<J::Foo, J::Baz, J::Qux>();
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ compiler.runPasses(*graph);
+
+ // Inspect the graph and verify the islands configuration
+ cv::gimpl::GModel::ConstGraph gm(*graph);
+
+ auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
+ auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
+ auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp1);
+ auto scl0_nh = cv::gimpl::GModel::dataNodeOf(gm, scl0);
+ auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
+
+ // in/out mats shouldn't be assigned to any Island
+ EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
+
+ // tmp0/tmp1/scl should be assigned to island
+ EXPECT_TRUE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
+ EXPECT_TRUE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
+ EXPECT_TRUE(gm.metadata(scl0_nh).contains<cv::gimpl::Island>());
+
+ // Check that there's a single island object and it contains all
+ // that data object handles
+
+ cv::gimpl::GModel::ConstGraph cg(*graph);
+ auto isl_model = cg.metadata().get<cv::gimpl::IslandModel>().model;
+ cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
+
+ const auto is_island = [&](ade::NodeHandle nh) {
+ return (cv::gimpl::NodeKind::ISLAND
+ == gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
+ };
+ const std::size_t num_isl = std::count_if(gim.nodes().begin(),
+ gim.nodes().end(),
+ is_island);
+ EXPECT_EQ(1u, num_isl);
+
+ auto isl_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
+ auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
+ EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp0_nh));
+ EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp1_nh));
+ EXPECT_TRUE(ade::util::contains(isl_obj->contents(), scl0_nh));
+}
+
+TEST(IslandFusion, Regression_ShouldFuseAll)
+{
+ // Initially the merge procedure didn't work as expected and
+ // stopped fusion even if it could be continued (e.g. full
+ // GModel graph could be fused into a single GIsland node).
+ // Example of this is custom RGB 2 YUV pipeline as shown below:
+
+ cv::GMat r, g, b;
+ cv::GMat y = 0.299f*r + 0.587f*g + 0.114f*b;
+ cv::GMat u = 0.492f*(b - y);
+ cv::GMat v = 0.877f*(r - y);
+
+ cv::GComputation customCvt({r, g, b}, {y, u, v});
+
+ const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
+
+ // Directly instantiate G-API graph compiler and run partial compilation
+ cv::gimpl::GCompiler compiler(customCvt, {in_meta,in_meta,in_meta}, cv::compile_args());
+ cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
+ compiler.runPasses(*graph);
+
+ cv::gimpl::GModel::ConstGraph cg(*graph);
+ auto isl_model = cg.metadata().get<cv::gimpl::IslandModel>().model;
+ cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
+
+ std::vector<ade::NodeHandle> data_nhs;
+ std::vector<ade::NodeHandle> isl_nhs;
+ for (auto &&nh : gim.nodes())
+ {
+ if (gim.metadata(nh).contains<cv::gimpl::FusedIsland>())
+ isl_nhs.push_back(std::move(nh));
+ else if (gim.metadata(nh).contains<cv::gimpl::DataSlot>())
+ data_nhs.push_back(std::move(nh));
+ else FAIL() << "GIslandModel node with unexpected metadata type";
+ }
+
+ EXPECT_EQ(6u, data_nhs.size()); // 3 input nodes + 3 output nodes
+ EXPECT_EQ(1u, isl_nhs.size()); // 1 island
+}
+
+// FIXME: add more tests on mixed (hetero) graphs
+// ADE-222, ADE-223
+
+// FIXME: add test on combination of user-specified island
+// which should be heterogeneous (based on kernel availability)
+// but as we don't support this, compilation should fail
+
+// FIXME: add tests on automatic inferred islands which are
+// connected via 1) gmat 2) gscalar 3) garray,
+// check the case with executor
+// check the case when this 1/2/3 interim object is also gcomputation output
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_island_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_island_tests.cpp
new file mode 100644
index 000000000..09f188032
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_island_tests.cpp
@@ -0,0 +1,653 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include "compiler/gmodel.hpp"
+#include "compiler/gcompiled_priv.hpp"
+
+namespace opencv_test
+{
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests on a plain graph
+//
+// (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
+//
+namespace
+{
+ struct PlainIslandsFixture
+ {
+ cv::GMat in;
+ cv::GMat tmp[3];
+ cv::GMat out;
+
+ PlainIslandsFixture()
+ {
+ tmp[0] = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
+ tmp[1] = cv::gapi::boxFilter(tmp[0], -1, cv::Size(3,3));
+ tmp[2] = cv::gapi::boxFilter(tmp[1], -1, cv::Size(3,3));
+ out = cv::gapi::boxFilter(tmp[2], -1, cv::Size(3,3));
+ }
+ };
+
+ struct Islands: public ::testing::Test, public PlainIslandsFixture {};
+
+ using GIntArray = GArray<int>;
+
+ G_TYPED_KERNEL(CreateMatWithDiag, <GMat(GIntArray)>, "test.array.create_mat_with_diag")
+ {
+ static GMatDesc outMeta(const GArrayDesc&) { return cv::GMatDesc{CV_32S, 1,{3, 3}}; }
+ };
+
+ GAPI_OCV_KERNEL(CreateMatWithDiagImpl, CreateMatWithDiag)
+ {
+ static void run(const std::vector<int> &in, cv::Mat& out)
+ {
+ auto size = static_cast<int>(in.size());
+ out = Mat::zeros(size, size, CV_32SC1);
+ for(int i = 0; i < out.rows; i++)
+ {
+ auto* row = out.ptr<int>(i);
+ row[i] = in[i];
+ }
+ }
+ };
+
+ G_TYPED_KERNEL(Mat2Array, <GIntArray(GMat)>, "test.array.mat2array")
+ {
+ static GArrayDesc outMeta(const GMatDesc&) { return empty_array_desc(); }
+ };
+
+ GAPI_OCV_KERNEL(Mat2ArrayImpl, Mat2Array)
+ {
+ static void run(const cv::Mat& in, std::vector<int> &out)
+ {
+ GAPI_Assert(in.depth() == CV_32S && in.isContinuous());
+ out.reserve(in.cols * in.rows);
+ out.assign((int*)in.datastart, (int*)in.dataend);
+ }
+ };
+}
+
+TEST_F(Islands, SmokeTest)
+{
+ // (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
+ // : "test" :
+ // :<------------------------->:
+ cv::gapi::island("test", cv::GIn(tmp[0]), cv::GOut(tmp[2]));
+ auto cc = cv::GComputation(in, out).compile(cv::GMatDesc{CV_8U,1,{640,480}});
+
+ const auto &gm = cc.priv().model();
+ const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
+ const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
+ const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
+
+ // tmp1 and tmp3 is not a part of any island
+ EXPECT_FALSE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp2_nh).contains<cv::gimpl::Island>());
+
+ // tmp2 is part of "test" island
+ EXPECT_TRUE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
+ EXPECT_EQ("test", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
+}
+
+TEST_F(Islands, TwoIslands)
+{
+ // (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
+ // : "test1" : : "test2" :
+ // :<---------------------------->: :<--------------------------------->
+ EXPECT_NO_THROW(cv::gapi::island("test1", cv::GIn(in), cv::GOut(tmp[1])));
+ EXPECT_NO_THROW(cv::gapi::island("test2", cv::GIn(tmp[1]), cv::GOut(out)));
+
+ auto cc = cv::GComputation(in, out).compile(cv::GMatDesc{CV_8U,1,{640,480}});
+ const auto &gm = cc.priv().model();
+ const auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
+ const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
+ const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
+ const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
+ const auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
+
+ // Only tmp0 and tmp2 should be listed in islands.
+ EXPECT_TRUE (gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
+ EXPECT_TRUE (gm.metadata(tmp2_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(in_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out_nh) .contains<cv::gimpl::Island>());
+
+ EXPECT_EQ("test1", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
+ EXPECT_EQ("test2", gm.metadata(tmp2_nh).get<cv::gimpl::Island>().island);
+}
+
+// FIXME: Disabled since currently merge procedure merges two into one
+// succesfully
+TEST_F(Islands, DISABLED_Two_Islands_With_Same_Name_Should_Fail)
+{
+ // (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
+ // : "test1" : : "test1" :
+ // :<---------------------------->: :<--------------------------------->
+
+ EXPECT_NO_THROW(cv::gapi::island("test1", cv::GIn(in), cv::GOut(tmp[1])));
+ EXPECT_NO_THROW(cv::gapi::island("test1", cv::GIn(tmp[1]), cv::GOut(out)));
+
+ EXPECT_ANY_THROW(cv::GComputation(in, out).compile(cv::GMatDesc{CV_8U,1,{640,480}}));
+}
+
+
+// (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
+// : "test1": : :
+// :<----------------:----------->: :
+// : :
+// : "test2" :
+// :<------------------------->:
+TEST_F(Islands, OverlappingIslands1)
+{
+ EXPECT_NO_THROW (cv::gapi::island("test1", cv::GIn(in), cv::GOut(tmp[1])));
+ EXPECT_ANY_THROW(cv::gapi::island("test2", cv::GIn(tmp[0]), cv::GOut(tmp[2])));
+}
+
+TEST_F(Islands, OverlappingIslands2)
+{
+ EXPECT_NO_THROW (cv::gapi::island("test2", cv::GIn(tmp[0]), cv::GOut(tmp[2])));
+ EXPECT_ANY_THROW(cv::gapi::island("test1", cv::GIn(in), cv::GOut(tmp[1])));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests on a complex graph
+//
+// (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
+// ^ ^
+// (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
+// :
+// `------------> Median -> (tmp3) --> Blur -------> (out1)
+//
+namespace
+{
+ struct ComplexIslandsFixture
+ {
+ cv::GMat in[2];
+ cv::GMat tmp[4];
+ cv::GScalar scl;
+ cv::GMat out[2];
+
+ ComplexIslandsFixture()
+ {
+ tmp[0] = cv::gapi::bitwise_not(in[0]);
+ tmp[1] = cv::gapi::boxFilter(in[1], -1, cv::Size(3,3));
+ tmp[2] = tmp[0] + tmp[1]; // FIXME: handle tmp[2] = tmp[0]+tmp[2] typo
+ scl = cv::gapi::sum(tmp[1]);
+ tmp[3] = cv::gapi::medianBlur(tmp[1], 3);
+ out[0] = tmp[2] + scl;
+ out[1] = cv::gapi::boxFilter(tmp[3], -1, cv::Size(3,3));
+ }
+ };
+
+ struct ComplexIslands: public ::testing::Test, public ComplexIslandsFixture {};
+} // namespace
+
+TEST_F(ComplexIslands, SmokeTest)
+{
+ // isl0 #internal1
+ // ........................... ........
+ // (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
+ // :............ ........^...: :.^....:
+ // ... : :
+ // (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
+ // : isl1
+ // : ..............................
+ // `------------> Median -> (tmp3) --> Blur -------> (out1)
+ // :............................:
+
+ cv::gapi::island("isl0", cv::GIn(in[0], tmp[1]), cv::GOut(tmp[2]));
+ cv::gapi::island("isl1", cv::GIn(tmp[1]), cv::GOut(out[1]));
+ auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
+ .compile(cv::GMatDesc{CV_8U,1,{640,480}},
+ cv::GMatDesc{CV_8U,1,{640,480}});
+ const auto &gm = cc.priv().model();
+ const auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
+ const auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
+ const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
+ const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
+ const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
+ const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
+ const auto scl_nh = cv::gimpl::GModel::dataNodeOf(gm, scl);
+ const auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out[0]);
+ const auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out[1]);
+
+ // tmp0, tmp3 are in islands, others are not
+ EXPECT_TRUE(gm.metadata(tmp0_nh) .contains<cv::gimpl::Island>()); // isl0
+ EXPECT_TRUE(gm.metadata(tmp3_nh) .contains<cv::gimpl::Island>()); // isl1
+ EXPECT_FALSE(gm.metadata(in0_nh) .contains<cv::gimpl::Island>()); // (input is never fused)
+ EXPECT_FALSE(gm.metadata(in1_nh) .contains<cv::gimpl::Island>()); // (input is never fused)
+ EXPECT_TRUE (gm.metadata(tmp1_nh).contains<cv::gimpl::Island>()); // <internal island>
+ EXPECT_FALSE(gm.metadata(tmp2_nh).contains<cv::gimpl::Island>()); // #not fused as cycle-causing#
+ EXPECT_FALSE(gm.metadata(scl_nh) .contains<cv::gimpl::Island>()); // #not fused as cycle-causing#
+ EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>()); // (output is never fused)
+ EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>()); // (output is never fused)
+
+ EXPECT_EQ("isl0", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
+ EXPECT_EQ("isl1", gm.metadata(tmp3_nh).get<cv::gimpl::Island>().island);
+
+ EXPECT_NE("isl0", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
+ EXPECT_NE("isl1", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
+
+ // FIXME: Add a test with same graph for Fusion and check GIslandModel
+}
+
+TEST_F(ComplexIslands, DistinictIslandsWithSameName)
+{
+ // isl0
+ // ...........................
+ // (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
+ // :............ ........^...: ^
+ // ... : :
+ // (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
+ // : isl0
+ // : ..............................
+ // `------------> Median -> (tmp3) --> Blur -------> (out1)
+ // :............................:
+
+ cv::gapi::island("isl0", cv::GIn(in[0], tmp[1]), cv::GOut(tmp[2]));
+ cv::gapi::island("isl0", cv::GIn(tmp[1]), cv::GOut(out[1]));
+
+ auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]));
+
+ EXPECT_ANY_THROW(cc.compile(cv::GMatDesc{CV_8U,1,{640,480}},
+ cv::GMatDesc{CV_8U,1,{640,480}}));
+}
+
+TEST_F(ComplexIslands, FullGraph)
+{
+ cv::gapi::island("isl0", cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]));
+ auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
+ .compile(cv::GMatDesc{CV_8U,1,{640,480}},
+ cv::GMatDesc{CV_8U,1,{640,480}});
+ const auto &gm = cc.priv().model();
+ std::vector<ade::NodeHandle> handles_inside = {
+ cv::gimpl::GModel::dataNodeOf(gm, tmp[0]),
+ cv::gimpl::GModel::dataNodeOf(gm, tmp[1]),
+ cv::gimpl::GModel::dataNodeOf(gm, tmp[2]),
+ cv::gimpl::GModel::dataNodeOf(gm, tmp[3]),
+ cv::gimpl::GModel::dataNodeOf(gm, scl),
+ };
+ std::vector<ade::NodeHandle> handles_outside = {
+ cv::gimpl::GModel::dataNodeOf(gm, in[0]),
+ cv::gimpl::GModel::dataNodeOf(gm, in[1]),
+ cv::gimpl::GModel::dataNodeOf(gm, out[0]),
+ cv::gimpl::GModel::dataNodeOf(gm, out[1]),
+ };
+
+ for (auto nh_inside : handles_inside)
+ {
+ EXPECT_EQ("isl0", gm.metadata(nh_inside).get<cv::gimpl::Island>().island);
+ }
+ for (auto nh_outside : handles_outside)
+ {
+ EXPECT_FALSE(gm.metadata(nh_outside).contains<cv::gimpl::Island>());
+ }
+}
+
+TEST_F(ComplexIslands, ViaScalar)
+{
+ //
+ // .........................................#internal0.
+ // (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
+ // :....................^.........................^...:
+ // : :
+ // .....................:.........(isl0). :
+ // (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
+ // :..........:.........................:
+ // :
+ // : ..................#internal1.
+ // `------------> Median -> (tmp3) --> Blur -------> (out1)
+ // :...........................:
+
+ cv::gapi::island("isl0", cv::GIn(in[1]), cv::GOut(scl));
+ auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
+ .compile(cv::GMatDesc{CV_8U,1,{640,480}},
+ cv::GMatDesc{CV_8U,1,{640,480}});
+ const auto &gm = cc.priv().model();
+
+ const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
+ const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
+ const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
+ const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
+
+ EXPECT_NE("isl0", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island); // <internal>
+ EXPECT_EQ("isl0", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island); // isl0
+ EXPECT_NE("isl0", gm.metadata(tmp2_nh).get<cv::gimpl::Island>().island); // <internal>
+ EXPECT_NE("isl0", gm.metadata(tmp3_nh).get<cv::gimpl::Island>().island); // <internal>
+
+ std::vector<ade::NodeHandle> handles_outside = {
+ cv::gimpl::GModel::dataNodeOf(gm, in[0]),
+ cv::gimpl::GModel::dataNodeOf(gm, in[1]),
+ cv::gimpl::GModel::dataNodeOf(gm, scl),
+ cv::gimpl::GModel::dataNodeOf(gm, out[0]),
+ cv::gimpl::GModel::dataNodeOf(gm, out[1]),
+ };
+ for (auto nh_outside : handles_outside)
+ {
+ EXPECT_FALSE(gm.metadata(nh_outside).contains<cv::gimpl::Island>());
+ }
+}
+
+TEST_F(ComplexIslands, BorderDataIsland)
+{
+ // .................................(isl0)..
+ // : :
+ // (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
+ // : ^ : ^
+ // : : : :
+ // (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
+ // :...........:...........................:
+ // : : :
+ // : : :.........................................(isl1)..
+ // : `------------> Median -> (tmp3) --> Blur -------> (out1)
+ // : :
+ // :......................................................:
+
+ cv::gapi::island("isl0", cv::GIn(in[0], in[1]), cv::GOut(tmp[2], scl));
+ cv::gapi::island("isl1", cv::GIn(tmp[1]), cv::GOut(out[1]));
+
+ auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
+ .compile(cv::GMatDesc{CV_8U,1,{640,480}},
+ cv::GMatDesc{CV_8U,1,{640,480}});
+ const auto &gm = cc.priv().model();
+ const auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
+ const auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
+ const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
+ const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
+ const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
+ const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
+ const auto scl_nh = cv::gimpl::GModel::dataNodeOf(gm, scl);
+ const auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out[0]);
+ const auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out[1]);
+
+ // Check handles inside isl0
+ EXPECT_EQ("isl0", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
+ EXPECT_EQ("isl0", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
+ // ^^^ Important - tmp1 is assigned to isl0, not isl1
+
+ // Check handles inside isl1
+ EXPECT_EQ("isl1", gm.metadata(tmp3_nh).get<cv::gimpl::Island>().island);
+
+ // Check outside handles
+ EXPECT_FALSE(gm.metadata(in0_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(in1_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp2_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(scl_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
+}
+
+
+TEST_F(ComplexIslands, IncompleteSpec)
+{
+ // isl0
+ // ...........................
+ // (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
+ // :...........xxx.......^...: ^
+ // : :
+ // (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
+ // :
+ // :
+ // `------------> Median -> (tmp3) --> Blur -------> (out1)
+ //
+
+ // tmp1 is missing in the below spec
+ EXPECT_ANY_THROW(cv::gapi::island("isl0", cv::GIn(in[0]), cv::GOut(tmp[2])));
+
+ // empty range
+ EXPECT_ANY_THROW(cv::gapi::island("isl1", cv::GIn(tmp[2]), cv::GOut(tmp[2])));
+}
+
+TEST_F(ComplexIslands, InputOperationFromDifferentIslands)
+{
+ // isl1
+ // ........................... ........
+ // (in0)--> Not -> (tmp0) --> Add :--------> (tmp2)-->: AddC : -------> (out0)
+ // :......................^..: : ^ :
+ // isl0 : : : :
+ // .......................:....................... : :
+ // (in1) :-> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----- :
+ // :....................................................:
+ // isl0 :
+ // `------------> Median -> (tmp3) --> Blur -------> (out1)
+ //
+
+ cv::gapi::island("isl0", cv::GIn(in[1], tmp[2]), cv::GOut(out[0]));
+ cv::gapi::island("isl1", cv::GIn(in[0], tmp[1]), cv::GOut(tmp[2]));
+ auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
+ .compile(cv::GMatDesc{CV_8U,1,{640,480}},
+ cv::GMatDesc{CV_8U,1,{640,480}});
+
+ const auto &gm = cc.priv().model();
+ const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
+ const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
+ const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
+
+ EXPECT_EQ("isl1", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
+ EXPECT_EQ("isl0", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
+ EXPECT_FALSE(gm.metadata(tmp2_nh).contains<cv::gimpl::Island>());
+}
+
+TEST_F(ComplexIslands, NoWayBetweenNodes)
+{
+ // (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
+ // ^ ^
+ // (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
+ // :
+ // `------------> Median -> (tmp3) --> Blur -------> (out1)
+
+ EXPECT_ANY_THROW(cv::gapi::island("isl0", cv::GIn(in[1]), cv::GOut(tmp[0])));
+}
+
+TEST_F(ComplexIslands, IslandsContainUnusedPart)
+{
+ // Unused part of the graph
+ // x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
+ // x x
+ // x(in0) -> Not -> (tmp0) --> Add ---------> (tmp2)---> AddC ---------> (out0) x
+ // x ^ ^ x
+ // x x x x x x x x x x x x x x x | x x | x
+ // | x | x
+ // ...... | x | x
+ // (in1) -> :Blur:----------> (tmp1) x-----> Sum ------> (scl0) x
+ // ...... : x x x x x x x x x x x x x x x x x x x x x x x x
+ // isl0
+ // :
+ // `------------> Median -> (tmp3) --> Blur -------> (out1)
+
+ cv::gapi::island("isl0", cv::GIn(in[1]), cv::GOut(scl));
+ auto cc = cv::GComputation(cv::GIn(in[1]), cv::GOut(out[1]))
+ .compile(cv::GMatDesc{CV_8U,1,{640,480}});
+
+ const auto &gm = cc.priv().model();
+ const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
+
+ //The output 0 is not specified in the graph
+ //means that there will not be a node scl, so that tmp1 will not assign to the island
+ // FIXME Check that blur assigned to island using the function producerOf
+ // After merge islands fusion
+ EXPECT_FALSE(gm.metadata(tmp1_nh) .contains<cv::gimpl::Island>());
+}
+
+TEST_F(ComplexIslands, FullGraphInTwoIslands)
+{
+ // isl0
+ // ..................................................
+ // (in0) -> :Not -> (tmp0) --> Add ---------> (tmp2) --> AddC: -------> (out0)
+ // ...................^.... ^ :
+ // ............... | : : :
+ // (in1) -> :Blur-> (tmp1):----'-->:Sum ----> (scl0) ----' :
+ // ........ | : ...........................
+ // isl1 : | :............................................
+ // : `------------> Median -> (tmp3) --> Blur ------->:(out1)
+ // ....................................................
+
+ cv::gapi::island("isl0", cv::GIn(in[0], tmp[1]), cv::GOut(out[0]));
+ cv::gapi::island("isl1", cv::GIn(in[1]), cv::GOut(out[1]));
+ auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
+ .compile(cv::GMatDesc{CV_8U,1,{640,480}},
+ cv::GMatDesc{CV_8U,1,{640,480}});
+
+ const auto &gm = cc.priv().model();
+ const auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
+ const auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
+ const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
+ const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
+ const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
+ const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
+ const auto scl_nh = cv::gimpl::GModel::dataNodeOf(gm, scl);
+ const auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out[0]);
+ const auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out[1]);
+
+ // Check handles inside isl0
+ EXPECT_EQ("isl0", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
+ EXPECT_EQ("isl0", gm.metadata(tmp2_nh).get<cv::gimpl::Island>().island);
+ EXPECT_EQ("isl0", gm.metadata(scl_nh).get<cv::gimpl::Island>().island);
+
+ // Check handles inside isl1
+ EXPECT_EQ("isl1", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
+ EXPECT_EQ("isl1", gm.metadata(tmp3_nh).get<cv::gimpl::Island>().island);
+
+ // Check outside handles
+ EXPECT_FALSE(gm.metadata(in0_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(in1_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
+}
+
+TEST_F(ComplexIslands, OnlyOperationsAssignedToIslands)
+{
+ cv::gapi::island("isl0", cv::GIn(in[1]), cv::GOut(tmp[1]));
+ cv::gapi::island("isl1", cv::GIn(tmp[1]), cv::GOut(scl));
+ cv::gapi::island("isl2", cv::GIn(scl, tmp[2]), cv::GOut(out[0]));
+ cv::gapi::island("isl3", cv::GIn(in[0]), cv::GOut(tmp[0]));
+ cv::gapi::island("isl4", cv::GIn(tmp[0], tmp[1]), cv::GOut(tmp[2]));
+ cv::gapi::island("isl5", cv::GIn(tmp[1]), cv::GOut(tmp[3]));
+ cv::gapi::island("isl6", cv::GIn(tmp[3]), cv::GOut(out[1]));
+
+ auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
+ .compile(cv::GMatDesc{CV_8U,1,{640,480}},
+ cv::GMatDesc{CV_8U,1,{640,480}});
+
+ const auto &gm = cc.priv().model();
+ //FIXME: Check that operation handles are really assigned to isl0..isl6
+ const auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
+ const auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
+ const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
+ const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
+ const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
+ const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
+ const auto scl_nh = cv::gimpl::GModel::dataNodeOf(gm, scl);
+ const auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out[0]);
+ const auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out[1]);
+
+ EXPECT_FALSE(gm.metadata(in0_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(in1_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp0_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp1_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp2_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp3_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(scl_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
+}
+
+namespace
+{
+ struct IslandStructureWithGArray
+ {
+ GIntArray in, out;
+ GMat tmp;
+
+ IslandStructureWithGArray()
+ {
+ tmp = CreateMatWithDiag::on(in);
+ out = Mat2Array::on(tmp);
+ }
+ };
+
+ struct IslandsWithGArray: public ::testing::Test, public IslandStructureWithGArray {};
+} // namespace
+
+TEST_F(IslandsWithGArray, IslandWithGArrayAsInput)
+{
+ cv::gapi::island("isl0", cv::GIn(in), cv::GOut(tmp));
+
+ const auto pkg = cv::gapi::kernels<CreateMatWithDiagImpl, Mat2ArrayImpl>();
+ auto cc = cv::GComputation(cv::GIn(in), GOut(out)).compile(cv::empty_array_desc(), cv::compile_args(pkg));
+ const auto &gm = cc.priv().model();
+
+ const auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in.strip());
+ const auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out.strip());
+ const auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
+ GAPI_Assert(tmp_nh->inNodes().size() == 1);
+ const auto create_diag_mat_nh = tmp_nh->inNodes().front();
+
+ EXPECT_EQ("isl0", gm.metadata(create_diag_mat_nh).get<cv::gimpl::Island>().island);
+ EXPECT_FALSE(gm.metadata(in_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp_nh) .contains<cv::gimpl::Island>());
+}
+
+TEST_F(IslandsWithGArray, IslandWithGArrayAsOutput)
+{
+ cv::gapi::island("isl0", cv::GIn(tmp), cv::GOut(out));
+
+ const auto pkg = cv::gapi::kernels<CreateMatWithDiagImpl, Mat2ArrayImpl>();
+ auto cc = cv::GComputation(cv::GIn(in), GOut(out)).compile(cv::empty_array_desc(), cv::compile_args(pkg));
+ const auto &gm = cc.priv().model();
+
+ const auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in.strip());
+ const auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out.strip());
+ const auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
+ GAPI_Assert(tmp_nh->inNodes().size() == 1);
+ const auto mat2array_nh = out_nh->inNodes().front();
+
+ EXPECT_EQ("isl0", gm.metadata(mat2array_nh).get<cv::gimpl::Island>().island);
+ EXPECT_FALSE(gm.metadata(in_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(out_nh) .contains<cv::gimpl::Island>());
+ EXPECT_FALSE(gm.metadata(tmp_nh) .contains<cv::gimpl::Island>());
+}
+////////////////////////////////////////////////////////////////////////////////
+// Wrong input tests on island name
+//
+namespace
+{
+ struct CheckName : public TestWithParam<std::tuple<bool, const char*> >,
+ public PlainIslandsFixture
+ {
+ void assignIsland(const std::string &s)
+ {
+ cv::gapi::island(s, cv::GIn(tmp[0]), cv::GOut(tmp[2]));
+ };
+ };
+ TEST_P(CheckName, Test)
+ {
+ bool correct = false;
+ const char *name = "";
+ std::tie(correct, name) = GetParam();
+ if (correct) EXPECT_NO_THROW(assignIsland(name));
+ else EXPECT_ANY_THROW(assignIsland(name));
+ }
+} // namespace
+INSTANTIATE_TEST_CASE_P(IslandName, CheckName,
+ Values(std::make_tuple(true, "name"),
+ std::make_tuple(true, " name "),
+ std::make_tuple(true, " n a m e "),
+ std::make_tuple(true, " 123 $$ %%"),
+ std::make_tuple(true, ".: -"),
+ std::make_tuple(false, ""),
+ std::make_tuple(false, " "),
+ std::make_tuple(false, " \t "),
+ std::make_tuple(false, " \t \t ")));
+
+// FIXME: add <internal> test on unrollExpr() use for islands
+
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_recompilation_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_recompilation_test.cpp
new file mode 100644
index 000000000..252af9c1a
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_recompilation_test.cpp
@@ -0,0 +1,233 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "api/gcomputation_priv.hpp"
+
+#include "opencv2/gapi/fluid/gfluidkernel.hpp"
+#include "opencv2/gapi/fluid/core.hpp"
+#include "opencv2/gapi/fluid/imgproc.hpp"
+
+namespace opencv_test
+{
+
+TEST(GComputationCompile, NoRecompileWithSameMeta)
+{
+ cv::GMat in;
+ cv::GComputation cc(in, in+in);
+
+ cv::Mat in_mat1 = cv::Mat::eye (32, 32, CV_8UC1);
+ cv::Mat in_mat2 = cv::Mat::zeros(32, 32, CV_8UC1);
+ cv::Mat out_mat;
+
+ cc.apply(in_mat1, out_mat);
+ auto comp1 = cc.priv().m_lastCompiled;
+
+ cc.apply(in_mat2, out_mat);
+ auto comp2 = cc.priv().m_lastCompiled;
+
+ // Both compiled objects are actually the same unique executable
+ EXPECT_EQ(&comp1.priv(), &comp2.priv());
+}
+
+TEST(GComputationCompile, NoRecompileWithWrongMeta)
+{
+ cv::GMat in;
+ cv::GComputation cc(in, in+in);
+
+ cv::Mat in_mat1 = cv::Mat::eye (32, 32, CV_8UC1);
+ cv::Mat in_mat2 = cv::Mat::zeros(32, 32, CV_8UC1);
+ cv::Mat out_mat;
+
+ cc.apply(in_mat1, out_mat);
+ auto comp1 = cc.priv().m_lastCompiled;
+
+ EXPECT_THROW(cc.apply(cv::gin(cv::Scalar(128)), cv::gout(out_mat)), std::logic_error);
+ auto comp2 = cc.priv().m_lastCompiled;
+
+ // Both compiled objects are actually the same unique executable
+ EXPECT_EQ(&comp1.priv(), &comp2.priv());
+}
+
+TEST(GComputationCompile, RecompileWithDifferentMeta)
+{
+ cv::GMat in;
+ cv::GComputation cc(in, in+in);
+
+ cv::Mat in_mat1 = cv::Mat::eye (32, 32, CV_8UC1);
+ cv::Mat in_mat2 = cv::Mat::zeros(64, 64, CV_32F);
+ cv::Mat out_mat;
+
+ cc.apply(in_mat1, out_mat);
+ auto comp1 = cc.priv().m_lastCompiled;
+
+ cc.apply(in_mat2, out_mat);
+ auto comp2 = cc.priv().m_lastCompiled;
+
+ // Both compiled objects are different
+ EXPECT_NE(&comp1.priv(), &comp2.priv());
+}
+
+TEST(GComputationCompile, FluidReshapeWithDifferentDims)
+{
+ cv::GMat in;
+ cv::GComputation cc(in, in+in);
+
+ cv::Mat in_mat1 = cv::Mat::eye (32, 32, CV_8UC1);
+ cv::Mat in_mat2 = cv::Mat::zeros(64, 64, CV_8UC1);
+ cv::Mat out_mat;
+
+ cc.apply(in_mat1, out_mat, cv::compile_args(cv::gapi::core::fluid::kernels()));
+ auto comp1 = cc.priv().m_lastCompiled;
+
+ cc.apply(in_mat2, out_mat);
+ auto comp2 = cc.priv().m_lastCompiled;
+
+ // Both compiled objects are actually the same unique executable
+ EXPECT_EQ(&comp1.priv(), &comp2.priv());
+}
+
+TEST(GComputationCompile, FluidReshapeResizeDownScale)
+{
+ cv::Size szOut(4, 4);
+ cv::GMat in;
+ cv::GComputation cc(in, cv::gapi::resize(in, szOut));
+
+ cv::Mat in_mat1( 8, 8, CV_8UC3);
+ cv::Mat in_mat2(16, 16, CV_8UC3);
+ cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::Mat out_mat1, out_mat2;
+
+ cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::core::fluid::kernels()));
+ auto comp1 = cc.priv().m_lastCompiled;
+
+ cc.apply(in_mat2, out_mat2);
+ auto comp2 = cc.priv().m_lastCompiled;
+
+ // Both compiled objects are actually the same unique executable
+ EXPECT_EQ(&comp1.priv(), &comp2.priv());
+
+ cv::Mat cv_out_mat1, cv_out_mat2;
+ cv::resize(in_mat1, cv_out_mat1, szOut);
+ cv::resize(in_mat2, cv_out_mat2, szOut);
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat1 != cv_out_mat1));
+ EXPECT_EQ(0, cv::countNonZero(out_mat2 != cv_out_mat2));
+}
+
+TEST(GComputationCompile, FluidReshapeSwitchToUpscaleFromDownscale)
+{
+ cv::Size szOut(4, 4);
+ cv::GMat in;
+ cv::GComputation cc(in, cv::gapi::resize(in, szOut));
+
+ cv::Mat in_mat1( 8, 8, CV_8UC3);
+ cv::Mat in_mat2( 2, 2, CV_8UC3);
+ cv::Mat in_mat3(16, 16, CV_8UC3);
+ cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::randu(in_mat3, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::Mat out_mat1, out_mat2, out_mat3;
+
+ cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::core::fluid::kernels()));
+ auto comp1 = cc.priv().m_lastCompiled;
+
+ cc.apply(in_mat2, out_mat2);
+ auto comp2 = cc.priv().m_lastCompiled;
+
+ cc.apply(in_mat3, out_mat3);
+ auto comp3 = cc.priv().m_lastCompiled;
+
+ EXPECT_EQ(&comp1.priv(), &comp2.priv());
+ EXPECT_EQ(&comp1.priv(), &comp3.priv());
+
+ cv::Mat cv_out_mat1, cv_out_mat2, cv_out_mat3;
+ cv::resize(in_mat1, cv_out_mat1, szOut);
+ cv::resize(in_mat2, cv_out_mat2, szOut);
+ cv::resize(in_mat3, cv_out_mat3, szOut);
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat1 != cv_out_mat1));
+ EXPECT_EQ(0, cv::countNonZero(out_mat2 != cv_out_mat2));
+ EXPECT_EQ(0, cv::countNonZero(out_mat3 != cv_out_mat3));
+}
+
+TEST(GComputationCompile, ReshapeBlur)
+{
+ cv::Size kernelSize{3, 3};
+ cv::GMat in;
+ cv::GComputation cc(in, cv::gapi::blur(in, kernelSize));
+
+ cv::Mat in_mat1( 8, 8, CV_8UC1);
+ cv::Mat in_mat2(16, 16, CV_8UC1);
+ cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
+ cv::Mat out_mat1, out_mat2;
+
+ cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::imgproc::fluid::kernels()));
+ auto comp1 = cc.priv().m_lastCompiled;
+
+ cc.apply(in_mat2, out_mat2);
+ auto comp2 = cc.priv().m_lastCompiled;
+
+ // Both compiled objects are actually the same unique executable
+ EXPECT_EQ(&comp1.priv(), &comp2.priv());
+
+ cv::Mat cv_out_mat1, cv_out_mat2;
+ cv::blur(in_mat1, cv_out_mat1, kernelSize);
+ cv::blur(in_mat2, cv_out_mat2, kernelSize);
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat1 != cv_out_mat1));
+ EXPECT_EQ(0, cv::countNonZero(out_mat2 != cv_out_mat2));
+}
+
+TEST(GComputationCompile, ReshapeRois)
+{
+ cv::Size kernelSize{3, 3};
+ cv::Size szOut(8, 8);
+ cv::GMat in;
+ auto blurred = cv::gapi::blur(in, kernelSize);
+ cv::GComputation cc(in, cv::gapi::resize(blurred, szOut));
+
+ cv::Mat first_in_mat(8, 8, CV_8UC3);
+ cv::randn(first_in_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));
+ cv::Mat first_out_mat;
+ auto fluidKernels = cv::gapi::combine(gapi::imgproc::fluid::kernels(),
+ gapi::core::fluid::kernels(),
+ cv::unite_policy::REPLACE);
+ cc.apply(first_in_mat, first_out_mat, cv::compile_args(fluidKernels));
+ auto first_comp = cc.priv().m_lastCompiled;
+
+ constexpr int niter = 4;
+ for (int i = 0; i < niter; i++)
+ {
+ int width = 4 + 2*i;
+ int height = width;
+ cv::Mat in_mat(width, height, CV_8UC3);
+ cv::randn(in_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));
+ cv::Mat out_mat = cv::Mat::zeros(szOut, CV_8UC3);
+
+ int x = 0;
+ int y = szOut.height * i / niter;
+ int roiW = szOut.width;
+ int roiH = szOut.height / niter;
+ cv::Rect roi{x, y, roiW, roiH};
+
+ cc.apply(in_mat, out_mat, cv::compile_args(cv::GFluidOutputRois{{to_own(roi)}}));
+ auto comp = cc.priv().m_lastCompiled;
+
+ EXPECT_EQ(&first_comp.priv(), &comp.priv());
+
+ cv::Mat blur_mat, cv_out_mat;
+ cv::blur(in_mat, blur_mat, kernelSize);
+ cv::resize(blur_mat, cv_out_mat, szOut);
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat(roi) != cv_out_mat(roi)));
+ }
+}
+
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_resolve_kernel_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_resolve_kernel_test.cpp
new file mode 100644
index 000000000..d4b16f627
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_resolve_kernel_test.cpp
@@ -0,0 +1,119 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+#include "gapi_mock_kernels.hpp"
+
+namespace opencv_test
+{
+
+TEST(Lookup, CreateOrder)
+{
+ const auto order = cv::gapi::lookup_order({Jupiter::backend(),
+ Saturn::backend()});
+ EXPECT_EQ(2u, order.size());
+ EXPECT_EQ(Jupiter::backend(), order[0]);
+ EXPECT_EQ(Saturn ::backend(), order[1]);
+}
+
+TEST(Lookup, NoOrder)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz,
+ S::Foo, S::Bar, S::Baz>();
+
+ EXPECT_NO_THROW (pkg.lookup<I::Foo>());
+ EXPECT_NO_THROW (pkg.lookup<I::Bar>());
+ EXPECT_NO_THROW (pkg.lookup<I::Baz>());
+ EXPECT_ANY_THROW(pkg.lookup<I::Qux>());
+}
+
+TEST(Lookup, Only_Jupiter)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz,
+ S::Foo, S::Bar, S::Baz>();
+
+ auto order = cv::gapi::lookup_order({J::backend()});
+
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Foo>(order));
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Bar>(order));
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Baz>(order));
+ EXPECT_ANY_THROW(pkg.lookup<I::Qux>(order));
+}
+
+TEST(Lookup, Only_Saturn)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz,
+ S::Foo, S::Bar, S::Baz>();
+
+ auto order = cv::gapi::lookup_order({S::backend()});
+
+ EXPECT_EQ(S::backend(), pkg.lookup<I::Foo>(order));
+ EXPECT_EQ(S::backend(), pkg.lookup<I::Bar>(order));
+ EXPECT_EQ(S::backend(), pkg.lookup<I::Baz>(order));
+ EXPECT_ANY_THROW(pkg.lookup<I::Qux>(order));
+}
+
+TEST(Lookup, With_Order)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz,
+ S::Foo, S::Bar, S::Baz>();
+
+ auto prefer_j = cv::gapi::lookup_order({J::backend(), S::backend()});
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Foo>(prefer_j));
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Bar>(prefer_j));
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Baz>(prefer_j));
+ EXPECT_ANY_THROW(pkg.lookup<I::Qux>(prefer_j));
+
+ auto prefer_s = cv::gapi::lookup_order({S::backend(), J::backend()});
+ EXPECT_EQ(S::backend(), pkg.lookup<I::Foo>(prefer_s));
+ EXPECT_EQ(S::backend(), pkg.lookup<I::Bar>(prefer_s));
+ EXPECT_EQ(S::backend(), pkg.lookup<I::Baz>(prefer_s));
+ EXPECT_ANY_THROW(pkg.lookup<I::Qux>(prefer_s));
+}
+
+TEST(Lookup, NoOverlap)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, S::Baz, S::Qux>();
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Foo>());
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Bar>());
+ EXPECT_EQ(S::backend(), pkg.lookup<I::Baz>());
+ EXPECT_EQ(S::backend(), pkg.lookup<I::Qux>());
+}
+
+TEST(Lookup, ExtraBackend)
+{
+ namespace J = Jupiter;
+ namespace S = Saturn;
+ const auto pkg = cv::gapi::kernels<J::Foo, J::Bar, J::Baz>();
+
+ // Even if pkg doesn't contain S kernels while S is preferable,
+ // it should work.
+ const auto prefer_sj = cv::gapi::lookup_order({S::backend(), J::backend()});
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Foo>(prefer_sj));
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Bar>(prefer_sj));
+ EXPECT_EQ(J::backend(), pkg.lookup<I::Baz>(prefer_sj));
+
+ // If search scope is limited to S only, neither J nor S kernels
+ // shouldn't be found
+ const auto only_s = cv::gapi::lookup_order({S::backend()});
+ EXPECT_ANY_THROW(pkg.lookup<I::Foo>(only_s));
+ EXPECT_ANY_THROW(pkg.lookup<I::Bar>(only_s));
+ EXPECT_ANY_THROW(pkg.lookup<I::Baz>(only_s));
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_vectorref_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_vectorref_test.cpp
new file mode 100644
index 000000000..1b14e0670
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_int_vectorref_test.cpp
@@ -0,0 +1,207 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+
+namespace opencv_test
+{
+
+typedef ::testing::Types<int, cv::Point, cv::Rect> VectorRef_Test_Types;
+
+template<typename T> struct VectorRefT: public ::testing::Test { using Type = T; };
+
+TYPED_TEST_CASE(VectorRefT, VectorRef_Test_Types);
+
+TYPED_TEST(VectorRefT, Reset_Valid)
+{
+ using T = typename TestFixture::Type;
+ cv::detail::VectorRefT<T> ref; // vector ref created empty
+ EXPECT_NO_THROW(ref.reset()); // 1st reset is OK (initializes)
+ EXPECT_NO_THROW(ref.reset()); // 2nd reset is also OK (resets)
+}
+
+TYPED_TEST(VectorRefT, Reset_Invalid)
+{
+ using T = typename TestFixture::Type;
+ std::vector<T> vec(42); // create a std::vector of 42 elements
+ cv::detail::VectorRefT<T> ref(vec); // RO_EXT (since reference is const)
+ EXPECT_ANY_THROW(ref.reset()); // data-bound vector ref can't be reset
+}
+
+TYPED_TEST(VectorRefT, ReadRef_External)
+{
+ using T = typename TestFixture::Type;
+ const std::vector<T> vec(42); // create a std::vector of 42 elements
+ cv::detail::VectorRefT<T> ref(vec); // RO_EXT (since reference is const)
+ auto &vref = ref.rref();
+ EXPECT_EQ(vec.data(), vref.data());
+ EXPECT_EQ(vec.size(), vref.size());
+}
+
+TYPED_TEST(VectorRefT, ReadRef_Internal)
+{
+ using T = typename TestFixture::Type;
+ cv::detail::VectorRefT<T> ref;
+ ref.reset(); // RW_OWN (reset on empty ref)
+ auto &vref = ref.rref(); // read access is valid for RW_OWN
+ EXPECT_EQ(0u, vref.size()); // by default vector is empty
+}
+
+TYPED_TEST(VectorRefT, WriteRef_External)
+{
+ using T = typename TestFixture::Type;
+ std::vector<T> vec(42); // create a std::vector of 42 elements
+ cv::detail::VectorRefT<T> ref(vec); // RW_EXT (since reference is not const)
+ auto &vref = ref.wref(); // write access is valid with RW_EXT
+ EXPECT_EQ(vec.data(), vref.data());
+ EXPECT_EQ(vec.size(), vref.size());
+}
+
+TYPED_TEST(VectorRefT, WriteRef_Internal)
+{
+ using T = typename TestFixture::Type;
+ cv::detail::VectorRefT<T> ref;
+ ref.reset(); // RW_OWN (reset on empty ref)
+ auto &vref = ref.wref(); // write access is valid for RW_OWN
+ EXPECT_EQ(0u, vref.size()); // empty vector by default
+}
+
+TYPED_TEST(VectorRefT, WriteToRO)
+{
+ using T = typename TestFixture::Type;
+ const std::vector<T> vec(42); // create a std::vector of 42 elements
+ cv::detail::VectorRefT<T> ref(vec); // RO_EXT (since reference is const)
+ EXPECT_ANY_THROW(ref.wref());
+}
+
+TYPED_TEST(VectorRefT, ReadAfterWrite)
+{
+ using T = typename TestFixture::Type;
+ std::vector<T> vec; // Initial data holder (empty vector)
+ cv::detail::VectorRefT<T> writer(vec); // RW_EXT
+
+ const auto& ro_ref = vec;
+ cv::detail::VectorRefT<T> reader(ro_ref); // RO_EXT
+
+ EXPECT_EQ(0u, writer.wref().size()); // Check the initial state
+ EXPECT_EQ(0u, reader.rref().size());
+
+ writer.wref().emplace_back(); // Check that write is successfull
+ EXPECT_EQ(1u, writer.wref().size());
+
+ EXPECT_EQ(1u, vec.size()); // Check that changes are reflected to the original container
+ EXPECT_EQ(1u, reader.rref().size()); // Check that changes are reflected to reader's view
+
+ EXPECT_EQ(T(), vec.at(0)); // Check the value (must be default-initialized)
+ EXPECT_EQ(T(), reader.rref().at(0));
+ EXPECT_EQ(T(), writer.wref().at(0));
+}
+
+template<typename T> struct VectorRefU: public ::testing::Test { using Type = T; };
+
+TYPED_TEST_CASE(VectorRefU, VectorRef_Test_Types);
+
+template<class T> struct custom_struct { T a; T b; };
+
+TYPED_TEST(VectorRefU, Reset_Valid)
+{
+ using T = typename TestFixture::Type;
+ cv::detail::VectorRef ref; // vector ref created empty
+ EXPECT_NO_THROW(ref.reset<T>()); // 1st reset is OK (initializes)
+ EXPECT_NO_THROW(ref.reset<T>()); // 2nd reset is also OK (resets)
+
+ EXPECT_ANY_THROW(ref.reset<custom_struct<T> >()); // type change is not allowed
+}
+
+TYPED_TEST(VectorRefU, Reset_Invalid)
+{
+ using T = typename TestFixture::Type;
+ std::vector<T> vec(42); // create a std::vector of 42 elements
+ cv::detail::VectorRef ref(vec); // RO_EXT (since reference is const)
+ EXPECT_ANY_THROW(ref.reset<T>()); // data-bound vector ref can't be reset
+}
+
+TYPED_TEST(VectorRefU, ReadRef_External)
+{
+ using T = typename TestFixture::Type;
+ const std::vector<T> vec(42); // create a std::vector of 42 elements
+ cv::detail::VectorRef ref(vec); // RO_EXT (since reference is const)
+ auto &vref = ref.rref<T>();
+ EXPECT_EQ(vec.data(), vref.data());
+ EXPECT_EQ(vec.size(), vref.size());
+}
+
+TYPED_TEST(VectorRefU, ReadRef_Internal)
+{
+ using T = typename TestFixture::Type;
+ cv::detail::VectorRef ref;
+ ref.reset<T>(); // RW_OWN (reset on empty ref)
+ auto &vref = ref.rref<T>(); // read access is valid for RW_OWN
+ EXPECT_EQ(0u, vref.size()); // by default vector is empty
+}
+
+TYPED_TEST(VectorRefU, WriteRef_External)
+{
+ using T = typename TestFixture::Type;
+ std::vector<T> vec(42); // create a std::vector of 42 elements
+ cv::detail::VectorRef ref(vec); // RW_EXT (since reference is not const)
+ auto &vref = ref.wref<T>(); // write access is valid with RW_EXT
+ EXPECT_EQ(vec.data(), vref.data());
+ EXPECT_EQ(vec.size(), vref.size());
+}
+
+TYPED_TEST(VectorRefU, WriteRef_Internal)
+{
+ using T = typename TestFixture::Type;
+ cv::detail::VectorRef ref;
+ ref.reset<T>(); // RW_OWN (reset on empty ref)
+ auto &vref = ref.wref<T>(); // write access is valid for RW_OWN
+ EXPECT_EQ(0u, vref.size()); // empty vector by default
+}
+
+TYPED_TEST(VectorRefU, WriteToRO)
+{
+ using T = typename TestFixture::Type;
+ const std::vector<T> vec(42); // create a std::vector of 42 elements
+ cv::detail::VectorRef ref(vec); // RO_EXT (since reference is const)
+ EXPECT_ANY_THROW(ref.wref<T>());
+}
+
+TYPED_TEST(VectorRefU, ReadAfterWrite)
+{
+ using T = typename TestFixture::Type;
+ std::vector<T> vec; // Initial data holder (empty vector)
+ cv::detail::VectorRef writer(vec); // RW_EXT
+
+ const auto& ro_ref = vec;
+ cv::detail::VectorRef reader(ro_ref); // RO_EXT
+
+ EXPECT_EQ(0u, writer.wref<T>().size()); // Check the initial state
+ EXPECT_EQ(0u, reader.rref<T>().size());
+
+ writer.wref<T>().emplace_back(); // Check that write is successfull
+ EXPECT_EQ(1u, writer.wref<T>().size());
+
+ EXPECT_EQ(1u, vec.size()); // Check that changes are reflected to the original container
+ EXPECT_EQ(1u, reader.rref<T>().size()); // Check that changes are reflected to reader's view
+
+ EXPECT_EQ(T(), vec.at(0)); // Check the value (must be default-initialized)
+ EXPECT_EQ(T(), reader.rref<T>().at(0));
+ EXPECT_EQ(T(), writer.wref<T>().at(0));
+}
+
+TEST(VectorRefU, TypeCheck)
+{
+ cv::detail::VectorRef ref;
+ ref.reset<int>(); // RW_OWN
+
+ EXPECT_ANY_THROW(ref.reset<char>());
+ EXPECT_ANY_THROW(ref.rref<char>());
+ EXPECT_ANY_THROW(ref.wref<char>());
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_transactions_test.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_transactions_test.cpp
new file mode 100644
index 000000000..f550340e8
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/internal/gapi_transactions_test.cpp
@@ -0,0 +1,222 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include <ade/graph.hpp>
+#include "compiler/transactions.hpp"
+
+namespace opencv_test
+{
+namespace
+{
+
+bool contains(const ade::Graph& graph, const ade::NodeHandle& node)
+{
+ auto nodes = graph.nodes();
+ return nodes.end() != std::find(nodes.begin(), nodes.end(), node);
+}
+
+bool connected(const ade::NodeHandle& src_node, const ade::NodeHandle& dst_node)
+{
+ auto nodes = src_node->outNodes();
+ return nodes.end() != std::find(nodes.begin(), nodes.end(), dst_node);
+}
+
+struct SimpleGraph
+{
+ // ehs[0] ehs[1] ehs[2] ehs[3]
+ // nhs[0] -- > nhs[1] --> nhs[2] --> nhs[3] --> nhs[4]
+
+ enum { node_nums = 5 };
+ ade::Graph graph;
+ ade::NodeHandle fused_nh; /* For check that fusion node is connected to the
+ inputs of the prod and the outputs of the cons */
+ std::array<ade::NodeHandle, node_nums> nhs;
+ std::array<ade::EdgeHandle, node_nums - 1> ehs;
+ Change::List changes;
+
+ SimpleGraph()
+ {
+ nhs[0] = graph.createNode();
+ for (int i = 1; i < node_nums; ++i)
+ {
+ nhs[i ] = graph.createNode();
+ ehs[i - 1] = graph.link(nhs[i - 1], nhs[i]);
+ }
+ }
+
+ void fuse()
+ {
+ // nhs[0] --> fused_nh --> nhs[4]
+
+ fused_nh = graph.createNode();
+ changes.enqueue<Change::NodeCreated>(fused_nh);
+ changes.enqueue<Change::NewLink> (graph, nhs[0], fused_nh);
+ changes.enqueue<Change::DropLink>(graph, nhs[1], ehs[0]);
+ changes.enqueue<Change::NewLink> (graph, fused_nh, nhs[4]);
+ changes.enqueue<Change::DropLink>(graph, nhs[3], ehs[3]);
+ changes.enqueue<Change::DropLink>(graph, nhs[1], ehs[1]);
+ changes.enqueue<Change::DropLink>(graph, nhs[2], ehs[2]);
+ changes.enqueue<Change::DropNode>(nhs[1]);
+ changes.enqueue<Change::DropNode>(nhs[2]);
+ changes.enqueue<Change::DropNode>(nhs[3]);
+ }
+
+ void commit() { changes.commit(graph); }
+ void rollback() { changes.rollback(graph); }
+
+};
+
+struct Transactions: public ::testing::Test, public SimpleGraph {};
+
+} // anonymous namespace
+
+TEST_F(Transactions, NodeCreated_Create)
+{
+ auto new_nh = graph.createNode();
+ Change::NodeCreated node_created(new_nh);
+
+ EXPECT_EQ(6u, static_cast<std::size_t>(graph.nodes().size()));
+ EXPECT_TRUE(contains(graph, new_nh));
+}
+
+TEST_F(Transactions, NodeCreated_RollBack)
+{
+ auto new_nh = graph.createNode();
+ Change::NodeCreated node_created(new_nh);
+
+ node_created.rollback(graph);
+
+ EXPECT_EQ(5u, static_cast<std::size_t>(graph.nodes().size()));
+ EXPECT_FALSE(contains(graph, new_nh));
+}
+
+TEST_F(Transactions, NodeCreated_Commit)
+{
+ auto new_nh = graph.createNode();
+ Change::NodeCreated node_created(new_nh);
+
+ node_created.commit(graph);
+
+ EXPECT_EQ(6u, static_cast<std::size_t>(graph.nodes().size()));
+ EXPECT_TRUE(contains(graph, new_nh));
+}
+
+TEST_F(Transactions, DropLink_Create)
+{
+ Change::DropLink drop_link(graph, nhs[0], ehs[0]);
+
+ EXPECT_FALSE(connected(nhs[0], nhs[1]));
+}
+
+TEST_F(Transactions, DropLink_RollBack)
+{
+ Change::DropLink drop_link(graph, nhs[0], ehs[0]);
+
+ drop_link.rollback(graph);
+
+ EXPECT_TRUE(connected(nhs[0], nhs[1]));
+}
+
+TEST_F(Transactions, DropLink_Commit)
+{
+ Change::DropLink drop_link(graph, nhs[0], ehs[0]);
+
+ drop_link.commit(graph);
+
+ EXPECT_FALSE(connected(nhs[0], nhs[1]));
+}
+
+TEST_F(Transactions, NewLink_Create)
+{
+ auto new_nh = graph.createNode();
+ Change::NewLink new_link(graph, new_nh, nhs[0]);
+
+ EXPECT_TRUE(connected(new_nh, nhs[0]));
+}
+
+TEST_F(Transactions, NewLink_RollBack)
+{
+ auto new_nh = graph.createNode();
+ Change::NewLink new_link(graph, new_nh, nhs[0]);
+
+ new_link.rollback(graph);
+
+ EXPECT_FALSE(connected(new_nh, nhs[0]));
+}
+
+TEST_F(Transactions, NewLink_Commit)
+{
+ auto new_nh = graph.createNode();
+ Change::NewLink new_link(graph, new_nh, nhs[0]);
+
+ new_link.commit(graph);
+
+ EXPECT_TRUE(connected(new_nh, nhs[0]));
+}
+
+TEST_F(Transactions, DropNode_Create)
+{
+ auto new_nh = graph.createNode();
+ Change::DropNode drop_node(new_nh);
+
+ EXPECT_EQ(6u, static_cast<std::size_t>(graph.nodes().size()));
+ EXPECT_TRUE(contains(graph, new_nh));
+}
+
+TEST_F(Transactions, DropNode_RollBack)
+{
+ auto new_nh = graph.createNode();
+ Change::DropNode drop_node(new_nh);
+
+ drop_node.rollback(graph);
+
+ EXPECT_EQ(6u, static_cast<std::size_t>(graph.nodes().size()));
+ EXPECT_TRUE(contains(graph, new_nh));
+}
+
+TEST_F(Transactions, DropNode_Commit)
+{
+ auto new_nh = graph.createNode();
+ Change::DropNode drop_node(new_nh);
+
+ drop_node.commit(graph);
+
+ EXPECT_EQ(5u, static_cast<std::size_t>(graph.nodes().size()));
+ EXPECT_FALSE(contains(graph, new_nh));
+}
+
+TEST_F(Transactions, Fusion_Commit)
+{
+ namespace C = Change;
+
+ fuse();
+ commit();
+
+ EXPECT_EQ(3u, static_cast<std::size_t>(graph.nodes().size()));
+ EXPECT_TRUE(connected(nhs[0] , fused_nh));
+ EXPECT_TRUE(connected(fused_nh, nhs[4]));
+}
+
+TEST_F(Transactions, Fusion_RollBack)
+{
+ namespace C = Change;
+
+ fuse();
+ rollback();
+
+ EXPECT_EQ(static_cast<std::size_t>(node_nums),
+ static_cast<std::size_t>(graph.nodes().size()));
+ EXPECT_FALSE(contains(graph, fused_nh));
+
+ for (int i = 0; i < static_cast<int>(node_nums) - 1; ++i)
+ {
+ EXPECT_TRUE(connected(nhs[i], nhs[i + 1]));
+ }
+}
+
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/own/gapi_types_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/own/gapi_types_tests.cpp
new file mode 100644
index 000000000..c25435707
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/own/gapi_types_tests.cpp
@@ -0,0 +1,159 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "opencv2/gapi/own/types.hpp"
+
+namespace opencv_test
+{
+
+TEST(Point, CreateEmpty)
+{
+ cv::gapi::own::Point p;
+
+ EXPECT_EQ(0, p.x);
+ EXPECT_EQ(0, p.y);
+}
+
+TEST(Point, CreateWithParams)
+{
+ cv::gapi::own::Point p = {1, 2};
+
+ EXPECT_EQ(1, p.x);
+ EXPECT_EQ(2, p.y);
+}
+
+TEST(Rect, CreateEmpty)
+{
+ cv::gapi::own::Rect r;
+
+ EXPECT_EQ(0, r.x);
+ EXPECT_EQ(0, r.y);
+ EXPECT_EQ(0, r.width);
+ EXPECT_EQ(0, r.height);
+}
+
+TEST(Rect, CreateWithParams)
+{
+ cv::gapi::own::Rect r(1, 2, 3, 4);
+
+ EXPECT_EQ(1, r.x);
+ EXPECT_EQ(2, r.y);
+ EXPECT_EQ(3, r.width);
+ EXPECT_EQ(4, r.height);
+}
+
+TEST(Rect, CompareEqual)
+{
+ cv::gapi::own::Rect r1(1, 2, 3, 4);
+
+ cv::gapi::own::Rect r2(1, 2, 3, 4);
+
+ EXPECT_TRUE(r1 == r2);
+}
+
+TEST(Rect, CompareDefaultEqual)
+{
+ cv::gapi::own::Rect r1;
+
+ cv::gapi::own::Rect r2;
+
+ EXPECT_TRUE(r1 == r2);
+}
+
+TEST(Rect, CompareNotEqual)
+{
+ cv::gapi::own::Rect r1(1, 2, 3, 4);
+
+ cv::gapi::own::Rect r2;
+
+ EXPECT_TRUE(r1 != r2);
+}
+
+TEST(Rect, Intersection)
+{
+ cv::gapi::own::Rect r1(2, 2, 3, 3);
+ cv::gapi::own::Rect r2(3, 1, 3, 3);
+
+ cv::gapi::own::Rect intersect = r1 & r2;
+
+ EXPECT_EQ(3, intersect.x);
+ EXPECT_EQ(2, intersect.y);
+ EXPECT_EQ(2, intersect.width);
+ EXPECT_EQ(2, intersect.height);
+}
+
+TEST(Rect, AssignIntersection)
+{
+ cv::gapi::own::Rect r1(2, 2, 3, 3);
+ cv::gapi::own::Rect r2(3, 1, 3, 3);
+
+ r1 &= r2;
+
+ EXPECT_EQ(3, r1.x);
+ EXPECT_EQ(2, r1.y);
+ EXPECT_EQ(2, r1.width);
+ EXPECT_EQ(2, r1.height);
+}
+
+TEST(Size, CreateEmpty)
+{
+ cv::gapi::own::Size s;
+
+ EXPECT_EQ(0, s.width);
+ EXPECT_EQ(0, s.height);
+}
+
+TEST(Size, CreateWithParams)
+{
+ cv::gapi::own::Size s(640, 480);
+
+ EXPECT_EQ(640, s.width);
+ EXPECT_EQ(480, s.height);
+}
+
+TEST(Size, AdditionAssignment)
+{
+ cv::gapi::own::Size s1(1, 2);
+ cv::gapi::own::Size s2(2, 3);
+
+ s1 += s2;
+
+ EXPECT_EQ(3, s1.width);
+ EXPECT_EQ(5, s1.height);
+}
+
+TEST(Size, CompareEqual)
+{
+ cv::gapi::own::Size s1(1, 2);
+
+ cv::gapi::own::Size s2(1, 2);
+
+ EXPECT_TRUE(s1 == s2);
+ EXPECT_FALSE(s1 != s2);
+}
+
+TEST(Size, CompareDefaultEqual)
+{
+ cv::gapi::own::Size s1;
+ cv::gapi::own::Size s2;
+
+ EXPECT_TRUE(s1 == s2);
+ EXPECT_FALSE(s1 != s2);
+}
+
+TEST(Size, CompareNotEqual)
+{
+ cv::gapi::own::Size s1(1, 2);
+
+ cv::gapi::own::Size s2(3, 4);
+
+ EXPECT_FALSE(s1 == s2);
+ EXPECT_TRUE(s1 != s2);
+}
+
+} // opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/own/mat_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/own/mat_tests.cpp
new file mode 100644
index 000000000..ba2cd2df4
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/own/mat_tests.cpp
@@ -0,0 +1,387 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "opencv2/gapi/own/mat.hpp"
+#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
+
+namespace opencv_test
+{
+using Mat = cv::gapi::own::Mat;
+
+TEST(OwnMat, DefaultConstruction)
+{
+ Mat m;
+ ASSERT_EQ(m.data, nullptr);
+ ASSERT_EQ(m.cols, 0);
+ ASSERT_EQ(m.rows, 0);
+ ASSERT_EQ(m.cols, 0);
+ ASSERT_EQ(m.type(), 0);
+ ASSERT_EQ(m.depth(), 0);
+}
+
+TEST(OwnMat, Create)
+{
+ auto size = cv::gapi::own::Size{32,16};
+ Mat m;
+ m.create(size, CV_8UC1);
+
+ ASSERT_NE(m.data, nullptr);
+ ASSERT_EQ((cv::gapi::own::Size{m.cols, m.rows}), size);
+
+ ASSERT_EQ(m.total(), static_cast<size_t>(size.height*size.width));
+ ASSERT_EQ(m.type(), CV_8UC1);
+ ASSERT_EQ(m.depth(), CV_8U);
+ ASSERT_EQ(m.channels(), 1);
+ ASSERT_EQ(m.elemSize(), sizeof(uint8_t));
+ ASSERT_EQ(m.step, sizeof(uint8_t) * m.cols);
+}
+
+TEST(OwnMat, CreateOverload)
+{
+ auto size = cv::gapi::own::Size{32,16};
+ Mat m;
+ m.create(size.height,size.width, CV_8UC1);
+
+ ASSERT_NE(m.data, nullptr);
+ ASSERT_EQ((cv::Size{m.cols, m.rows}), size);
+
+ ASSERT_EQ(m.total(), static_cast<size_t>(size.height*size.width));
+ ASSERT_EQ(m.type(), CV_8UC1);
+ ASSERT_EQ(m.depth(), CV_8U);
+ ASSERT_EQ(m.channels(), 1);
+ ASSERT_EQ(m.elemSize(), sizeof(uint8_t));
+ ASSERT_EQ(m.step, sizeof(uint8_t) * m.cols);
+}
+TEST(OwnMat, Create3chan)
+{
+ auto size = cv::Size{32,16};
+ Mat m;
+ m.create(size, CV_8UC3);
+
+ ASSERT_NE(m.data, nullptr);
+ ASSERT_EQ((cv::Size{m.cols, m.rows}), size);
+
+ ASSERT_EQ(m.type(), CV_8UC3);
+ ASSERT_EQ(m.depth(), CV_8U);
+ ASSERT_EQ(m.channels(), 3);
+ ASSERT_EQ(m.elemSize(), 3 * sizeof(uint8_t));
+ ASSERT_EQ(m.step, 3* sizeof(uint8_t) * m.cols);
+}
+
+struct NonEmptyMat {
+ cv::gapi::own::Size size{32,16};
+ Mat m;
+ NonEmptyMat() {
+ m.create(size, CV_8UC1);
+ }
+};
+
+struct OwnMatSharedSemantics : NonEmptyMat, ::testing::Test {};
+
+
+namespace {
+ auto state_of = [](Mat const& mat) {
+ return std::make_tuple(
+ mat.data,
+ cv::Size{mat.cols, mat.rows},
+ mat.type(),
+ mat.depth(),
+ mat.channels()
+ );
+ };
+
+ void ensure_mats_are_same(Mat const& copy, Mat const& m){
+ EXPECT_NE(copy.data, nullptr);
+ EXPECT_EQ(state_of(copy), state_of(m));
+ }
+}
+TEST_F(OwnMatSharedSemantics, CopyConstruction)
+{
+ Mat copy(m);
+ ensure_mats_are_same(copy, m);
+}
+
+TEST_F(OwnMatSharedSemantics, CopyAssignment)
+{
+ Mat copy;
+ copy = m;
+ ensure_mats_are_same(copy, m);
+}
+
+struct OwnMatMoveSemantics : NonEmptyMat, ::testing::Test {
+ Mat& moved_from = m;
+ decltype(state_of(moved_from)) initial_state = state_of(moved_from);
+
+ void ensure_state_moved_to(Mat const& moved_to)
+ {
+ EXPECT_EQ(state_of(moved_to), initial_state);
+ EXPECT_EQ(state_of(moved_from), state_of(Mat{}));
+ }
+};
+
+TEST_F(OwnMatMoveSemantics, MoveConstruction)
+{
+ Mat moved_to(std::move(moved_from));
+
+ ensure_state_moved_to(moved_to);
+}
+
+TEST_F(OwnMatMoveSemantics, MoveAssignment)
+{
+ Mat moved_to(std::move(moved_from));
+ ensure_state_moved_to(moved_to);
+}
+
+struct OwnMatNonOwningView : NonEmptyMat, ::testing::Test {
+ decltype(state_of(m)) initial_state = state_of(m);
+
+ void TearDown() override {
+ EXPECT_EQ(state_of(m), initial_state)<<"State of the source matrix changed?";
+ //ASAN should complain here if memory is freed here (e.g. by bug in non owning logic of own::Mat)
+ volatile uchar dummy = m.data[0];
+ cv::util::suppress_unused_warning(dummy);
+ }
+
+};
+
+TEST_F(OwnMatNonOwningView, Construction)
+{
+ Mat non_owning_view(m.rows, m.cols, m.type(), static_cast<void*>(m.data));
+
+ ensure_mats_are_same(non_owning_view, m);
+}
+
+TEST_F(OwnMatNonOwningView, CopyConstruction)
+{
+ Mat non_owning_view{m.rows, m.cols, m.type(), static_cast<void*>(m.data)};
+
+ Mat non_owning_view_copy = non_owning_view;
+ ensure_mats_are_same(non_owning_view_copy, m);
+}
+
+TEST_F(OwnMatNonOwningView, Assignment)
+{
+ Mat non_owning_view{m.rows, m.cols, m.type(), static_cast<void*>(m.data)};
+ Mat non_owning_view_copy;
+
+ non_owning_view_copy = non_owning_view;
+ ensure_mats_are_same(non_owning_view_copy, m);
+}
+
+TEST(OwnMatConversion, WithStep)
+{
+ constexpr int width = 8;
+ constexpr int height = 8;
+ constexpr int stepInPixels = 16;
+
+ std::array<int, height * stepInPixels> data;
+ for (size_t i = 0; i < data.size(); i++)
+ {
+ data[i] = static_cast<int>(i);
+ }
+ cv::Mat cvMat(cv::Size{width, height}, CV_32S, data.data(), stepInPixels * sizeof(int));
+
+ auto ownMat = to_own(cvMat);
+ auto cvMatFromOwn = cv::gapi::own::to_ocv(ownMat);
+
+ EXPECT_EQ(0, cv::countNonZero(cvMat != cvMatFromOwn))
+ << cvMat << std::endl
+ << (cvMat != cvMatFromOwn);
+}
+
+TEST(OwnMat, PtrWithStep)
+{
+ constexpr int width = 8;
+ constexpr int height = 8;
+ constexpr int stepInPixels = 16;
+
+ std::array<int, height * stepInPixels> data;
+ for (size_t i = 0; i < data.size(); i++)
+ {
+ data[i] = static_cast<int>(i);
+ }
+ Mat mat(height, width, CV_32S, data.data(), stepInPixels * sizeof(int));
+
+ EXPECT_EQ(& data[0], reinterpret_cast<int*>(mat.ptr(0)));
+ EXPECT_EQ(& data[1], reinterpret_cast<int*>(mat.ptr(0, 1)));
+ EXPECT_EQ(& data[stepInPixels], reinterpret_cast<int*>(mat.ptr(1)));
+ EXPECT_EQ(& data[stepInPixels +1], reinterpret_cast<int*>(mat.ptr(1,1)));
+
+ auto const& cmat = mat;
+
+ EXPECT_EQ(& data[0], reinterpret_cast<const int*>(cmat.ptr(0)));
+ EXPECT_EQ(& data[1], reinterpret_cast<const int*>(cmat.ptr(0, 1)));
+ EXPECT_EQ(& data[stepInPixels], reinterpret_cast<const int*>(cmat.ptr(1)));
+ EXPECT_EQ(& data[stepInPixels +1], reinterpret_cast<const int*>(cmat.ptr(1,1)));
+}
+
+TEST(OwnMat, CopyToWithStep)
+{
+ constexpr int width = 8;
+ constexpr int height = 8;
+ constexpr int stepInPixels = 16;
+
+ std::array<int, height * stepInPixels> data;
+ for (size_t i = 0; i < data.size(); i++)
+ {
+ data[i] = static_cast<int>(i);
+ }
+ Mat mat(height, width, CV_32S, data.data(), stepInPixels * sizeof(int));
+
+ Mat dst;
+ mat.copyTo(dst);
+
+ EXPECT_NE(mat.data, dst.data);
+ EXPECT_EQ(0, cv::countNonZero(to_ocv(mat) != to_ocv(dst)))
+ << to_ocv(mat) << std::endl
+ << (to_ocv(mat) != to_ocv(dst));
+}
+
+TEST(OwnMat, ScalarAssign32SC1)
+{
+ constexpr int width = 8;
+ constexpr int height = 8;
+ constexpr int stepInPixels = 16;
+
+ std::array<int, height * stepInPixels> data;
+ for (size_t i = 0; i < data.size(); i++)
+ {
+ data[i] = static_cast<int>(i);
+ }
+ Mat mat(height, width, CV_32S, data.data(), stepInPixels * sizeof(data[0]));
+
+ mat = cv::gapi::own::Scalar{-1};
+
+ std::array<int, height * stepInPixels> expected;
+
+ for (size_t row = 0; row < height; row++)
+ {
+ for (size_t col = 0; col < stepInPixels; col++)
+ {
+ auto index = row*stepInPixels + col;
+ expected[index] = col < width ? -1 : static_cast<int>(index);
+ }
+ }
+
+ auto cmp_result_mat = (cv::Mat{height, stepInPixels, CV_32S, data.data()} != cv::Mat{height, stepInPixels, CV_32S, expected.data()});
+ EXPECT_EQ(0, cv::countNonZero(cmp_result_mat))
+ << cmp_result_mat << std::endl;
+}
+
+TEST(OwnMat, ScalarAssign8UC1)
+{
+ constexpr int width = 8;
+ constexpr int height = 8;
+ constexpr int stepInPixels = 16;
+
+ std::array<uchar, height * stepInPixels> data;
+ for (size_t i = 0; i < data.size(); i++)
+ {
+ data[i] = static_cast<uchar>(i);
+ }
+ Mat mat(height, width, CV_8U, data.data(), stepInPixels * sizeof(data[0]));
+
+ mat = cv::gapi::own::Scalar{-1};
+
+ std::array<uchar, height * stepInPixels> expected;
+
+ for (size_t row = 0; row < height; row++)
+ {
+ for (size_t col = 0; col < stepInPixels; col++)
+ {
+ auto index = row*stepInPixels + col;
+ expected[index] = col < width ? cv::saturate_cast<uchar>(-1) : static_cast<uchar>(index);
+ }
+ }
+
+ auto cmp_result_mat = (cv::Mat{height, stepInPixels, CV_8U, data.data()} != cv::Mat{height, stepInPixels, CV_8U, expected.data()});
+ EXPECT_EQ(0, cv::countNonZero(cmp_result_mat))
+ << cmp_result_mat << std::endl;
+}
+
+TEST(OwnMat, ScalarAssign8UC3)
+{
+ constexpr auto cv_type = CV_8SC3;
+ constexpr int channels = 3;
+ constexpr int width = 8;
+ constexpr int height = 8;
+ constexpr int stepInPixels = 16;
+
+ std::array<schar, height * stepInPixels * channels> data;
+ for (size_t i = 0; i < data.size(); i+= channels)
+ {
+ data[i + 0] = static_cast<schar>(10 * i + 0);
+ data[i + 1] = static_cast<schar>(10 * i + 1);
+ data[i + 2] = static_cast<schar>(10 * i + 2);
+ }
+
+ Mat mat(height, width, cv_type, data.data(), channels * stepInPixels * sizeof(data[0]));
+
+ mat = cv::gapi::own::Scalar{-10, -11, -12};
+
+ std::array<schar, data.size()> expected;
+
+ for (size_t row = 0; row < height; row++)
+ {
+ for (size_t col = 0; col < stepInPixels; col++)
+ {
+ int index = static_cast<int>(channels * (row*stepInPixels + col));
+ expected[index + 0] = static_cast<schar>(col < width ? -10 : 10 * index + 0);
+ expected[index + 1] = static_cast<schar>(col < width ? -11 : 10 * index + 1);
+ expected[index + 2] = static_cast<schar>(col < width ? -12 : 10 * index + 2);
+ }
+ }
+
+ auto cmp_result_mat = (cv::Mat{height, stepInPixels, cv_type, data.data()} != cv::Mat{height, stepInPixels, cv_type, expected.data()});
+ EXPECT_EQ(0, cv::countNonZero(cmp_result_mat))
+ << cmp_result_mat << std::endl
+ << "data : " << std::endl
+ << cv::Mat{height, stepInPixels, cv_type, data.data()} << std::endl
+ << "expected : " << std::endl
+ << cv::Mat{height, stepInPixels, cv_type, expected.data()} << std::endl;
+}
+
+TEST(OwnMat, ROIView)
+{
+ constexpr int width = 8;
+ constexpr int height = 8;
+ constexpr int stepInPixels = 16;
+
+ std::array<uchar, height * stepInPixels> data;
+ for (size_t i = 0; i < data.size(); i++)
+ {
+ data[i] = static_cast<uchar>(i);
+ }
+
+
+// std::cout<<cv::Mat{height, stepInPixels, CV_8U, data.data()}<<std::endl;
+
+ std::array<uchar, 4 * 4> expected;
+
+ for (size_t row = 0; row < 4; row++)
+ {
+ for (size_t col = 0; col < 4; col++)
+ {
+ expected[row*4 +col] = static_cast<uchar>(stepInPixels * (2 + row) + 2 + col);
+ }
+ }
+
+ Mat mat(height, width, CV_8U, data.data(), stepInPixels * sizeof(data[0]));
+ Mat roi_view (mat, cv::gapi::own::Rect{2,2,4,4});
+
+// std::cout<<cv::Mat{4, 4, CV_8U, expected.data()}<<std::endl;
+//
+ auto expected_cv_mat = cv::Mat{4, 4, CV_8U, expected.data()};
+
+ auto cmp_result_mat = (to_ocv(roi_view) != expected_cv_mat);
+ EXPECT_EQ(0, cv::countNonZero(cmp_result_mat))
+ << cmp_result_mat << std::endl
+ << to_ocv(roi_view) << std::endl
+ << expected_cv_mat << std::endl;
+}
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/own/scalar_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/own/scalar_tests.cpp
new file mode 100644
index 000000000..a9c5c0123
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/own/scalar_tests.cpp
@@ -0,0 +1,44 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "opencv2/gapi/own/scalar.hpp"
+
+namespace opencv_test
+{
+
+TEST(Scalar, CreateEmpty)
+{
+ cv::gapi::own::Scalar s;
+
+ for (int i = 0; i < 4; ++i)
+ {
+ EXPECT_EQ(s[i], 0.0);
+ }
+}
+
+TEST(Scalar, CreateFromVal)
+{
+ cv::gapi::own::Scalar s(5.0);
+
+ EXPECT_EQ(s[0], 5.0);
+ EXPECT_EQ(s[1], 0.0);
+ EXPECT_EQ(s[2], 0.0);
+ EXPECT_EQ(s[3], 0.0);
+}
+
+TEST(Scalar, CreateFromVals)
+{
+ cv::gapi::own::Scalar s(5.3, 3.3, 4.1, -2.0);
+
+ EXPECT_EQ(s[0], 5.3);
+ EXPECT_EQ(s[1], 3.3);
+ EXPECT_EQ(s[2], 4.1);
+ EXPECT_EQ(s[3], -2.0);
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/test_main.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/test_main.cpp
new file mode 100644
index 000000000..fa5862fa1
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/test_main.cpp
@@ -0,0 +1,12 @@
+// 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) 2018 Intel Corporation
+
+
+// FIXME: OpenCV license header
+
+#include "test_precomp.hpp"
+
+CV_TEST_MAIN("gapi")
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/test_precomp.hpp b/inference-engine/thirdparty/fluid/modules/gapi/test/test_precomp.hpp
new file mode 100644
index 000000000..bcab803ba
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/test_precomp.hpp
@@ -0,0 +1,27 @@
+// 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) 2018 Intel Corporation
+
+
+// FIXME: OpenCV header
+
+#ifndef __OPENCV_GAPI_TEST_PRECOMP_HPP__
+#define __OPENCV_GAPI_TEST_PRECOMP_HPP__
+
+#include <cstdint>
+#include <vector>
+
+#include "opencv2/ts.hpp"
+#include "opencv2/gapi.hpp"
+#include "opencv2/gapi/imgproc.hpp"
+#include "opencv2/gapi/core.hpp"
+#include "opencv2/gapi/cpu/gcpukernel.hpp"
+#include "opencv2/gapi/gpu/ggpukernel.hpp"
+#include "opencv2/gapi/gcompoundkernel.hpp"
+#include "opencv2/gapi/operators.hpp"
+#include "opencv2/gapi/fluid/imgproc.hpp"
+#include "opencv2/gapi/fluid/core.hpp"
+
+#endif // __OPENCV_GAPI_TEST_PRECOMP_HPP__
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/util/any_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/util/any_tests.cpp
new file mode 100644
index 000000000..60bbcc13b
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/util/any_tests.cpp
@@ -0,0 +1,121 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "opencv2/gapi/util/any.hpp"
+
+namespace opencv_test
+{
+
+TEST(Any, basic)
+{
+ using namespace util;
+ any a(8);
+ auto casted_pointer = any_cast<int>(&a);
+ ASSERT_NE(nullptr, casted_pointer);
+ ASSERT_EQ(*casted_pointer, 8);
+
+ *casted_pointer = 7;
+ ASSERT_EQ(any_cast<int>(a), 7);
+}
+
+TEST(Any, any_cast_ref_throws_on_empty)
+{
+ using namespace util;
+ any a;
+
+ ASSERT_THROW(util::any_cast<int>(a), bad_any_cast);
+}
+
+TEST(Any, copy)
+{
+ using namespace util;
+ any a(8);
+
+ ASSERT_EQ(any_cast<int>(a), 8);
+
+ any b (a);
+
+ ASSERT_NE(nullptr, any_cast<int>(&b));
+ ASSERT_EQ(8 , any_cast<int>(b));
+ ASSERT_EQ(8 , any_cast<int>(a));
+}
+
+TEST(Any, copy_empty)
+{
+ using namespace util;
+ any a;
+
+ ASSERT_EQ(nullptr, any_cast<int>(&a));
+
+ any b (a);
+
+ ASSERT_EQ(nullptr, any_cast<int>(&a));
+ ASSERT_EQ(nullptr, any_cast<int>(&b));
+}
+
+TEST(Any, move)
+{
+ using namespace util;
+ any a(8);
+
+ ASSERT_EQ(any_cast<int>(a), 8);
+
+ any b (std::move(a));
+
+ ASSERT_NE(nullptr, any_cast<int>(&b));
+ ASSERT_EQ(8 , any_cast<int>(b));
+ ASSERT_EQ(nullptr, any_cast<int>(&a));
+}
+
+TEST(Any, swap)
+{
+ using namespace util;
+ any a(8);
+ any b(7);
+
+ ASSERT_EQ(7, any_cast<int>(b));
+ ASSERT_EQ(8, any_cast<int>(a));
+
+ swap(a,b);
+
+ ASSERT_EQ(8, any_cast<int>(b));
+ ASSERT_EQ(7, any_cast<int>(a));
+}
+
+TEST(Any, move_assign)
+{
+ using namespace util;
+ any a(8);
+ any b;
+
+ ASSERT_EQ(any_cast<int>(a), 8);
+
+ b = (std::move(a));
+
+ ASSERT_NE(nullptr, any_cast<int>(&b));
+ ASSERT_EQ(8 , any_cast<int>(b));
+ ASSERT_EQ(nullptr, any_cast<int>(&a));
+}
+
+TEST(Any, copy_assign)
+{
+ using namespace util;
+ any a(8);
+ any b;
+
+ ASSERT_EQ(any_cast<int>(a), 8);
+ ASSERT_EQ(nullptr, any_cast<int>(&b));
+
+ b = a;
+
+ ASSERT_NE(nullptr, any_cast<int>(&b));
+ ASSERT_EQ(8 , any_cast<int>(b));
+ ASSERT_EQ(8 , any_cast<int>(a));
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/util/optional_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/util/optional_tests.cpp
new file mode 100644
index 000000000..b7fabd530
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/util/optional_tests.cpp
@@ -0,0 +1,175 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "opencv2/gapi/util/optional.hpp"
+#include <opencv2/gapi/util/compiler_hints.hpp> //suppress_unused_warning
+
+namespace opencv_test
+{
+
+TEST(Optional, EmptyCtor)
+{
+ util::optional<int> o;
+ EXPECT_FALSE(o.has_value());
+ EXPECT_FALSE(static_cast<bool>(o));
+}
+
+TEST(Optional, ValueCTor)
+{
+ util::optional<int> o(42);
+ EXPECT_TRUE(o.has_value());
+ EXPECT_TRUE(static_cast<bool>(o));
+}
+
+TEST(Optional, MoveCtr)
+{
+ util::optional<std::string> os1(std::string("text"));
+ EXPECT_TRUE(os1.has_value());
+
+ util::optional<std::string> os2(std::move(os1));
+ EXPECT_FALSE(os1.has_value());
+ EXPECT_TRUE(os2.has_value());
+ EXPECT_EQ("text", os2.value());
+}
+
+TEST(Optional, EmptyThrows)
+{
+ struct foo { int bar; };
+ util::optional<foo> om;
+ const util::optional<foo> oc;
+
+ int dummy;
+
+ EXPECT_THROW(dummy = om->bar, util::bad_optional_access);
+ EXPECT_THROW(dummy = oc->bar, util::bad_optional_access);
+ cv::util::suppress_unused_warning(dummy);
+ EXPECT_THROW(*om, util::bad_optional_access);
+ EXPECT_THROW(*oc, util::bad_optional_access);
+ EXPECT_THROW(om.value(), util::bad_optional_access);
+ EXPECT_THROW(oc.value(), util::bad_optional_access);
+}
+
+TEST(Optional, ValueNoThrow)
+{
+ struct foo { int bar; };
+ util::optional<foo> om(foo{42});
+ const util::optional<foo> oc(foo{42});
+
+ int dummy;
+ EXPECT_NO_THROW(dummy = om->bar);
+ EXPECT_NO_THROW(dummy = oc->bar);
+ cv::util::suppress_unused_warning(dummy);
+ EXPECT_NO_THROW(*om);
+ EXPECT_NO_THROW(*oc);
+ EXPECT_NO_THROW(om.value());
+ EXPECT_NO_THROW(oc.value());
+}
+
+TEST(Optional, Value)
+{
+ util::optional<int> oi(42);
+
+ struct foo { int bar; };
+ util::optional<foo> of(foo{42});
+
+ EXPECT_EQ(42, oi.value());
+ EXPECT_EQ(42, *oi);
+
+ EXPECT_EQ(42, of.value().bar);
+ EXPECT_EQ(42, of->bar);
+}
+
+TEST(Optional, Mutable)
+{
+ util::optional<int> oi(42);
+ *oi = 43;
+ EXPECT_EQ(43, *oi);
+
+ struct foo { int bar; int baz; };
+ util::optional<foo> of(foo{11,22});
+
+ (*of).bar = 42;
+ EXPECT_EQ(42, of->bar);
+ EXPECT_EQ(22, of->baz);
+
+ of->baz = 33;
+ EXPECT_EQ(42, of->bar);
+ EXPECT_EQ(33, of->baz);
+}
+
+TEST(Optional, MoveAssign)
+{
+ util::optional<int> e, i(42);
+
+ EXPECT_FALSE(e.has_value());
+ EXPECT_TRUE(i.has_value());
+ EXPECT_EQ(42, *i);
+
+ e = std::move(i);
+ EXPECT_TRUE(e.has_value());
+ EXPECT_FALSE(i.has_value());
+ EXPECT_EQ(42, *e);
+}
+
+TEST(Optional, CopyAssign)
+{
+ util::optional<int> e;
+ const util::optional<int> i(42);
+
+ EXPECT_FALSE(e.has_value());
+ EXPECT_TRUE(i.has_value());
+ EXPECT_EQ(42, *i);
+
+ e = i;
+ EXPECT_TRUE(e.has_value());
+ EXPECT_TRUE(i.has_value());
+ EXPECT_EQ(42, *e);
+ EXPECT_EQ(42, *i);
+}
+
+TEST(Optional, ValueOr)
+{
+ util::optional<int> e;
+ EXPECT_FALSE(e.has_value());
+ EXPECT_EQ(42, e.value_or(42));
+ EXPECT_EQ(42, e.value_or(42.1));
+}
+
+TEST(Optional, Swap)
+{
+ util::optional<int> e, i(42);
+
+ EXPECT_FALSE(e.has_value());
+ EXPECT_TRUE(i.has_value());
+ EXPECT_EQ(42, *i);
+
+ e.swap(i);
+
+ EXPECT_TRUE(e.has_value());
+ EXPECT_FALSE(i.has_value());
+ EXPECT_EQ(42, *e);
+}
+
+TEST(Optional, Reset)
+{
+ util::optional<int> i(42);
+ EXPECT_TRUE(i.has_value());
+
+ i.reset();
+ EXPECT_FALSE(i.has_value());
+}
+
+TEST(Optional, MakeOptional)
+{
+ std::string s("text");
+ auto os = util::make_optional(s);
+ EXPECT_TRUE(os.has_value());
+ EXPECT_EQ(s, os.value());
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/modules/gapi/test/util/variant_tests.cpp b/inference-engine/thirdparty/fluid/modules/gapi/test/util/variant_tests.cpp
new file mode 100644
index 000000000..a95b6aa80
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/modules/gapi/test/util/variant_tests.cpp
@@ -0,0 +1,386 @@
+// 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) 2018 Intel Corporation
+
+
+#include "test_precomp.hpp"
+#include "opencv2/gapi/util/variant.hpp"
+#include <cstddef> //std::max_align_t
+
+namespace opencv_test
+{
+
+namespace
+{
+ typedef util::variant<int, std::string> TestVar;
+ typedef util::variant<int, float> TestVar2;
+}
+
+TEST(Variant, EmptyCTor)
+{
+ util::variant<int> vi;
+ EXPECT_EQ(0, util::get<int>(vi));
+
+ util::variant<int, std::string> vis;
+ EXPECT_EQ(0, util::get<int>(vis));
+
+ util::variant<std::string> vs;
+ EXPECT_EQ("", util::get<std::string>(vs));
+
+ util::variant<std::string, int> vsi;
+ EXPECT_EQ("", util::get<std::string>(vsi));
+}
+
+TEST(Variant, ValueMoveCTor)
+{
+ util::variant<int> vi(42);
+ EXPECT_EQ(0u, vi.index());
+ EXPECT_EQ(42, util::get<int>(vi));
+
+ util::variant<int, std::string> vis(2017);
+ EXPECT_EQ(0u, vis.index());
+ EXPECT_EQ(2017, util::get<int>(vis));
+
+ util::variant<int, std::string> vis2(std::string("2017"));
+ EXPECT_EQ(1u, vis2.index());
+ EXPECT_EQ("2017", util::get<std::string>(vis2));
+
+ util::variant<std::string> vs(std::string("2017"));
+ EXPECT_EQ(0u, vs.index());
+ EXPECT_EQ("2017", util::get<std::string>(vs));
+
+ util::variant<std::string, int> vsi(std::string("2017"));
+ EXPECT_EQ(0u, vsi.index());
+ EXPECT_EQ("2017", util::get<std::string>(vsi));
+
+ util::variant<std::string, int> vsi2(42);
+ EXPECT_EQ(1u, vsi2.index());
+ EXPECT_EQ(42, util::get<int>(vsi2));
+}
+
+TEST(Variant, ValueCopyCTor)
+{
+ const int i42 = 42;
+ const int i17 = 2017;
+ const std::string s17 = "2017";
+
+ util::variant<int> vi(i42);
+ EXPECT_EQ(0u, vi.index());
+ EXPECT_EQ(i42, util::get<int>(vi));
+
+ util::variant<int, std::string> vis(i17);
+ EXPECT_EQ(0u, vis.index());
+ EXPECT_EQ(i17, util::get<int>(vis));
+
+ util::variant<int, std::string> vis2(s17);
+ EXPECT_EQ(1u, vis2.index());
+ EXPECT_EQ(s17, util::get<std::string>(vis2));
+
+ util::variant<std::string> vs(s17);
+ EXPECT_EQ(0u, vs.index());
+ EXPECT_EQ(s17, util::get<std::string>(vs));
+
+ util::variant<std::string, int> vsi(s17);
+ EXPECT_EQ(0u, vsi.index());
+ EXPECT_EQ(s17, util::get<std::string>(vsi));
+
+ util::variant<std::string, int> vsi2(i42);
+ EXPECT_EQ(1u, vsi2.index());
+ EXPECT_EQ(i42, util::get<int>(vsi2));
+}
+
+TEST(Variant, CopyMoveCTor)
+{
+ const TestVar tvconst(std::string("42"));
+
+ TestVar tv = tvconst;
+ EXPECT_EQ( 1u, tv.index());
+ EXPECT_EQ("42", util::get<std::string>(tv));
+
+ TestVar tv2(TestVar(40+2));
+ EXPECT_EQ( 0u, tv2.index());
+ EXPECT_EQ( 42, util::get<int>(tv2));
+}
+
+TEST(Variant, Assign_Basic)
+{
+ TestVar vis;
+ EXPECT_EQ(0u, vis.index());
+ EXPECT_EQ(0, util::get<int>(vis));
+
+ vis = 42;
+ EXPECT_EQ(0u, vis.index());
+ EXPECT_EQ(42, util::get<int>(vis));
+}
+
+TEST(Variant, Assign_ValueUpdate_SameType)
+{
+ TestVar vis(42);
+
+ EXPECT_EQ(0u, vis.index());
+ EXPECT_EQ(42, util::get<int>(vis));
+
+ vis = 43;
+ EXPECT_EQ(0u, vis.index());
+ EXPECT_EQ(43, util::get<int>(vis));
+}
+
+TEST(Variant, Assign_ValueUpdate_DiffType)
+{
+ TestVar vis(42);
+
+ EXPECT_EQ(0u, vis.index());
+ EXPECT_EQ(42, util::get<int>(vis));
+
+ vis = std::string("42");
+ EXPECT_EQ(1u, vis.index());
+ EXPECT_EQ("42", util::get<std::string>(vis));
+}
+
+TEST(Variant, Assign_ValueUpdate_Const)
+{
+ TestVar va(42);
+ const TestVar vb(43);
+
+ EXPECT_EQ(0u, va.index());
+ EXPECT_EQ(42, util::get<int>(va));
+
+ EXPECT_EQ(0u, vb.index());
+ EXPECT_EQ(43, util::get<int>(vb));
+
+ va = vb;
+
+ EXPECT_EQ(0u, va.index());
+ EXPECT_EQ(43, util::get<int>(va));
+}
+
+TEST(Variant, Assign_ValueUpdate_Const_DiffType)
+{
+ TestVar va(42);
+ const TestVar vb(std::string("42"));
+
+ EXPECT_EQ(0u, va.index());
+ EXPECT_EQ(42, util::get<int>(va));
+
+ EXPECT_EQ(1u, vb.index());
+ EXPECT_EQ("42", util::get<std::string>(vb));
+
+ va = vb;
+
+ EXPECT_EQ(1u, va.index());
+ EXPECT_EQ("42", util::get<std::string>(va));
+}
+
+TEST(Variant, Assign_Move)
+{
+ TestVar va(42);
+ TestVar vb(std::string("42"));
+ TestVar vc(43);
+
+ EXPECT_EQ(0u, va.index());
+ EXPECT_EQ(42, util::get<int>(va));
+
+ EXPECT_EQ(1u, vb.index());
+ EXPECT_EQ("42", util::get<std::string>(vb));
+
+ EXPECT_EQ(0u, vc.index());
+ EXPECT_EQ(43, util::get<int>(vc));
+
+ va = std::move(vb);
+ EXPECT_EQ(1u, va.index());
+ EXPECT_EQ("42", util::get<std::string>(va));
+
+ va = std::move(vc);
+ EXPECT_EQ(0u, va.index());
+ EXPECT_EQ(43, util::get<int>(va));
+}
+
+TEST(Variant, Swap_SameIndex)
+{
+ TestVar tv1(42);
+ TestVar tv2(43);
+
+ EXPECT_EQ(0u, tv1.index());
+ EXPECT_EQ(42, util::get<int>(tv1));
+
+ EXPECT_EQ(0u, tv2.index());
+ EXPECT_EQ(43, util::get<int>(tv2));
+
+ tv1.swap(tv2);
+
+ EXPECT_EQ(0u, tv1.index());
+ EXPECT_EQ(43, util::get<int>(tv1));
+
+ EXPECT_EQ(0u, tv2.index());
+ EXPECT_EQ(42, util::get<int>(tv2));
+}
+
+TEST(Variant, Swap_DiffIndex)
+{
+ TestVar2 tv1(42);
+ TestVar2 tv2(3.14f);
+
+ EXPECT_EQ(0u, tv1.index());
+ EXPECT_EQ(42, util::get<int>(tv1));
+
+ EXPECT_EQ(1u, tv2.index());
+ EXPECT_EQ(3.14f, util::get<float>(tv2));
+
+ tv1.swap(tv2);
+
+ EXPECT_EQ(0u, tv2.index());
+ EXPECT_EQ(42, util::get<int>(tv2));
+
+ EXPECT_EQ(1u, tv1.index());
+ EXPECT_EQ(3.14f, util::get<float>(tv1));
+}
+
+TEST(Variant, Get)
+{
+ const TestVar cv(42);
+
+ // Test const& get()
+ EXPECT_EQ(42, util::get<int>(cv));
+ EXPECT_THROW(util::get<std::string>(cv), util::bad_variant_access);
+
+ // Test &get
+ TestVar cv2(std::string("42"));
+ EXPECT_EQ("42", util::get<std::string>(cv2));
+ EXPECT_THROW(util::get<int>(cv2), util::bad_variant_access);
+}
+
+TEST(Variant, GetWrite)
+{
+ util::variant<int, std::string> v(42);
+ EXPECT_EQ(42, util::get<int>(v));
+
+ util::get<int>(v) = 43;
+ EXPECT_EQ(43, util::get<int>(v));
+}
+
+TEST(Variant, NoDefaultCtor)
+{
+ struct MyType
+ {
+ int m_a;
+ MyType() = delete;
+ };
+
+ // This code MUST compile
+ util::variant<int, MyType> var;
+ SUCCEED() << "Code compiled";
+
+ // At the same time, util::variant<MyType, ...> MUST NOT.
+}
+
+TEST(Variant, MonoState)
+{
+ struct MyType
+ {
+ int m_a;
+ explicit MyType(int a) : m_a(a) {}
+ MyType() = delete;
+ };
+
+ util::variant<util::monostate, MyType> var;
+ EXPECT_EQ(0u, var.index());
+
+ var = MyType{42};
+ EXPECT_EQ(1u, var.index());
+ EXPECT_EQ(42, util::get<MyType>(var).m_a);
+}
+
+
+TEST(Variant, Eq)
+{
+ TestVar v1(42), v2(std::string("42"));
+ TestVar v3(v1), v4(v2);
+
+ EXPECT_TRUE(v1 == v3);
+ EXPECT_TRUE(v2 == v4);
+ EXPECT_TRUE(v1 != v2);
+ EXPECT_TRUE(v3 != v4);
+
+ EXPECT_FALSE(v1 == v2);
+ EXPECT_FALSE(v3 == v4);
+ EXPECT_FALSE(v1 != v3);
+ EXPECT_FALSE(v2 != v4);
+}
+
+TEST(Variant, Eq_Monostate)
+{
+ using TestVar3 = util::variant<util::monostate, int>;
+ TestVar3 v1;
+ TestVar3 v2(42);
+
+ EXPECT_NE(v1, v2);
+
+ v2 = util::monostate{};
+ EXPECT_EQ(v1, v2);
+}
+
+TEST(Variant, VectorOfVariants)
+{
+ std::vector<TestVar> vv1(1024);
+ std::vector<TestVar> vv2(1024);
+
+ EXPECT_TRUE(vv1 == vv2);
+
+ std::vector<TestVar> vv3(2048, TestVar(std::string("42")));
+
+ // Just test chat the below code compiles:
+ // 1: internal copy of variants from one vector to another,
+ // with probable reallocation of 1st vector to host all elements
+ std::copy(vv1.begin(), vv1.end(), std::back_inserter(vv2));
+ EXPECT_EQ(2048u, vv2.size());
+
+ // 2: truncation of vector, with probable destruction of its tail memory
+ vv2.resize(1024);
+ EXPECT_EQ(1024u, vv2.size());
+
+ // 3. vector assignment, with overwriting underlying variants
+ vv2 = vv3;
+ EXPECT_EQ(2048u, vv2.size());
+ EXPECT_TRUE(vv2 == vv3);
+}
+
+TEST(Variant, HoldsAlternative)
+{
+ TestVar v(42);
+ EXPECT_TRUE (util::holds_alternative<int> (v));
+ EXPECT_FALSE(util::holds_alternative<std::string>(v));
+
+ v = std::string("42");
+ EXPECT_FALSE(util::holds_alternative<int> (v));
+ EXPECT_TRUE (util::holds_alternative<std::string>(v));
+}
+
+TEST(Variant, Sizeof)
+{
+ //variant has to store index of the contained type as well as the type itself
+ EXPECT_EQ(2 * sizeof(size_t), (sizeof(util::variant<int, char>)));
+#if !defined(__GNUG__) || __GNUG__ >= 5
+ // GCC versions prior to 5.0 have limited C++11 support, e.g.
+ // no std::max_align_t defined
+ EXPECT_EQ((sizeof(std::max_align_t) + std::max(sizeof(size_t), alignof(std::max_align_t))), (sizeof(util::variant<std::max_align_t, char>)));
+#endif
+}
+
+TEST(Variant, EXT_IndexOf)
+{
+ struct MyType{};
+ class MyClass{};
+
+ using V = util::variant<util::monostate, int, double, char, float, MyType, MyClass>;
+ static_assert(0u == V::index_of<util::monostate>(), "Index is incorrect");
+ static_assert(1u == V::index_of<int >(), "Index is incorrect");
+ static_assert(2u == V::index_of<double >(), "Index is incorrect");
+ static_assert(3u == V::index_of<char >(), "Index is incorrect");
+ static_assert(4u == V::index_of<float >(), "Index is incorrect");
+ static_assert(5u == V::index_of<MyType >(), "Index is incorrect");
+ static_assert(6u == V::index_of<MyClass>(), "Index is incorrect");
+}
+
+} // namespace opencv_test
diff --git a/inference-engine/thirdparty/fluid/revision.txt b/inference-engine/thirdparty/fluid/revision.txt
new file mode 100644
index 000000000..e088afdce
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/revision.txt
@@ -0,0 +1 @@
+a3df05d93b188d4e86e23ffd1e988dbec0fc9211
diff --git a/inference-engine/thirdparty/fluid/update.sh b/inference-engine/thirdparty/fluid/update.sh
new file mode 100644
index 000000000..5f4c0536c
--- /dev/null
+++ b/inference-engine/thirdparty/fluid/update.sh
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+
+REVISION=""
+TARGET_DIR=$(pwd)
+
+case "$#" in
+ "0") echo "Using latest master..."
+ REVISION="master"
+ ;;
+ "1") REVISION=$1
+ echo "Using revision ${REVISION}..."
+ ;;
+ *) echo "Usage: ${0} [REVISION]
+
+ Update Fluid to OpenCV source tree at the given REVISION.
+ If no revision specified, the most recent 'master' commit is used.
+"
+ exit 1 ;;
+esac
+
+# Before doing anything, check if this snapshot was not modified
+./check.sh
+if [ $? -ne 0 ]; then
+ echo "Consistency check failed, please reset this subtree to its initial state first!"
+ exit 1
+fi
+
+# Download the stuff...
+URL="https://github.com/opencv/opencv/archive/${REVISION}.zip"
+wget -c ${URL}
+if [ $? -ne 0 ]; then
+ echo "Failed to download ${URL}!"
+ exit 1
+fi
+
+unzip -qq ${REVISION}.zip
+
+# Remove current files
+if [ -f modules ]; then
+ find modules -type f | xargs git rm
+ find modules -type f | xargs rm
+ rm -vd modules
+fi
+
+# Put a new copy. Extend this section if needed
+# BOM thing might help here, probably
+pushd "opencv-${REVISION}"
+cp -rv --parent modules/gapi ${TARGET_DIR}
+popd
+# Note "-f" is used to add files like doc/ which are omitted
+# now by IE's current .gitignore - it breaks checksum otherwise.
+git add -f modules/gapi
+
+# Clean-up files
+rm -rf "opencv-${REVISION}"
+rm "${REVISION}.zip"
+
+# Calculate and store checksum
+./checksum.sh > checksum.txt
+git add checksum.txt
+
+# Store revision
+if [ ${REVISION} == "master" ]; then
+ REVISION="${REVISION} / $(date +%F)"
+fi
+echo ${REVISION} > revision.txt
+git add revision.txt
+
+# Display status
+git status
+
+# Fin
+echo "Done!"