From 5b3d5f9f3c3c96f0f0f602983661d012a4a447c1 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 9 Sep 2021 10:56:34 +0300 Subject: [PATCH 1/9] 3.4: Support of OpenVINO interface libraries original commit: c703f1eed6c3da4f14b37cc151e03463bb4ff54f --- CMakeLists.txt | 3 ++- cmake/OpenCVUtils.cmake | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba2d477501..617d9dd468 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1528,6 +1528,7 @@ if(WITH_INF_ENGINE OR INF_ENGINE_TARGET) if(INF_ENGINE_TARGET) list(GET INF_ENGINE_TARGET 0 ie_target) set(__msg "YES (${INF_ENGINE_RELEASE} / ${INF_ENGINE_VERSION})") + ocv_get_imported_target(ie_target "${ie_target}") get_target_property(_lib ${ie_target} IMPORTED_LOCATION) get_target_property(_lib_imp_rel ${ie_target} IMPORTED_IMPLIB_RELEASE) get_target_property(_lib_imp_dbg ${ie_target} IMPORTED_IMPLIB_DEBUG) @@ -1551,7 +1552,7 @@ if(WITH_INF_ENGINE OR INF_ENGINE_TARGET) endif() if(WITH_NGRAPH OR HAVE_NGRAPH) if(HAVE_NGRAPH) - set(__target ngraph::ngraph) + ocv_get_imported_target(__target ngraph::ngraph) set(__msg "YES (${ngraph_VERSION})") get_target_property(_lib ${__target} IMPORTED_LOCATION) get_target_property(_lib_imp_rel ${__target} IMPORTED_IMPLIB_RELEASE) diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index 1e0ea947ef..9f23abe9f7 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -1580,6 +1580,19 @@ function(ocv_add_library target) endfunction() +# Returns the first non-interface target +function(ocv_get_imported_target imported interface) + set(__result "${interface}") + get_target_property(__type "${__result}" TYPE) + if(__type STREQUAL "INTERFACE_LIBRARY") + get_target_property(__libs "${__result}" INTERFACE_LINK_LIBRARIES) + list(GET __libs 0 __interface) + ocv_get_imported_target(__result "${__interface}") + endif() + set(${imported} "${__result}" PARENT_SCOPE) +endfunction() + + macro(ocv_get_libname var_name) get_filename_component(__libname "${ARGN}" NAME) # libopencv_core.so.3.3 -> opencv_core From d1e76a34a07e2e8e68c7bf582aebe94665605980 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Sat, 15 Jan 2022 00:53:19 +0300 Subject: [PATCH 2/9] 3.4: Use modern OpenVINO package interface original commit: 437af37b1341e5cef90aa1a4ce60210feacc6c8a --- CMakeLists.txt | 112 ++++++++++++------------ cmake/OpenCVDetectInferenceEngine.cmake | 43 +++++---- cmake/OpenCVUtils.cmake | 41 +++++++++ modules/dnn/CMakeLists.txt | 22 +---- 4 files changed, 127 insertions(+), 91 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 617d9dd468..8f9a2d17d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -291,12 +291,10 @@ OCV_OPTION(WITH_IPP "Include Intel IPP support" (NOT MINGW AND NOT CV_DISABLE_OP OCV_OPTION(WITH_HALIDE "Include Halide support" OFF VISIBLE_IF TRUE VERIFY HAVE_HALIDE) -OCV_OPTION(WITH_INF_ENGINE "Include Intel Inference Engine support" OFF +# replacement for deprecated options: WITH_INF_ENGINE, WITH_NGRAPH +OCV_OPTION(WITH_OPENVINO "Include Intel OpenVINO toolkit support" (WITH_INF_ENGINE) VISIBLE_IF TRUE - VERIFY INF_ENGINE_TARGET) -OCV_OPTION(WITH_NGRAPH "Include nGraph support" WITH_INF_ENGINE - VISIBLE_IF TRUE - VERIFY TARGET ngraph::ngraph) + VERIFY TARGET ocv.3rdparty.openvino) OCV_OPTION(WITH_JASPER "Include JPEG2K support" ON VISIBLE_IF NOT IOS VERIFY HAVE_JASPER) @@ -764,7 +762,7 @@ if(WITH_HALIDE) endif() # --- Inference Engine --- -if(WITH_INF_ENGINE) +if(WITH_INF_ENGINE OR WITH_OPENVINO) include(cmake/OpenCVDetectInferenceEngine.cmake) endif() @@ -1524,55 +1522,61 @@ if(WITH_HALIDE OR HAVE_HALIDE) status(" Halide:" HAVE_HALIDE THEN "YES (${HALIDE_LIBRARIES} ${HALIDE_INCLUDE_DIRS})" ELSE NO) endif() -if(WITH_INF_ENGINE OR INF_ENGINE_TARGET) - if(INF_ENGINE_TARGET) - list(GET INF_ENGINE_TARGET 0 ie_target) - set(__msg "YES (${INF_ENGINE_RELEASE} / ${INF_ENGINE_VERSION})") - ocv_get_imported_target(ie_target "${ie_target}") - get_target_property(_lib ${ie_target} IMPORTED_LOCATION) - get_target_property(_lib_imp_rel ${ie_target} IMPORTED_IMPLIB_RELEASE) - get_target_property(_lib_imp_dbg ${ie_target} IMPORTED_IMPLIB_DEBUG) - get_target_property(_lib_rel ${ie_target} IMPORTED_LOCATION_RELEASE) - get_target_property(_lib_dbg ${ie_target} IMPORTED_LOCATION_DEBUG) - ocv_build_features_string(_lib - IF _lib THEN "${_lib}" - IF _lib_imp_rel AND _lib_imp_dbg THEN "${_lib_imp_rel} / ${_lib_imp_dbg}" - IF _lib_rel AND _lib_dbg THEN "${_lib_rel} / ${_lib_dbg}" - IF _lib_rel THEN "${_lib_rel}" - IF _lib_dbg THEN "${_lib_dbg}" - ELSE "unknown" - ) - get_target_property(_inc ${ie_target} INTERFACE_INCLUDE_DIRECTORIES) - status(" Inference Engine:" "${__msg}") - status(" * libs:" "${_lib}") - status(" * includes:" "${_inc}") - else() - status(" Inference Engine:" "NO") +if(HAVE_OPENVINO + OR (WITH_OPENVINO AND NOT WITH_INF_ENGINE AND NOT INF_ENGINE_TARGET) +) + status(" OpenVINO:" TARGET openvino::runtime THEN "YES (${OpenVINO_VERSION})" ELSE "NO") +else() + if(WITH_INF_ENGINE OR INF_ENGINE_TARGET) + if(INF_ENGINE_TARGET) + list(GET INF_ENGINE_TARGET 0 ie_target) + set(__msg "YES (${INF_ENGINE_RELEASE} / ${INF_ENGINE_VERSION})") + ocv_get_imported_target(ie_target "${ie_target}") + get_target_property(_lib ${ie_target} IMPORTED_LOCATION) + get_target_property(_lib_imp_rel ${ie_target} IMPORTED_IMPLIB_RELEASE) + get_target_property(_lib_imp_dbg ${ie_target} IMPORTED_IMPLIB_DEBUG) + get_target_property(_lib_rel ${ie_target} IMPORTED_LOCATION_RELEASE) + get_target_property(_lib_dbg ${ie_target} IMPORTED_LOCATION_DEBUG) + ocv_build_features_string(_lib + IF _lib THEN "${_lib}" + IF _lib_imp_rel AND _lib_imp_dbg THEN "${_lib_imp_rel} / ${_lib_imp_dbg}" + IF _lib_rel AND _lib_dbg THEN "${_lib_rel} / ${_lib_dbg}" + IF _lib_rel THEN "${_lib_rel}" + IF _lib_dbg THEN "${_lib_dbg}" + ELSE "unknown" + ) + get_target_property(_inc ${ie_target} INTERFACE_INCLUDE_DIRECTORIES) + status(" Inference Engine:" "${__msg}") + status(" * libs:" "${_lib}") + status(" * includes:" "${_inc}") + else() + status(" Inference Engine:" "NO") + endif() endif() -endif() -if(WITH_NGRAPH OR HAVE_NGRAPH) - if(HAVE_NGRAPH) - ocv_get_imported_target(__target ngraph::ngraph) - set(__msg "YES (${ngraph_VERSION})") - get_target_property(_lib ${__target} IMPORTED_LOCATION) - get_target_property(_lib_imp_rel ${__target} IMPORTED_IMPLIB_RELEASE) - get_target_property(_lib_imp_dbg ${__target} IMPORTED_IMPLIB_DEBUG) - get_target_property(_lib_rel ${__target} IMPORTED_LOCATION_RELEASE) - get_target_property(_lib_dbg ${__target} IMPORTED_LOCATION_DEBUG) - ocv_build_features_string(_lib - IF _lib THEN "${_lib}" - IF _lib_imp_rel AND _lib_imp_dbg THEN "${_lib_imp_rel} / ${_lib_imp_dbg}" - IF _lib_rel AND _lib_dbg THEN "${_lib_rel} / ${_lib_dbg}" - IF _lib_rel THEN "${_lib_rel}" - IF _lib_dbg THEN "${_lib_dbg}" - ELSE "unknown" - ) - get_target_property(_inc ${__target} INTERFACE_INCLUDE_DIRECTORIES) - status(" nGraph:" "${__msg}") - status(" * libs:" "${_lib}") - status(" * includes:" "${_inc}") - else() - status(" nGraph:" "NO") + if(WITH_NGRAPH OR HAVE_NGRAPH) + if(HAVE_NGRAPH) + ocv_get_imported_target(__target ngraph::ngraph) + set(__msg "YES (${ngraph_VERSION})") + get_target_property(_lib ${__target} IMPORTED_LOCATION) + get_target_property(_lib_imp_rel ${__target} IMPORTED_IMPLIB_RELEASE) + get_target_property(_lib_imp_dbg ${__target} IMPORTED_IMPLIB_DEBUG) + get_target_property(_lib_rel ${__target} IMPORTED_LOCATION_RELEASE) + get_target_property(_lib_dbg ${__target} IMPORTED_LOCATION_DEBUG) + ocv_build_features_string(_lib + IF _lib THEN "${_lib}" + IF _lib_imp_rel AND _lib_imp_dbg THEN "${_lib_imp_rel} / ${_lib_imp_dbg}" + IF _lib_rel AND _lib_dbg THEN "${_lib_rel} / ${_lib_dbg}" + IF _lib_rel THEN "${_lib_rel}" + IF _lib_dbg THEN "${_lib_dbg}" + ELSE "unknown" + ) + get_target_property(_inc ${__target} INTERFACE_INCLUDE_DIRECTORIES) + status(" nGraph:" "${__msg}") + status(" * libs:" "${_lib}") + status(" * includes:" "${_inc}") + else() + status(" nGraph:" "NO") + endif() endif() endif() diff --git a/cmake/OpenCVDetectInferenceEngine.cmake b/cmake/OpenCVDetectInferenceEngine.cmake index 128883b128..58a16f6d54 100644 --- a/cmake/OpenCVDetectInferenceEngine.cmake +++ b/cmake/OpenCVDetectInferenceEngine.cmake @@ -1,21 +1,7 @@ -# The script detects Intel(R) Inference Engine installation -# -# Cache variables: -# INF_ENGINE_RELEASE - a number reflecting IE source interface (linked with OpenVINO release) -# -# Detect parameters: -# 1. Native cmake IE package: -# - environment variable InferenceEngine_DIR is set to location of cmake module -# 2. Custom location: -# - INF_ENGINE_INCLUDE_DIRS - headers search location -# - INF_ENGINE_LIB_DIRS - library search location -# 3. OpenVINO location: -# - environment variable INTEL_OPENVINO_DIR is set to location of OpenVINO installation dir -# - INF_ENGINE_PLATFORM - part of name of library directory representing its platform +# The script detects Intel(R) OpenVINO(TM) runtime installation # # Result: -# INF_ENGINE_TARGET - set to name of imported library target representing InferenceEngine -# +# - target ocv.3rdparty.openvino if(NOT HAVE_CXX11) message(WARNING "DL Inference engine requires C++11. You can turn it on via ENABLE_CXX11=ON CMake flag.") @@ -24,6 +10,19 @@ endif() # ======================= +if(WITH_OPENVINO) + find_package(OpenVINO QUIET) + if(OpenVINO_FOUND) + message(STATUS "OpenVINO FOUND: ${OpenVINO_VERSION}") + math(EXPR ver "${OpenVINO_VERSION_MAJOR} * 1000000 + ${OpenVINO_VERSION_MINOR} * 10000 + ${OpenVINO_VERSION_PATCH} * 100") + ocv_add_external_target(openvino "" "openvino::runtime" "INF_ENGINE_RELEASE=${ver};HAVE_NGRAPH;HAVE_DNN_NGRAPH;HAVE_INF_ENGINE") + set(HAVE_OPENVINO 1) + return() + endif() +endif() + +# ====================== + macro(ocv_ie_find_extra_libraries find_prefix find_suffix) file(GLOB libraries "${INF_ENGINE_LIB_DIRS}/${find_prefix}inference_engine*${find_suffix}") foreach(full_path IN LISTS libraries) @@ -151,15 +150,19 @@ if(NOT INF_ENGINE_TARGET AND _loc) add_custom_ie_build("${ie_custom_env_inc}" "${ie_custom_env_lib}" "${ie_custom_env_lib_rel}" "${ie_custom_env_lib_dbg}" "OpenVINO (${_loc})") endif() -# Add more features to the target +set(tgts) +set(defs) +# Add more features to the target if(INF_ENGINE_TARGET) set_target_properties(${INF_ENGINE_TARGET} PROPERTIES INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}" ) + list(APPEND tgts ${INF_ENGINE_TARGET}) + list(APPEND defs "INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}" "HAVE_INF_ENGINE") endif() -if(WITH_NGRAPH) +if(WITH_NGRAPH OR NOT DEFINED WITH_NGRAPH) find_package(ngraph QUIET) if(ngraph_FOUND) ocv_assert(TARGET ngraph::ngraph) @@ -168,5 +171,9 @@ if(WITH_NGRAPH) endif() message(STATUS "Detected ngraph: cmake package (${ngraph_VERSION})") set(HAVE_NGRAPH ON) + list(APPEND tgts ngraph::ngraph) + list(APPEND defs "HAVE_NGRAPH" "HAVE_DNN_NGRAPH") endif() endif() + +ocv_add_external_target(openvino "" "${tgts}" "${defs}") diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index 9f23abe9f7..938c4e1f82 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -1580,6 +1580,47 @@ function(ocv_add_library target) endfunction() +function(ocv_add_external_target name inc link def) + if(BUILD_SHARED_LIBS AND link) + set(imp IMPORTED) + endif() + add_library(ocv.3rdparty.${name} INTERFACE ${imp}) + if(def) + if(NOT (CMAKE_VERSION VERSION_LESS "3.11.0")) # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/1264 : eliminates "Cannot specify compile definitions for imported target" error message + target_compile_definitions(ocv.3rdparty.${name} INTERFACE "${def}") + else() + set_target_properties(ocv.3rdparty.${name} PROPERTIES INTERFACE_COMPILE_DEFINITIONS "${def}") + endif() + endif() + if(inc) + if(NOT (CMAKE_VERSION VERSION_LESS "3.11.0")) # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/1264 : eliminates "Cannot specify compile definitions for imported target" error message + target_include_directories(ocv.3rdparty.${name} SYSTEM INTERFACE "$") + else() + set_target_properties(ocv.3rdparty.${name} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "$" + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "$" + ) + endif() + endif() + if(link) + # When cmake version is greater than or equal to 3.11, INTERFACE_LINK_LIBRARIES no longer applies to interface library + # See https://github.com/opencv/opencv/pull/18658 + if(CMAKE_VERSION VERSION_LESS 3.11) + set_target_properties(ocv.3rdparty.${name} PROPERTIES + INTERFACE_LINK_LIBRARIES "${link}") + else() + target_link_libraries(ocv.3rdparty.${name} INTERFACE ${link}) + endif() + endif() + # to install used target only upgrade CMake + if(NOT BUILD_SHARED_LIBS + AND CMAKE_VERSION VERSION_LESS "3.13.0" # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/2152 + ) + install(TARGETS ocv.3rdparty.${name} EXPORT OpenCVModules) + endif() +endfunction() + + # Returns the first non-interface target function(ocv_get_imported_target imported interface) set(__result "${interface}") diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt index 9dc048f5b6..8b117a952d 100644 --- a/modules/dnn/CMakeLists.txt +++ b/modules/dnn/CMakeLists.txt @@ -115,24 +115,8 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") endif() set(dnn_runtime_libs "") -if(INF_ENGINE_TARGET) - set(use_nn_builder OFF) - if(TARGET inference_engine_nn_builder OR # custom imported target - TARGET IE::inference_engine_nn_builder OR # default imported target via InferenceEngineConfig.cmake - INF_ENGINE_RELEASE VERSION_LESS "2020000000") # compatibility with older versions on IE - set(use_nn_builder ON) - endif() - ocv_option(OPENCV_DNN_IE_NN_BUILDER_2019 "Build with Inference Engine NN Builder API support" ${use_nn_builder}) # future: NOT HAVE_NGRAPH - if(OPENCV_DNN_IE_NN_BUILDER_2019) - message(STATUS "DNN: Enabling Inference Engine NN Builder API support") - add_definitions(-DHAVE_DNN_IE_NN_BUILDER_2019=1) - endif() - list(APPEND dnn_runtime_libs ${INF_ENGINE_TARGET}) -endif() -if(HAVE_NGRAPH) - message(STATUS "DNN: Enabling Inference Engine nGraph API support") - add_definitions(-DHAVE_DNN_NGRAPH) - list(APPEND dnn_runtime_libs ngraph::ngraph) +if(TARGET ocv.3rdparty.openvino) + list(APPEND dnn_runtime_libs ocv.3rdparty.openvino) endif() ocv_glob_module_sources(${sources_options} SOURCES ${fw_srcs}) @@ -143,7 +127,7 @@ ocv_add_accuracy_tests(${dnn_runtime_libs}) set(perf_path "${CMAKE_CURRENT_LIST_DIR}/perf") file(GLOB_RECURSE perf_srcs "${perf_path}/*.cpp") file(GLOB_RECURSE perf_hdrs "${perf_path}/*.hpp" "${perf_path}/*.h") -ocv_add_perf_tests(${INF_ENGINE_TARGET} +ocv_add_perf_tests(${dnn_runtime_libs} FILES test_common "${CMAKE_CURRENT_LIST_DIR}/test/test_common.hpp" "${CMAKE_CURRENT_LIST_DIR}/test/test_common.impl.hpp" FILES Src ${perf_srcs} FILES Include ${perf_hdrs} From 4d7953aa563f67fb0636116064dfe0114f90e624 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 3 Feb 2022 17:25:52 +0000 Subject: [PATCH 3/9] cmake(carotene): disable with CV_DISABLE_OPTIMIZATION --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba2d477501..db94b98986 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,7 +244,7 @@ OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O (iOS/Mac)" ON OCV_OPTION(WITH_CARBON "Use Carbon for UI instead of Cocoa (OBSOLETE)" OFF VISIBLE_IF (APPLE OR HAVE_COCOA) VERIFY HAVE_CARBON) -OCV_OPTION(WITH_CAROTENE "Use NVidia carotene acceleration library for ARM platform" ON +OCV_OPTION(WITH_CAROTENE "Use NVidia carotene acceleration library for ARM platform" (NOT CV_DISABLE_OPTIMIZATION) VISIBLE_IF (ARM OR AARCH64) AND NOT IOS AND NOT (CMAKE_VERSION VERSION_LESS "2.8.11")) OCV_OPTION(WITH_CPUFEATURES "Use cpufeatures Android library" ON VISIBLE_IF ANDROID From aa5bc20c835ad7238075b000863413b874e25c15 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sat, 5 Feb 2022 03:28:36 +0000 Subject: [PATCH 4/9] dnn(ngraph): fixup get_output_as_single_output_node() replacement patch --- modules/dnn/src/dnn.cpp | 17 +++++++++++++++-- modules/dnn/src/ie_ngraph.cpp | 2 +- modules/dnn/src/ie_ngraph.hpp | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 245a2c5c1d..f03fa20626 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -2196,9 +2196,22 @@ struct Net::Impl : public detail::NetImplBase continue; auto ieInpNode = inputNodes[i].dynamicCast(); - CV_Assert(oid < ieInpNode->node->get_output_size()); + const auto& ngraph_input_node = ieInpNode->node; + CV_LOG_DEBUG(NULL, "DNN/IE: bind output port " << lid << ":" << oid << " (" << ngraph_input_node->get_friendly_name() << ":" << ngraph_input_node->get_type_info().name << ")"); + + // Handle parameters from other subnets. Output port is not used in this case + if ((ngraph::op::is_parameter(ngraph_input_node) || ngraph::op::is_constant(ngraph_input_node)) && + ngraph_input_node->get_output_size() == 1) + { + inputNodes[i] = Ptr(new InfEngineNgraphNode(ngraph_input_node)); + continue; + } + CV_CheckLT((size_t)oid, ngraph_input_node->get_output_size(), ""); #if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2020_4) - inputNodes[i] = Ptr(new InfEngineNgraphNode(ieInpNode->node)); + // FIXIT refactor ".initNgraph()" API to use Output + // WA: use Concat to emulate Identity operation with requested output port + auto oid_node = std::make_shared(ngraph::OutputVector {ngraph_input_node->output(oid)}, 0); + inputNodes[i] = Ptr(new InfEngineNgraphNode(oid_node)); #elif INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2020_3) inputNodes[i] = Ptr(new InfEngineNgraphNode(ieInpNode->node->get_output_as_single_output_node(oid))); #else diff --git a/modules/dnn/src/ie_ngraph.cpp b/modules/dnn/src/ie_ngraph.cpp index 6736590161..916f5e0a18 100644 --- a/modules/dnn/src/ie_ngraph.cpp +++ b/modules/dnn/src/ie_ngraph.cpp @@ -330,7 +330,7 @@ public: InfEngineNgraphNode::InfEngineNgraphNode(std::shared_ptr&& _node) : BackendNode(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH), node(std::move(_node)) {} -InfEngineNgraphNode::InfEngineNgraphNode(std::shared_ptr& _node) +InfEngineNgraphNode::InfEngineNgraphNode(const std::shared_ptr& _node) : BackendNode(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH), node(_node) {} InfEngineNgraphNode::InfEngineNgraphNode(const std::vector >& nodes, diff --git a/modules/dnn/src/ie_ngraph.hpp b/modules/dnn/src/ie_ngraph.hpp index 617f1d4542..bb593833ff 100644 --- a/modules/dnn/src/ie_ngraph.hpp +++ b/modules/dnn/src/ie_ngraph.hpp @@ -102,7 +102,7 @@ public: std::vector& internals); InfEngineNgraphNode(std::shared_ptr&& _node); - InfEngineNgraphNode(std::shared_ptr& _node); + InfEngineNgraphNode(const std::shared_ptr& _node); void setName(const std::string& name); From 1f70d4e2a502502f5ccf37311d2d841974dfe05e Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sat, 5 Feb 2022 03:31:39 +0000 Subject: [PATCH 5/9] dnn(test): re-enable ONNX split tests for OpenVINO --- ...conformance_layer_filter__openvino.inl.hpp | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp b/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp index c3b62a7f75..4bde85100f 100644 --- a/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp +++ b/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp @@ -1697,26 +1697,11 @@ CASE(test_spacetodepth) CASE(test_spacetodepth_example) // no filter CASE(test_split_equal_parts_1d) -#if INF_ENGINE_VER_MAJOR_EQ(2021040000) - SKIP_CPU; - // MYRIAD is ok - SKIP_OPENCL; - SKIP_OPENCL_FP16; -#endif + // no filter CASE(test_split_equal_parts_2d) -#if INF_ENGINE_VER_MAJOR_EQ(2021040000) - SKIP_CPU; - // MYRIAD is ok - SKIP_OPENCL; - SKIP_OPENCL_FP16; -#endif + // no filter CASE(test_split_equal_parts_default_axis) -#if INF_ENGINE_VER_MAJOR_EQ(2021040000) - SKIP_CPU; - // MYRIAD is ok - SKIP_OPENCL; - SKIP_OPENCL_FP16; -#endif + // no filter CASE(test_split_variable_parts_1d) // no filter CASE(test_split_variable_parts_2d) From 062f305d1aa9d11b1b81c8231102d820738858d8 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 3 Feb 2022 20:23:17 +0000 Subject: [PATCH 6/9] dnn: don't fuse 'outputs' with OpenVINO backend --- modules/dnn/src/dnn.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index f03fa20626..ff16b31590 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -2412,8 +2412,15 @@ struct Net::Impl : public detail::NetImplBase preferableBackend != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)) return; +#if 0 // FIXIT mode without fusion is broken due to unsupported layers and handling of "custom" nodes + if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + return; +#endif + // scan through all the layers. If there is convolution layer followed by the activation layer, // we try to embed this activation into the convolution and disable separate execution of the activation + + // FIXIT replace by layersToKeep to avoid hacks like "LayerPin(lid, 0)" std::set pinsToKeep(blobsToKeep_.begin(), blobsToKeep_.end()); for (MapIdToLayerData::const_iterator it = layers.begin(); it != layers.end(); it++) @@ -2438,6 +2445,13 @@ struct Net::Impl : public detail::NetImplBase LayerPin lpNext(ld.consumers[0].lid, 0); while (nextData) { +#ifdef HAVE_INF_ENGINE + if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && pinsToKeep.count(lpNext) != 0) + { + CV_LOG_DEBUG(NULL, "DNN/IE: skip fusing with 'output' node: " << nextData->name << "@" << nextData->type); + break; + } +#endif Ptr nextLayer = nextData->layerInstance; if (currLayer->tryFuse(nextLayer)) { From 67978b5746567d56827c8db5e2e08ba5351916fb Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sat, 5 Feb 2022 14:36:57 +0000 Subject: [PATCH 7/9] dnn(ngraph): add debuging messages --- modules/dnn/include/opencv2/dnn/shape_utils.hpp | 10 +++++++--- modules/dnn/src/dnn.cpp | 16 ++++++++++++++++ modules/dnn/src/ie_ngraph.cpp | 13 +++++++++---- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/modules/dnn/include/opencv2/dnn/shape_utils.hpp b/modules/dnn/include/opencv2/dnn/shape_utils.hpp index b77333bd48..fafd1bf725 100644 --- a/modules/dnn/include/opencv2/dnn/shape_utils.hpp +++ b/modules/dnn/include/opencv2/dnn/shape_utils.hpp @@ -184,7 +184,8 @@ static inline MatShape concat(const MatShape& a, const MatShape& b) return c; } -static inline std::string toString(const MatShape& shape, const String& name = "") +template +static inline std::string toString(const std::vector<_Tp>& shape, const String& name = "") { std::ostringstream ss; if (!name.empty()) @@ -195,11 +196,14 @@ static inline std::string toString(const MatShape& shape, const String& name = " ss << " ]"; return ss.str(); } -static inline void print(const MatShape& shape, const String& name = "") + +template +static inline void print(const std::vector<_Tp>& shape, const String& name = "") { std::cout << toString(shape, name) << std::endl; } -static inline std::ostream& operator<<(std::ostream &out, const MatShape& shape) +template +static inline std::ostream& operator<<(std::ostream &out, const std::vector<_Tp>& shape) { out << toString(shape); return out; diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index ff16b31590..672b328993 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -1941,6 +1941,8 @@ struct Net::Impl : public detail::NetImplBase { CV_TRACE_FUNCTION(); + CV_LOG_DEBUG(NULL, "DNN/IE: layer of new subnet: " << ld.name << "@" << ld.type); + Ptr layerNet; auto it = ld.backendNodes.find(preferableBackend); if (it != ld.backendNodes.end()) @@ -1964,6 +1966,7 @@ struct Net::Impl : public detail::NetImplBase CV_Assert(!ieInpNode.empty()); CV_Assert(!ieInpNode->net.empty()); if (layerNet != ieInpNode->net) { + CV_LOG_DEBUG(NULL, "DNN/IE: pin output between subnets: " << ieInpNode->node->get_friendly_name()); ieInpNode->net->addOutput(ieInpNode->node->get_friendly_name()); ieInpNode->net->setUnconnectedNodes(ieInpNode); } @@ -2064,13 +2067,19 @@ struct Net::Impl : public detail::NetImplBase { LayerData& ld = it->second; + CV_LOG_DEBUG(NULL, "DNN/IE: processing layer " << ld.name << "@" << ld.type << " (" << ld.id << ") ..."); + if (ld.id == 0 && ld.skip) + { + CV_LOG_DEBUG(NULL, "DNN/IE: SKIP!"); continue; + } bool fused = ld.skip; Ptr layer = ld.layerInstance; if (!fused && !layer->supportBackend(preferableBackend)) { + CV_LOG_DEBUG(NULL, "DNN/IE: NOT supported!"); bool customizable = ld.id != 0 && supportsCPUFallback; // TODO: there is a bug in Myriad plugin with custom layers shape infer. @@ -2097,6 +2106,7 @@ struct Net::Impl : public detail::NetImplBase if (!customizable) { + CV_LOG_DEBUG(NULL, "DNN/IE: NOT customizable!"); addNgraphOutputs(ld); net = Ptr(); layer->preferableTarget = DNN_TARGET_CPU; @@ -2221,7 +2231,9 @@ struct Net::Impl : public detail::NetImplBase if (layer->supportBackend(preferableBackend)) { + CV_LOG_DEBUG(NULL, "DNN/IE: wrap layer " << ld.name << "@" << ld.type << " - outputs: " << ld.outputBlobsWrappers.size()); node = layer->initNgraph(ld.inputBlobsWrappers, inputNodes); + // FIXIT doesn't work with multiple outputs (set name is applied to the same node) for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i) { InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.outputBlobsWrappers[i]); @@ -2230,12 +2242,16 @@ struct Net::Impl : public detail::NetImplBase } else { + CV_LOG_DEBUG(NULL, "DNN/IE: layer is not supported: " << ld.name << "@" << ld.type); node = Ptr(new InfEngineNgraphNode(inputNodes, ld.layerInstance, ld.inputBlobs, ld.outputBlobs, ld.internals)); } } else if (node.empty()) + { + CV_LOG_DEBUG(NULL, "DNN/IE: node.empty() bypass..."); continue; + } ld.backendNodes[preferableBackend] = node; diff --git a/modules/dnn/src/ie_ngraph.cpp b/modules/dnn/src/ie_ngraph.cpp index 916f5e0a18..de735cc32c 100644 --- a/modules/dnn/src/ie_ngraph.cpp +++ b/modules/dnn/src/ie_ngraph.cpp @@ -449,6 +449,7 @@ void InfEngineNgraphNet::createNet(Target targetId) { ngraph::ResultVector outs; for (auto& node : unconnectedNodes) { + CV_LOG_DEBUG(NULL, "DNN/IE: +network_output[" << outs.size() << "]: name='" << node->get_friendly_name() << "'"); auto out = std::make_shared(node); outs.push_back(out); } @@ -456,6 +457,7 @@ void InfEngineNgraphNet::createNet(Target targetId) { ngraph_function = std::make_shared(outs, inputs_vec); int num_comp = getNumComponents(); + CV_LOG_DEBUG(NULL, "DNN/IE: number of subgraphs: " << num_comp); if (num_comp > 1) { for (int i = num_comp - 1; i >= 0; --i) { ngraph::ResultVector outputs; @@ -466,6 +468,7 @@ void InfEngineNgraphNet::createNet(Target targetId) { #else if (node->is_parameter()) { #endif + CV_LOG_DEBUG(NULL, "DNN/IE: subgraph[" << i << "]: +input[" << inps.size() << "] = '" << node->get_friendly_name() << "'"); auto parameter = std::dynamic_pointer_cast(node); inps.push_back(parameter); } @@ -474,10 +477,12 @@ void InfEngineNgraphNet::createNet(Target targetId) { #else else if (node->is_output()) { #endif + CV_LOG_DEBUG(NULL, "DNN/IE: subgraph[" << i << "]: +output[" << outputs.size() << "] = '" << node->get_friendly_name() << "'"); auto result = std::dynamic_pointer_cast(node); outputs.push_back(result); } } + CV_LOG_DEBUG(NULL, "DNN/IE: subgraph[" << i << ": nodes=" << components.back().size() << " inputs=" << inps.size() << " outputs=" << outputs.size()); isInit = false; CV_Assert_N(!inps.empty(), !outputs.empty()); ngraph_function = std::make_shared(outputs, inps); @@ -729,10 +734,10 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) } } } - if (isHetero) - netExec = ie.LoadNetwork(net, "HETERO:" + device_name + ",CPU", config); - else - netExec = ie.LoadNetwork(net, device_name, config); + + std::string ieDevice = isHetero ? ("HETERO:" + device_name + ",CPU") : device_name; + CV_LOG_INFO(NULL, "DNN/IE: Calling LoadNetwork(device=" << ieDevice << ")..."); + netExec = ie.LoadNetwork(net, ieDevice, config); } catch (const std::exception& ex) { From b57ff73086540a0039408ec562efa93619f7fef1 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sat, 5 Feb 2022 02:51:44 +0000 Subject: [PATCH 8/9] dnn(ngraph): fix outputs handling, drop 'unconnected' logic --- modules/dnn/src/dnn.cpp | 16 +++++++--------- modules/dnn/src/ie_ngraph.cpp | 34 +++++++++++++++++----------------- modules/dnn/src/ie_ngraph.hpp | 6 ++---- 3 files changed, 26 insertions(+), 30 deletions(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 672b328993..82f814131e 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -1937,6 +1937,9 @@ struct Net::Impl : public detail::NetImplBase #ifdef HAVE_DNN_NGRAPH + /** mark input pins as outputs from other subnetworks + * FIXIT must be done by DNN engine not ngraph. + */ void addNgraphOutputs(LayerData &ld) { CV_TRACE_FUNCTION(); @@ -1967,8 +1970,7 @@ struct Net::Impl : public detail::NetImplBase if (layerNet != ieInpNode->net) { CV_LOG_DEBUG(NULL, "DNN/IE: pin output between subnets: " << ieInpNode->node->get_friendly_name()); - ieInpNode->net->addOutput(ieInpNode->node->get_friendly_name()); - ieInpNode->net->setUnconnectedNodes(ieInpNode); + ieInpNode->net->addOutput(ieInpNode); } } } @@ -2118,7 +2120,7 @@ struct Net::Impl : public detail::NetImplBase if (!inpNode.empty()) { Ptr ieNode = inpNode.dynamicCast(); CV_Assert(!ieNode.empty()); - ieNode->net->setUnconnectedNodes(ieNode); + ieNode->net->addOutput(ieNode); } } continue; @@ -2259,15 +2261,11 @@ struct Net::Impl : public detail::NetImplBase CV_Assert(!ieNode.empty()); ieNode->net = net; - if (ld.consumers.empty()) { - // TF EAST_text_detection - ieNode->net->setUnconnectedNodes(ieNode); - } for (const auto& pin : blobsToKeep_) { if (pin.lid == ld.id) { - ieNode->net->addOutput(ieNode->node->get_friendly_name()); + ieNode->net->addOutput(ieNode); break; } } @@ -2298,7 +2296,7 @@ struct Net::Impl : public detail::NetImplBase if (!ieNode->net->isInitialized()) { - ieNode->net->setUnconnectedNodes(ieNode); + ieNode->net->addOutput(ieNode); ieNode->net->createNet((Target)preferableTarget); ld.skip = false; } diff --git a/modules/dnn/src/ie_ngraph.cpp b/modules/dnn/src/ie_ngraph.cpp index de735cc32c..235fa7dcbb 100644 --- a/modules/dnn/src/ie_ngraph.cpp +++ b/modules/dnn/src/ie_ngraph.cpp @@ -379,16 +379,21 @@ InfEngineNgraphNet::InfEngineNgraphNet(detail::NetImplBase& netImpl, InferenceEn device_name = "CPU"; } -void InfEngineNgraphNet::addOutput(const std::string& name) +void InfEngineNgraphNet::addOutput(const Ptr& node) { - requestedOutputs.push_back(name); + CV_Assert(node); + CV_Assert(node->node); + const std::string& name = node->node->get_friendly_name(); + requestedOutputs.insert({name, node}); } void InfEngineNgraphNet::setNodePtr(std::shared_ptr* ptr) { all_nodes.emplace((*ptr)->get_friendly_name(), ptr); } - void InfEngineNgraphNet::release() { + void InfEngineNgraphNet::release() + { + // FIXIT release should not be conditional, release ALL for (auto& node : components.back()) { #if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2020_4) if (!(ngraph::op::is_parameter(node) || ngraph::op::is_output(node) || ngraph::op::is_constant(node)) ) { @@ -397,7 +402,6 @@ void InfEngineNgraphNet::setNodePtr(std::shared_ptr* ptr) { #endif auto it = all_nodes.find(node->get_friendly_name()); if (it != all_nodes.end()) { - unconnectedNodes.erase(*(it->second)); it->second->reset(); all_nodes.erase(it); } @@ -422,7 +426,8 @@ void InfEngineNgraphNet::dfs(std::shared_ptr& node, } } -int InfEngineNgraphNet::getNumComponents() { +int InfEngineNgraphNet::getNumComponents() +{ if (!components.empty()) { return components.size(); } @@ -445,12 +450,14 @@ int InfEngineNgraphNet::getNumComponents() { void InfEngineNgraphNet::createNet(Target targetId) { if (!hasNetOwner) { - CV_Assert(!unconnectedNodes.empty()); + CV_Assert(!requestedOutputs.empty()); ngraph::ResultVector outs; - for (auto& node : unconnectedNodes) + + for (auto output_node_it = requestedOutputs.begin(); output_node_it != requestedOutputs.end(); ++output_node_it) { - CV_LOG_DEBUG(NULL, "DNN/IE: +network_output[" << outs.size() << "]: name='" << node->get_friendly_name() << "'"); - auto out = std::make_shared(node); + CV_LOG_DEBUG(NULL, "DNN/NGRAPH: Add 'Result' output: " << output_node_it->first); + CV_Assert(output_node_it->second); + auto out = std::make_shared(output_node_it->second->node); outs.push_back(out); } CV_Assert_N(!inputs_vec.empty(), !outs.empty()); @@ -576,7 +583,7 @@ void InfEngineNgraphNet::init(Target targetId) auto node = ngraph_function->output(i).get_node(); for (size_t j = 0; j < node->get_input_size(); ++j) { std::string name = node->input_value(j).get_node()->get_friendly_name(); - auto iter = std::find(requestedOutputs.begin(), requestedOutputs.end(), name); + auto iter = requestedOutputs.find(name); if (iter != requestedOutputs.end()) { requestedOutputs.erase(iter); cnn.addOutput(name); @@ -584,10 +591,6 @@ void InfEngineNgraphNet::init(Target targetId) } } } - for (const auto& name : requestedOutputs) - { - cnn.addOutput(name); - } for (const auto& it : cnn.getInputsInfo()) { @@ -632,9 +635,6 @@ ngraph::ParameterVector InfEngineNgraphNet::setInputs(const std::vector return current_inp; } -void InfEngineNgraphNet::setUnconnectedNodes(Ptr& node) { - unconnectedNodes.insert(node->node); -} void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) { diff --git a/modules/dnn/src/ie_ngraph.hpp b/modules/dnn/src/ie_ngraph.hpp index bb593833ff..0d287a22a5 100644 --- a/modules/dnn/src/ie_ngraph.hpp +++ b/modules/dnn/src/ie_ngraph.hpp @@ -37,7 +37,7 @@ public: InfEngineNgraphNet(detail::NetImplBase& netImpl); InfEngineNgraphNet(detail::NetImplBase& netImpl, InferenceEngine::CNNNetwork& net); - void addOutput(const std::string& name); + void addOutput(const Ptr& node); bool isInitialized(); void init(Target targetId); @@ -47,7 +47,6 @@ public: void initPlugin(InferenceEngine::CNNNetwork& net); ngraph::ParameterVector setInputs(const std::vector& inputs, const std::vector& names); - void setUnconnectedNodes(Ptr& node); void addBlobs(const std::vector >& ptrs); void createNet(Target targetId); @@ -88,8 +87,7 @@ public: InferenceEngine::CNNNetwork cnn; bool hasNetOwner; - std::vector requestedOutputs; - std::unordered_set> unconnectedNodes; + std::unordered_map > requestedOutputs; std::map outputsDesc; }; From 1da48beeec8af53c1540e4571f5c06b3f771ff19 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sat, 5 Feb 2022 16:16:45 +0000 Subject: [PATCH 9/9] dnn(ngraph): fix output names --- modules/dnn/src/dnn.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 82f814131e..2e2112064e 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -2235,12 +2235,15 @@ struct Net::Impl : public detail::NetImplBase { CV_LOG_DEBUG(NULL, "DNN/IE: wrap layer " << ld.name << "@" << ld.type << " - outputs: " << ld.outputBlobsWrappers.size()); node = layer->initNgraph(ld.inputBlobsWrappers, inputNodes); - // FIXIT doesn't work with multiple outputs (set name is applied to the same node) +#if 0 // FIXIT doesn't work with multiple outputs (set name is applied to the same node) for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i) { InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.outputBlobsWrappers[i]); node.dynamicCast()->setName(dataPtr->getName()); } +#else + node.dynamicCast()->setName(layer->name); +#endif } else {