diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e69e3ac17..019f918896 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -276,6 +276,9 @@ OCV_OPTION(WITH_HALIDE "Include Halide support" OFF OCV_OPTION(WITH_INF_ENGINE "Include Intel Inference Engine support" OFF VISIBLE_IF TRUE VERIFY INF_ENGINE_TARGET) +OCV_OPTION(WITH_NGRAPH "Include nGraph support" WITH_INF_ENGINE + VISIBLE_IF TRUE + VERIFY TARGET ngraph::ngraph) OCV_OPTION(WITH_JASPER "Include JPEG2K support" ON VISIBLE_IF NOT IOS VERIFY HAVE_JASPER) @@ -1489,12 +1492,37 @@ if(WITH_INF_ENGINE OR INF_ENGINE_TARGET) ) get_target_property(_inc ${ie_target} INTERFACE_INCLUDE_DIRECTORIES) status(" Inference Engine:" "${__msg}") - status(" libs:" "${_lib}") - status(" includes:" "${_inc}") + status(" * libs:" "${_lib}") + status(" * includes:" "${_inc}") else() status(" Inference Engine:" "NO") endif() endif() +if(WITH_NGRAPH OR HAVE_NGRAPH) + if(HAVE_NGRAPH) + set(__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() if(WITH_EIGEN OR HAVE_EIGEN) status(" Eigen:" HAVE_EIGEN THEN "YES (ver ${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION})" ELSE NO) diff --git a/cmake/OpenCVDetectInferenceEngine.cmake b/cmake/OpenCVDetectInferenceEngine.cmake index 1302489c20..328ac462d2 100644 --- a/cmake/OpenCVDetectInferenceEngine.cmake +++ b/cmake/OpenCVDetectInferenceEngine.cmake @@ -35,6 +35,15 @@ function(add_custom_ie_build _inc _lib _lib_rel _lib_dbg _msg) IMPORTED_IMPLIB_DEBUG "${_lib_dbg}" INTERFACE_INCLUDE_DIRECTORIES "${_inc}" ) + + find_library(ie_builder_custom_lib "inference_engine_nn_builder" PATHS "${INF_ENGINE_LIB_DIRS}" NO_DEFAULT_PATH) + if(EXISTS "${ie_builder_custom_lib}") + add_library(inference_engine_nn_builder UNKNOWN IMPORTED) + set_target_properties(inference_engine_nn_builder PROPERTIES + IMPORTED_LOCATION "${ie_builder_custom_lib}" + ) + endif() + if(NOT INF_ENGINE_RELEASE VERSION_GREATER "2018050000") find_library(INF_ENGINE_OMP_LIBRARY iomp5 PATHS "${INF_ENGINE_OMP_DIR}" NO_DEFAULT_PATH) if(NOT INF_ENGINE_OMP_LIBRARY) @@ -44,7 +53,12 @@ function(add_custom_ie_build _inc _lib _lib_rel _lib_dbg _msg) endif() endif() set(INF_ENGINE_VERSION "Unknown" CACHE STRING "") - set(INF_ENGINE_TARGET inference_engine PARENT_SCOPE) + set(INF_ENGINE_TARGET inference_engine) + if(TARGET inference_engine_nn_builder) + list(APPEND INF_ENGINE_TARGET inference_engine_nn_builder) + set(_msg "${_msg}, with IE NN Builder API") + endif() + set(INF_ENGINE_TARGET "${INF_ENGINE_TARGET}" PARENT_SCOPE) message(STATUS "Detected InferenceEngine: ${_msg}") endfunction() @@ -54,7 +68,7 @@ find_package(InferenceEngine QUIET) if(InferenceEngine_FOUND) set(INF_ENGINE_TARGET ${InferenceEngine_LIBRARIES}) set(INF_ENGINE_VERSION "${InferenceEngine_VERSION}" CACHE STRING "") - message(STATUS "Detected InferenceEngine: cmake package") + message(STATUS "Detected InferenceEngine: cmake package (${InferenceEngine_VERSION})") endif() if(NOT INF_ENGINE_TARGET AND INF_ENGINE_LIB_DIRS AND INF_ENGINE_INCLUDE_DIRS) @@ -94,3 +108,15 @@ if(INF_ENGINE_TARGET) INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}" ) endif() + +if(WITH_NGRAPH) + find_package(ngraph QUIET) + if(ngraph_FOUND) + ocv_assert(TARGET ngraph::ngraph) + if(INF_ENGINE_RELEASE VERSION_LESS "2019039999") + message(WARNING "nGraph is not tested with current InferenceEngine version: INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}") + endif() + message(STATUS "Detected ngraph: cmake package (${ngraph_VERSION})") + set(HAVE_NGRAPH ON) + endif() +endif() diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt index 165eb9f99a..7ed4f27cd6 100644 --- a/modules/dnn/CMakeLists.txt +++ b/modules/dnn/CMakeLists.txt @@ -74,6 +74,7 @@ endif() set(include_dirs ${fw_inc}) set(sources_options "") + set(libs libprotobuf ${LAPACK_LIBRARIES}) if(OPENCV_DNN_OPENCL AND HAVE_OPENCL) list(APPEND include_dirs ${OPENCL_INCLUDE_DIRS}) @@ -87,10 +88,20 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") ocv_append_source_files_cxx_compiler_options(fw_srcs "-Wno-inconsistent-missing-override") # Clang endif() + +set(dnn_runtime_libs "") +if(INF_ENGINE_TARGET) + list(APPEND dnn_runtime_libs ${INF_ENGINE_TARGET}) +endif() +if(HAVE_NGRAPH) + add_definitions(-DHAVE_DNN_NGRAPH) + list(APPEND dnn_runtime_libs ngraph::ngraph) +endif() + ocv_glob_module_sources(${sources_options} SOURCES ${fw_srcs}) -ocv_create_module(${libs} ${INF_ENGINE_TARGET}) +ocv_create_module(${libs} ${dnn_runtime_libs}) ocv_add_samples() -ocv_add_accuracy_tests(${INF_ENGINE_TARGET}) +ocv_add_accuracy_tests(${dnn_runtime_libs}) set(perf_path "${CMAKE_CURRENT_LIST_DIR}/perf") file(GLOB_RECURSE perf_srcs "${perf_path}/*.cpp") diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index 9f966eec71..a4bbffcf41 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -47,9 +47,9 @@ #include "opencv2/core/async.hpp" #if !defined CV_DOXYGEN && !defined CV_STATIC_ANALYSIS && !defined CV_DNN_DONT_ADD_EXPERIMENTAL_NS -#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_34_v14 { +#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_34_v15 { #define CV__DNN_EXPERIMENTAL_NS_END } -namespace cv { namespace dnn { namespace experimental_dnn_34_v14 { } using namespace experimental_dnn_34_v14; }} +namespace cv { namespace dnn { namespace experimental_dnn_34_v15 { } using namespace experimental_dnn_34_v15; }} #else #define CV__DNN_EXPERIMENTAL_NS_BEGIN #define CV__DNN_EXPERIMENTAL_NS_END @@ -74,10 +74,18 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN //! DNN_BACKEND_DEFAULT equals to DNN_BACKEND_INFERENCE_ENGINE if //! OpenCV is built with Intel's Inference Engine library or //! DNN_BACKEND_OPENCV otherwise. - DNN_BACKEND_DEFAULT, + DNN_BACKEND_DEFAULT = 0, DNN_BACKEND_HALIDE, - DNN_BACKEND_INFERENCE_ENGINE, //!< Intel's Inference Engine computational backend. - DNN_BACKEND_OPENCV + DNN_BACKEND_INFERENCE_ENGINE, //!< Intel's Inference Engine computational backend + //!< @sa setInferenceEngineBackendType + DNN_BACKEND_OPENCV, + // OpenCV 4.x: DNN_BACKEND_VKCOM, + // OpenCV 4.x: DNN_BACKEND_CUDA, + +#ifdef __OPENCV_BUILD + DNN_BACKEND_INFERENCE_ENGINE_NGRAPH = 1000000, // internal - use DNN_BACKEND_INFERENCE_ENGINE + setInferenceEngineBackendType() + DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, // internal - use DNN_BACKEND_INFERENCE_ENGINE + setInferenceEngineBackendType() +#endif }; /** @@ -278,6 +286,8 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN virtual Ptr initInfEngine(const std::vector > &inputs); + virtual Ptr initNgraph(const std::vector > &inputs, const std::vector >& nodes); + /** * @brief Automatic Halide scheduling based on layer hyper-parameters. * @param[in] node Backend node with Halide functions. diff --git a/modules/dnn/include/opencv2/dnn/utils/inference_engine.hpp b/modules/dnn/include/opencv2/dnn/utils/inference_engine.hpp index 0211096ae5..cda2f9bfad 100644 --- a/modules/dnn/include/opencv2/dnn/utils/inference_engine.hpp +++ b/modules/dnn/include/opencv2/dnn/utils/inference_engine.hpp @@ -14,6 +14,27 @@ namespace cv { namespace dnn { CV__DNN_EXPERIMENTAL_NS_BEGIN +/* Values for 'OPENCV_DNN_BACKEND_INFERENCE_ENGINE_TYPE' parameter */ +#define CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API "NN_BUILDER" +#define CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH "NGRAPH" + +/** @brief Returns Inference Engine internal backend API. + * + * See values of `CV_DNN_BACKEND_INFERENCE_ENGINE_*` macros. + * + * Default value is controlled through `OPENCV_DNN_BACKEND_INFERENCE_ENGINE_TYPE` runtime parameter (environment variable). + */ +CV_EXPORTS_W cv::String getInferenceEngineBackendType(); + +/** @brief Specify Inference Engine internal backend API. + * + * See values of `CV_DNN_BACKEND_INFERENCE_ENGINE_*` macros. + * + * @returns previous value of internal backend API + */ +CV_EXPORTS_W cv::String setInferenceEngineBackendType(const cv::String& newBackendType); + + /** @brief Release a Myriad device (binded by OpenCV). * * Single Myriad device cannot be shared across multiple processes which uses diff --git a/modules/dnn/perf/perf_net.cpp b/modules/dnn/perf/perf_net.cpp index c1905cb9bf..c0628dba96 100644 --- a/modules/dnn/perf/perf_net.cpp +++ b/modules/dnn/perf/perf_net.cpp @@ -100,7 +100,7 @@ PERF_TEST_P_(DNNTestNetwork, SqueezeNet_v1_1) PERF_TEST_P_(DNNTestNetwork, Inception_5h) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) throw SkipTestException(""); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) throw SkipTestException(""); processNet("dnn/tensorflow_inception_graph.pb", "", "inception_5h.yml", Mat(cv::Size(224, 224), CV_32FC3), "softmax2"); @@ -108,7 +108,7 @@ PERF_TEST_P_(DNNTestNetwork, Inception_5h) PERF_TEST_P_(DNNTestNetwork, ENet) { - if ((backend == DNN_BACKEND_INFERENCE_ENGINE) || + if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) || (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)) throw SkipTestException(""); processNet("dnn/Enet-model-best.net", "", "enet.yml", @@ -126,7 +126,7 @@ PERF_TEST_P_(DNNTestNetwork, OpenFace) if (backend == DNN_BACKEND_HALIDE) throw SkipTestException(""); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) throw SkipTestException(""); #endif processNet("dnn/openface_nn4.small2.v1.t7", "", "", @@ -168,7 +168,7 @@ PERF_TEST_P_(DNNTestNetwork, DenseNet_121) PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages) { if (backend == DNN_BACKEND_HALIDE || - (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)) + (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)) throw SkipTestException(""); // The same .caffemodel but modified .prototxt // See https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/src/openpose/pose/poseParameters.cpp @@ -219,15 +219,15 @@ PERF_TEST_P_(DNNTestNetwork, FastNeuralStyle_eccv16) PERF_TEST_P_(DNNTestNetwork, Inception_v2_Faster_RCNN) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019010000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) throw SkipTestException("Test is disabled in OpenVINO 2019R1"); #endif #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019020000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) throw SkipTestException("Test is disabled in OpenVINO 2019R2"); #endif if (backend == DNN_BACKEND_HALIDE || - (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU) || + (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) || (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)) throw SkipTestException(""); processNet("dnn/faster_rcnn_inception_v2_coco_2018_01_28.pb", diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index f134cf6813..ad2e52766b 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -42,6 +42,8 @@ #include "precomp.hpp" #include "op_halide.hpp" #include "op_inf_engine.hpp" +#include "ie_ngraph.hpp" + #include "halide_scheduler.hpp" #include #include @@ -98,11 +100,9 @@ public: return impl; } - static inline bool checkIETarget(int target) +#ifdef HAVE_INF_ENGINE + static inline bool checkIETarget(Target target) { -#ifndef HAVE_INF_ENGINE - return false; -#else cv::dnn::Net net; cv::dnn::LayerParams lp; lp.set("kernel_size", 1); @@ -120,13 +120,14 @@ public: { net.forward(); } - catch(...) + catch(const std::exception& e) { + CV_LOG_INFO(NULL, "checkIETarget(" << (int)target << ") has failed with message: " << e.what()); return false; } return true; -#endif } +#endif private: BackendRegistry() @@ -140,21 +141,37 @@ private: #endif // HAVE_HALIDE #ifdef HAVE_INF_ENGINE - if (checkIETarget(DNN_TARGET_CPU)) - backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU)); - if (checkIETarget(DNN_TARGET_MYRIAD)) - backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD)); + if (checkIETarget(DNN_TARGET_CPU)) { + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, DNN_TARGET_CPU)); +#ifdef HAVE_DNN_NGRAPH + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, DNN_TARGET_CPU)); +#endif + } + if (checkIETarget(DNN_TARGET_MYRIAD)) { + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, DNN_TARGET_MYRIAD)); +#ifdef HAVE_DNN_NGRAPH + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, DNN_TARGET_MYRIAD)); +#endif + } if (checkIETarget(DNN_TARGET_FPGA)) - backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_FPGA)); -# ifdef HAVE_OPENCL + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, DNN_TARGET_FPGA)); +#ifdef HAVE_OPENCL if (cv::ocl::useOpenCL() && ocl::Device::getDefault().isIntel()) { - if (checkIETarget(DNN_TARGET_OPENCL)) - backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL)); - if (checkIETarget(DNN_TARGET_OPENCL_FP16)) - backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16)); + if (checkIETarget(DNN_TARGET_OPENCL)) { + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, DNN_TARGET_OPENCL)); +#ifdef HAVE_DNN_NGRAPH + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, DNN_TARGET_OPENCL)); +#endif + } + if (checkIETarget(DNN_TARGET_OPENCL_FP16)) { + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, DNN_TARGET_OPENCL_FP16)); +#ifdef HAVE_DNN_NGRAPH + backends.push_back(std::make_pair(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, DNN_TARGET_OPENCL_FP16)); +#endif + } } -# endif +#endif #endif // HAVE_INF_ENGINE #ifdef HAVE_OPENCL @@ -181,6 +198,10 @@ std::vector getAvailableTargets(Backend be) { if (be == DNN_BACKEND_DEFAULT) be = (Backend)PARAM_DNN_BACKEND_DEFAULT; +#ifdef HAVE_INF_ENGINE + if (be == DNN_BACKEND_INFERENCE_ENGINE) + be = getInferenceEngineBackendTypeParam(); +#endif std::vector result; const BackendRegistry::BackendsList all_backends = getAvailableBackends(); @@ -351,6 +372,7 @@ void imagesFromBlob(const cv::Mat& blob_, OutputArrayOfArrays images_) } } +#ifdef HAVE_OPENCL class OpenCLBackendWrapper : public BackendWrapper { public: @@ -440,6 +462,7 @@ private: Mat* host; bool hostDirty; }; +#endif struct LayerPin { @@ -536,7 +559,7 @@ struct DataLayer : public Layer virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && inputsData.size() == 1); + (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && inputsData.size() == 1); } void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE @@ -706,9 +729,9 @@ struct DataLayer : public Layer } } +#ifdef HAVE_INF_ENGINE virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE { -#ifdef HAVE_INF_ENGINE CV_CheckEQ(inputsData.size(), (size_t)1, ""); CV_CheckEQ(inputsData[0].dims, 4, ""); const size_t numChannels = inputsData[0].size[1]; @@ -737,9 +760,8 @@ struct DataLayer : public Layer addConstantData("weights", weights, ieLayer); addConstantData("biases", biases, ieLayer); return Ptr(new InfEngineBackendNode(ieLayer)); -#endif // HAVE_INF_ENGINE - return Ptr(); } +#endif // HAVE_INF_ENGINE std::vector outNames; // Preprocessing parameters for each network's input. @@ -980,10 +1002,12 @@ static Ptr wrapMat(int backendId, int targetId, cv::Mat& m) { if (targetId == DNN_TARGET_CPU) return Ptr(); +#ifdef HAVE_OPENCL else if (IS_DNN_OPENCL_TARGET(targetId)) return OpenCLBackendWrapper::create(m); +#endif else - CV_Error(Error::StsNotImplemented, "Unknown target identifier"); + CV_Error(Error::StsNotImplemented, "Unknown/unsupported target identifier"); } else if (backendId == DNN_BACKEND_HALIDE) { @@ -992,16 +1016,25 @@ static Ptr wrapMat(int backendId, int targetId, cv::Mat& m) return Ptr(new HalideBackendWrapper(targetId, m)); #endif // HAVE_HALIDE } - else if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { - CV_Assert(haveInfEngine()); #ifdef HAVE_INF_ENGINE return Ptr(new InfEngineBackendWrapper(targetId, m)); -#endif // HAVE_INF_ENGINE +#else + CV_Error(Error::StsNotImplemented, "This OpenCV version is built without Inference Engine API support"); +#endif + } + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + { +#ifdef HAVE_DNN_NGRAPH + return Ptr(new NgraphBackendWrapper(targetId, m)); +#else + CV_Error(Error::StsNotImplemented, "This OpenCV version is built without support of Inference Engine + nGraph"); +#endif } else CV_Error(Error::StsNotImplemented, "Unknown backend identifier"); - return Ptr(); + return Ptr(); // TODO Error? } struct Net::Impl @@ -1064,17 +1097,25 @@ struct Net::Impl Ptr baseBuffer = backendWrappers[data]; if (preferableBackend == DNN_BACKEND_OPENCV) { +#ifdef HAVE_OPENCL CV_Assert(IS_DNN_OPENCL_TARGET(preferableTarget)); return OpenCLBackendWrapper::create(baseBuffer, host); +#else + CV_Error(Error::StsInternal, ""); +#endif } else if (preferableBackend == DNN_BACKEND_HALIDE) { CV_Assert(haveHalide()); - #ifdef HAVE_HALIDE +#ifdef HAVE_HALIDE return Ptr(new HalideBackendWrapper(baseBuffer, shape)); - #endif // HAVE_HALIDE +#endif } - else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE) + else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + { + return wrapMat(preferableBackend, preferableTarget, host); + } + else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) { return wrapMat(preferableBackend, preferableTarget, host); } @@ -1167,6 +1208,10 @@ struct Net::Impl if (preferableBackend == DNN_BACKEND_DEFAULT) preferableBackend = (Backend)PARAM_DNN_BACKEND_DEFAULT; +#ifdef HAVE_INF_ENGINE + if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE) + preferableBackend = getInferenceEngineBackendTypeParam(); +#endif CV_Assert(preferableBackend != DNN_BACKEND_OPENCV || preferableTarget == DNN_TARGET_CPU || @@ -1175,12 +1220,17 @@ struct Net::Impl CV_Assert(preferableBackend != DNN_BACKEND_HALIDE || preferableTarget == DNN_TARGET_CPU || preferableTarget == DNN_TARGET_OPENCL); - CV_Assert(preferableBackend != DNN_BACKEND_INFERENCE_ENGINE || + if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || + preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + { + CV_Assert( preferableTarget == DNN_TARGET_CPU || preferableTarget == DNN_TARGET_OPENCL || preferableTarget == DNN_TARGET_OPENCL_FP16 || preferableTarget == DNN_TARGET_MYRIAD || - preferableTarget == DNN_TARGET_FPGA); + preferableTarget == DNN_TARGET_FPGA + ); + } if (!netWasAllocated || this->blobsToKeep != blobsToKeep_) { if (preferableBackend == DNN_BACKEND_OPENCV && IS_DNN_OPENCL_TARGET(preferableTarget)) @@ -1360,8 +1410,22 @@ struct Net::Impl CV_Assert(preferableTarget == DNN_TARGET_CPU || IS_DNN_OPENCL_TARGET(preferableTarget)); else if (preferableBackend == DNN_BACKEND_HALIDE) initHalideBackend(); - else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE) + else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + { +#ifdef HAVE_INF_ENGINE initInfEngineBackend(); +#else + CV_Assert(false && "This OpenCV version is built without Inference Engine API support"); +#endif + } + else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + { +#ifdef HAVE_DNN_NGRAPH + initNgraphBackend(); +#else + CV_Error(Error::StsNotImplemented, "This OpenCV version is built without support of Inference Engine + nGraph"); +#endif + } else CV_Error(Error::StsNotImplemented, "Unknown backend identifier"); } @@ -1427,6 +1491,7 @@ struct Net::Impl // layers from default backend or layers from different graphs. void addInfEngineNetOutputs(LayerData &ld) { + CV_TRACE_FUNCTION(); Ptr layerNet; if (ld.backendNodes.find(preferableBackend) != ld.backendNodes.end()) { @@ -1457,13 +1522,11 @@ struct Net::Impl } } } -#endif // HAVE_INF_ENGINE void initInfEngineBackend() { CV_TRACE_FUNCTION(); - CV_Assert_N(preferableBackend == DNN_BACKEND_INFERENCE_ENGINE, haveInfEngine()); -#ifdef HAVE_INF_ENGINE + CV_Assert_N(preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, haveInfEngine()); MapIdToLayerData::iterator it; Ptr net; @@ -1538,7 +1601,7 @@ struct Net::Impl ld.skip = true; } layers[lastLayerId].skip = false; - ieNode->net->init(preferableTarget); + ieNode->net->init((Target)preferableTarget); return; } @@ -1713,12 +1776,272 @@ struct Net::Impl if (!ieNode->net->isInitialized()) { - ieNode->net->init(preferableTarget); + ieNode->net->init((Target)preferableTarget); ld.skip = false; } } + } #endif // HAVE_INF_ENGINE + + +#ifdef HAVE_DNN_NGRAPH + void addNgraphOutputs(LayerData &ld) + { + CV_TRACE_FUNCTION(); + + Ptr layerNet; + auto it = ld.backendNodes.find(preferableBackend); + if (it != ld.backendNodes.end()) + { + Ptr node = it->second; + if (!node.empty()) + { + Ptr ieNode = node.dynamicCast(); + CV_Assert(!ieNode.empty()); CV_Assert(!ieNode->net.empty()); + layerNet = ieNode->net; + } + } + + for (int i = 0; i < ld.inputBlobsId.size(); ++i) + { + LayerData &inpLd = layers[ld.inputBlobsId[i].lid]; + Ptr inpNode = inpLd.backendNodes[preferableBackend]; + if (!inpNode.empty()) + { + Ptr ieInpNode = inpNode.dynamicCast(); + CV_Assert(!ieInpNode.empty()); CV_Assert(!ieInpNode->net.empty()); + if (layerNet != ieInpNode->net) + { + ieInpNode->net->addOutput(ieInpNode->node->get_friendly_name()); + ieInpNode->net->setUnconnectedNodes(ieInpNode); + } + } + } + } + + void initNgraphBackend() + { + CV_TRACE_FUNCTION(); + CV_Assert_N(preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, haveInfEngine()); + + MapIdToLayerData::iterator it; + Ptr net; + + for (it = layers.begin(); it != layers.end(); ++it) + { + LayerData &ld = it->second; + if (ld.id == 0) + { + CV_Assert((netInputLayer->outNames.empty() && ld.outputBlobsWrappers.size() == 1) || + (netInputLayer->outNames.size() == ld.outputBlobsWrappers.size())); + for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i) + { + InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.outputBlobsWrappers[i]); + dataPtr->setName(netInputLayer->outNames.empty() ? ld.name : netInputLayer->outNames[i]); + } + } + else + { + for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i) + { + InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.outputBlobsWrappers[i]); + dataPtr->setName(ld.name); + } + } + } + + if (skipInfEngineInit) + { + Ptr node = layers[lastLayerId].backendNodes[preferableBackend]; + CV_Assert(!node.empty()); + + Ptr ieNode = node.dynamicCast(); + CV_Assert(!ieNode.empty()); + + for (it = layers.begin(); it != layers.end(); ++it) + { + LayerData &ld = it->second; + if (ld.id == 0) + { + for (int i = 0; i < ld.inputBlobsWrappers.size(); ++i) + { + InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.inputBlobsWrappers[i]); + dataPtr->setName(netInputLayer->outNames[i]); + } + } + else + { + for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i) + { + InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.outputBlobsWrappers[i]); + dataPtr->setName(ld.name); + } + } + ieNode->net->addBlobs(ld.inputBlobsWrappers); + ieNode->net->addBlobs(ld.outputBlobsWrappers); + ld.skip = true; + } + layers[lastLayerId].skip = false; + ieNode->net->init((Target)preferableTarget); + return; + } + + // Build Inference Engine networks from sets of layers that support this + // backend. Split a whole model on several Inference Engine networks if + // some of layers are not implemented. + for (it = layers.begin(); it != layers.end(); ++it) + { + LayerData &ld = it->second; + + if (ld.id == 0 && ld.skip) + continue; + + bool fused = ld.skip; + Ptr layer = ld.layerInstance; + if (!fused && !layer->supportBackend(preferableBackend)) + { + addNgraphOutputs(ld); + net = Ptr(); + layer->preferableTarget = DNN_TARGET_CPU; + + for (int i = 0; i < ld.inputBlobsId.size(); ++i) + { + LayerData &inpLd = layers[ld.inputBlobsId[i].lid]; + Ptr inpNode = inpLd.backendNodes[preferableBackend]; + if (!inpNode.empty()) { + Ptr ieNode = inpNode.dynamicCast(); + ieNode->net->setUnconnectedNodes(ieNode); + } + } + continue; + } + ld.skip = true; // Initially skip all Inference Engine supported layers. + + // Create a new network if one of inputs from different Inference Engine graph. + std::vector> inputNodes; + for (int i = 0; i < ld.inputBlobsId.size(); ++i) + { + // Layer_Test_ROIPooling.Accuracy has 2 inputs inpLD = 0, 0 -> has 4 inputNodes (input, rois, input, rois) + if (inputNodes.size() == ld.inputBlobsId.size()) { + break; + } + LayerData &inpLd = layers[ld.inputBlobsId[i].lid]; + Ptr inpNode = inpLd.backendNodes[preferableBackend]; + if (!inpNode.empty()) + { + Ptr ieInpNode = inpNode.dynamicCast(); + CV_Assert(!ieInpNode.empty()); CV_Assert(!ieInpNode->net.empty()); + if (ieInpNode->net == net && !fused) { + inputNodes.push_back(inpNode); + continue; + } + } + + if (net.empty()) { + net = Ptr(new InfEngineNgraphNet()); + } + + if (!fused) { + std::vector inputNames; + std::vector inputs; + + auto curr_pos = inpLd.consumers.begin(); + auto compare = [&ld] (const LayerPin& lp) { return lp.lid == ld.id; }; + auto cons = curr_pos; + while ((cons = std::find_if(curr_pos, inpLd.consumers.end(), compare)) != + inpLd.consumers.end()) { + int cons_inp = cons->oid; + Ptr inpWrapper = inpLd.outputBlobsWrappers[cons_inp]. + dynamicCast(); + auto iter = std::find(inputNames.begin(), inputNames.end(), + inpWrapper->dataPtr->getName()); + if (iter == inputNames.end()) { + inputNames.push_back(inpWrapper->dataPtr->getName()); + inputs.push_back(inpLd.outputBlobs[cons_inp]); + } + curr_pos = cons + 1; + } + + auto inps = net->setInputs(inputs, inputNames); + for (auto& inp : inps) { + inputNodes.emplace_back(Ptr(new InfEngineNgraphNode(inp))); + } + } + } + + Ptr node; + if (!net.empty()) + { + if (fused) + { + bool inPlace = ld.inputBlobsId.size() == 1 && ld.outputBlobs.size() == 1 && + ld.inputBlobs[0]->data == ld.outputBlobs[0].data; + CV_Assert(inPlace); + node = layers[ld.inputBlobsId[0].lid].backendNodes[preferableBackend]; + ld.inputBlobsWrappers = layers[ld.inputBlobsId[0].lid].inputBlobsWrappers; + } + } + else { + net = Ptr(new InfEngineNgraphNet()); + } + + if (!fused) + { + CV_Assert(!inputNodes.empty()); + node = layer->initNgraph(ld.inputBlobsWrappers, inputNodes); + for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i) + { + InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.outputBlobsWrappers[i]); + node.dynamicCast()->setName(dataPtr->getName()); + } + } + else if (node.empty()) + continue; + + ld.backendNodes[preferableBackend] = node; + + Ptr ieNode = node.dynamicCast(); + CV_Assert(!ieNode.empty()); + ieNode->net = net; + + if (ld.consumers.empty()) { + // TF EAST_text_detection + ieNode->net->setUnconnectedNodes(ieNode); + } + ieNode->net->setNodePtr(&ieNode->node); + + net->addBlobs(ld.inputBlobsWrappers); + net->addBlobs(ld.outputBlobsWrappers); + addNgraphOutputs(ld); + } + + // Initialize all networks. + for (MapIdToLayerData::reverse_iterator it = layers.rbegin(); it != layers.rend(); ++it) + { + LayerData &ld = it->second; + auto iter = ld.backendNodes.find(preferableBackend); + if (iter == ld.backendNodes.end()) + continue; + + Ptr& node = iter->second; + if (node.empty()) + continue; + + Ptr ieNode = node.dynamicCast(); + if (ieNode.empty()) + continue; + + CV_Assert(!ieNode->net.empty()); + + if (!ieNode->net->isInitialized()) + { + ieNode->net->setUnconnectedNodes(ieNode); + ieNode->net->createNet((Target)preferableTarget); + ld.skip = false; + } + } } +#endif // HAVE_DNN_NGRAPH void allocateLayer(int lid, const LayersShapesMap& layersShapes) { @@ -1835,12 +2158,13 @@ struct Net::Impl void fuseLayers(const std::vector& blobsToKeep_) { - if( !fusion || (preferableBackend != DNN_BACKEND_OPENCV && - preferableBackend != DNN_BACKEND_INFERENCE_ENGINE)) - return; - CV_TRACE_FUNCTION(); + if(!fusion || (preferableBackend != DNN_BACKEND_OPENCV && + preferableBackend != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && + preferableBackend != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)) + return; + // 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 std::set pinsToKeep(blobsToKeep_.begin(), @@ -2058,6 +2382,7 @@ struct Net::Impl { Mat& output = ld.outputBlobs[0]; UMat umat_output; +#ifdef HAVE_OPENCL if (!ld.outputBlobsWrappers.empty() && (preferableBackend == DNN_BACKEND_OPENCV && IS_DNN_OPENCL_TARGET(preferableTarget))) { @@ -2082,6 +2407,7 @@ struct Net::Impl umat_outputBlobs = OpenCLBackendWrapper::getUMatVector(ld.outputBlobsWrappers); umat_output = umat_outputBlobs[0]; } +#endif // TODO: in general, this optimization can always be done, but // many layers currently check that the input/output blobs are @@ -2118,6 +2444,7 @@ struct Net::Impl // Allocate new memory to prevent collisions during memory // reusing (see https://github.com/opencv/opencv/pull/10456). output = output.clone(); +#ifdef HAVE_OPENCL if (preferableBackend == DNN_BACKEND_OPENCV && IS_DNN_OPENCL_TARGET(preferableTarget)) { @@ -2126,6 +2453,7 @@ struct Net::Impl umats[0] = umat_output; OpenCLBackendWrapper::update(ld.outputBlobsWrappers, umats); } +#endif Range chrange[] = { Range::all(), Range::all(), Range::all(), Range::all() }; int ofs = 0; for( i = 0; i < ninputs; i++ ) @@ -2142,12 +2470,14 @@ struct Net::Impl CV_Assert(output_slice.isContinuous() && output_slice.size == curr_output.size); Mat* oldPtr = &curr_output; curr_output = output_slice; +#ifdef HAVE_OPENCL if (preferableBackend == DNN_BACKEND_OPENCV && IS_DNN_OPENCL_TARGET(preferableTarget)) { std::vector umats(inp_i_data->outputBlobsWrappers.size()); umats[pin.oid] = umat_output(chrange); OpenCLBackendWrapper::update(inp_i_data->outputBlobsWrappers, umats); } +#endif // Layers that refer old input Mat will refer to the // new data but the same Mat object. CV_Assert_N(curr_output.data == output_slice.data, oldPtr == &curr_output); @@ -2231,6 +2561,7 @@ struct Net::Impl CV_Error(Error::StsNotImplemented, format("Layer \"%s\" of type \"%s\" unsupported on OpenCV backend", ld.name.c_str(), ld.type.c_str())); +#ifdef HAVE_OPENCL if (preferableBackend == DNN_BACKEND_OPENCV && IS_DNN_OPENCL_TARGET(preferableTarget)) { std::vector umat_inputBlobs = OpenCLBackendWrapper::getUMatVector(ld.inputBlobsWrappers); @@ -2305,6 +2636,7 @@ struct Net::Impl OpenCLBackendWrapper::update(ld.outputBlobsWrappers, umat_outputBlobs); } else +#endif { for (int i = 0, n = ld.inputBlobsWrappers.size(); i < n; ++i) { @@ -2384,10 +2716,14 @@ struct Net::Impl { forwardHalide(ld.outputBlobsWrappers, node); } - else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE) + else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { forwardInfEngine(ld.outputBlobsWrappers, node, isAsync); } + else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + { + forwardNgraph(ld.outputBlobsWrappers, node, isAsync); + } else { CV_Error(Error::StsNotImplemented, "Unknown backend identifier"); @@ -2550,13 +2886,23 @@ struct Net::Impl // Transfer data to CPU if it's require. ld.outputBlobsWrappers[pin.oid]->copyToHost(); } - CV_Assert(preferableBackend == DNN_BACKEND_INFERENCE_ENGINE); + CV_Assert(preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); - Ptr wrapper = ld.outputBlobsWrappers[pin.oid].dynamicCast(); - return std::move(wrapper->futureMat); + if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { + Ptr wrapper = ld.outputBlobsWrappers[pin.oid].dynamicCast(); + return std::move(wrapper->futureMat); + } + else if (preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + { +#ifdef HAVE_DNN_NGRAPH + Ptr wrapper = ld.outputBlobsWrappers[pin.oid].dynamicCast(); + return std::move(wrapper->futureMat); #else - CV_Error(Error::StsNotImplemented, "DNN_BACKEND_INFERENCE_ENGINE backend is required"); + CV_Error(Error::StsNotImplemented, "This OpenCV version is built without support of Inference Engine + nGraph"); #endif + } +#endif // HAVE_INF_ENGINE + CV_Error(Error::StsNotImplemented, "DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 backend is required"); } AsyncArray getBlobAsync(String outputName) @@ -2575,11 +2921,17 @@ Net Net::readFromModelOptimizer(const String& xml, const String& bin) #ifndef HAVE_INF_ENGINE CV_Error(Error::StsError, "Build OpenCV with Inference Engine to enable loading models from Model Optimizer."); #else + +#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R3) InferenceEngine::CNNNetReader reader; reader.ReadNetwork(xml); reader.ReadWeights(bin); InferenceEngine::CNNNetwork ieNet = reader.getNetwork(); +#else + InferenceEngine::Core& ie = getCore(); + InferenceEngine::CNNNetwork ieNet = ie.ReadNetwork(xml, bin); +#endif std::vector inputsNames; for (auto& it : ieNet.getInputsInfo()) @@ -2590,27 +2942,62 @@ Net Net::readFromModelOptimizer(const String& xml, const String& bin) Net cvNet; cvNet.setInputsNames(inputsNames); - Ptr backendNode(new InfEngineBackendNode(InferenceEngine::Builder::Layer(""))); - backendNode->net = Ptr(new InfEngineBackendNet(ieNet)); + Ptr backendNode; +#ifdef HAVE_DNN_NGRAPH + if (DNN_BACKEND_INFERENCE_ENGINE_NGRAPH == getInferenceEngineBackendTypeParam()) + { + auto fake_node = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + Ptr backendNodeNGraph(new InfEngineNgraphNode(fake_node)); + backendNodeNGraph->net = Ptr(new InfEngineNgraphNet(ieNet)); + backendNode = backendNodeNGraph; + } + else +#endif + { + Ptr backendNodeNN(new InfEngineBackendNode(InferenceEngine::Builder::Layer(""))); + backendNodeNN->net = Ptr(new InfEngineBackendNet(ieNet)); + backendNode = backendNodeNN; + } for (auto& it : ieNet.getOutputsInfo()) { - Ptr cvLayer(new InfEngineBackendLayer(ieNet)); - InferenceEngine::CNNLayerPtr ieLayer = ieNet.getLayerByName(it.first.c_str()); - CV_Assert(ieLayer); - LayerParams lp; int lid = cvNet.addLayer(it.first, "", lp); LayerData& ld = cvNet.impl->layers[lid]; - cvLayer->name = it.first; - cvLayer->type = ieLayer->type; - ld.layerInstance = cvLayer; - ld.backendNodes[DNN_BACKEND_INFERENCE_ENGINE] = backendNode; + +#ifdef HAVE_DNN_NGRAPH + if (DNN_BACKEND_INFERENCE_ENGINE_NGRAPH == getInferenceEngineBackendTypeParam()) + { + Ptr cvLayer(new NgraphBackendLayer(ieNet)); + + InferenceEngine::CNNLayerPtr ieLayer = ieNet.getLayerByName(it.first.c_str()); + CV_Assert(ieLayer); + + cvLayer->name = it.first; + cvLayer->type = ieLayer->type; + ld.layerInstance = cvLayer; + + ld.backendNodes[DNN_BACKEND_INFERENCE_ENGINE_NGRAPH] = backendNode; + } + else +#endif + { + Ptr cvLayer(new InfEngineBackendLayer(ieNet)); + + InferenceEngine::CNNLayerPtr ieLayer = ieNet.getLayerByName(it.first.c_str()); + CV_Assert(ieLayer); + + cvLayer->name = it.first; + cvLayer->type = ieLayer->type; + ld.layerInstance = cvLayer; + + ld.backendNodes[DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019] = backendNode; + } for (int i = 0; i < inputsNames.size(); ++i) cvNet.connect(0, i, lid, i); } - cvNet.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE); + cvNet.setPreferableBackend(getInferenceEngineBackendTypeParam()); cvNet.impl->skipInfEngineInit = true; return cvNet; @@ -2695,8 +3082,8 @@ AsyncArray Net::forwardAsync(const String& outputName) std::vector pins(1, impl->getPinByAlias(layerName)); impl->setUpNet(pins); - if (impl->preferableBackend != DNN_BACKEND_INFERENCE_ENGINE) - CV_Error(Error::StsNotImplemented, "Asynchronous forward for backend which is different from DNN_BACKEND_INFERENCE_ENGINE"); + if (!(impl->preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || impl->preferableBackend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)) + CV_Error(Error::StsNotImplemented, "DNN: Asynchronous forward is supported for Inference Engine backends only"); impl->isAsync = true; impl->forwardToLayer(impl->getLayerData(layerName)); @@ -2704,7 +3091,7 @@ AsyncArray Net::forwardAsync(const String& outputName) return impl->getBlobAsync(layerName); #else - CV_Error(Error::StsNotImplemented, "Asynchronous forward without C++11"); + CV_Error(Error::StsNotImplemented, "DNN: Asynchronous forward requires build with enabled C++11"); #endif // CV_CXX11 } @@ -2757,6 +3144,7 @@ void Net::forward(OutputArrayOfArrays outputBlobs, const String& outputName) { std::vector & outputvec = *(std::vector *)outputBlobs.getObj(); +#ifdef HAVE_OPENCL if (impl->preferableBackend == DNN_BACKEND_OPENCV && IS_DNN_OPENCL_TARGET(impl->preferableTarget)) { @@ -2771,6 +3159,7 @@ void Net::forward(OutputArrayOfArrays outputBlobs, const String& outputName) } } else +#endif { outputvec.resize(ld.outputBlobs.size()); for (int i = 0; i < outputvec.size(); ++i) @@ -2840,6 +3229,11 @@ void Net::setPreferableBackend(int backendId) CV_TRACE_FUNCTION(); CV_TRACE_ARG(backendId); +#ifdef HAVE_INF_ENGINE + if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + backendId = getInferenceEngineBackendTypeParam(); +#endif + if( impl->preferableBackend != backendId ) { impl->preferableBackend = backendId; @@ -3030,7 +3424,9 @@ String Net::dump() switch (prefBackend) { case DNN_BACKEND_DEFAULT: backend = "DEFAULT/"; break; case DNN_BACKEND_HALIDE: backend = "HALIDE/"; break; - case DNN_BACKEND_INFERENCE_ENGINE: backend = "DLIE/"; break; + case DNN_BACKEND_INFERENCE_ENGINE: // fallthru + case DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019: backend = "DLIE/"; break; + case DNN_BACKEND_INFERENCE_ENGINE_NGRAPH: backend = "NGRAPH/"; break; case DNN_BACKEND_OPENCV: backend = "OCV/"; break; } out << "digraph G {" << '\n'; @@ -3544,6 +3940,13 @@ Ptr Layer::initInfEngine(const std::vector > &) return Ptr(); } +Ptr Layer::initNgraph(const std::vector > & inputs, const std::vector >& nodes) +{ + CV_Error(Error::StsNotImplemented, "Inference Engine pipeline of " + type + + " layers is not defined."); + return Ptr(); +} + void Layer::applyHalideScheduler(Ptr& node, const std::vector &inputs, const std::vector &outputs, int targetId) const { diff --git a/modules/dnn/src/ie_ngraph.cpp b/modules/dnn/src/ie_ngraph.cpp new file mode 100644 index 0000000000..6b5c611c9a --- /dev/null +++ b/modules/dnn/src/ie_ngraph.cpp @@ -0,0 +1,679 @@ +// 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-2019, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. + +#include "precomp.hpp" +#include "ie_ngraph.hpp" + +#include + +#ifdef HAVE_DNN_NGRAPH +#include +#include +#endif // HAVE_DNN_NGRAPH + +#include +#include + +namespace cv { namespace dnn { + +#ifdef HAVE_DNN_NGRAPH + +// For networks with input layer which has an empty name, IE generates a name id[some_number]. +// OpenCV lets users use an empty input name and to prevent unexpected naming, +// we can use some predefined name. +static std::string kDefaultInpLayerName = "empty_inp_layer_name"; + +static std::vector > +ngraphWrappers(const std::vector >& ptrs) +{ + std::vector > wrappers(ptrs.size()); + for (int i = 0; i < ptrs.size(); ++i) + { + CV_Assert(!ptrs[i].empty()); + wrappers[i] = ptrs[i].dynamicCast(); + CV_Assert(!wrappers[i].empty()); + } + return wrappers; +} + +InfEngineNgraphNode::InfEngineNgraphNode(std::shared_ptr&& _node) + : BackendNode(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH), node(std::move(_node)) {} + +InfEngineNgraphNode::InfEngineNgraphNode(std::shared_ptr& _node) + : BackendNode(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH), node(_node) {} + +void InfEngineNgraphNode::setName(const std::string& name) { + node->set_friendly_name(name); +} + +InfEngineNgraphNet::InfEngineNgraphNet() +{ + hasNetOwner = false; + device_name = "CPU"; +} + +InfEngineNgraphNet::InfEngineNgraphNet(InferenceEngine::CNNNetwork& net) : cnn(net) +{ + hasNetOwner = true; + device_name = "CPU"; +} + +void InfEngineNgraphNet::addOutput(const std::string& name) +{ + requestedOutputs.push_back(name); +} + +void InfEngineNgraphNet::setNodePtr(std::shared_ptr* ptr) { + all_nodes.emplace((*ptr)->get_friendly_name(), ptr); +} + + void InfEngineNgraphNet::release() { + for (auto& node : components.back()) { + if (!(node->is_parameter() || node->is_output() || node->is_constant()) ) { + 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); + } + } + } + } + +void InfEngineNgraphNet::dfs(std::shared_ptr& node, + std::vector>& comp, + std::unordered_map& used) { + used[node->get_friendly_name()] = true; + comp.push_back(node); + auto inputs = node->get_users(); + for (size_t i = 0; i < node->get_input_size(); ++i) { + inputs.push_back(node->input_value(i).get_node()->shared_from_this()); + } + + for (auto& to : inputs) { + if (!used[to->get_friendly_name()]) { + dfs(to, comp, used); + } + } +} + +int InfEngineNgraphNet::getNumComponents() { + if (!components.empty()) { + return components.size(); + } + std::unordered_map used; + auto inputs = ngraph_function->get_ordered_ops(); + for (auto& node : inputs) { + used.emplace(node->get_friendly_name(), false); + } + + for (auto& node : inputs) { + if (!used[node->get_friendly_name()]) { + std::vector> current_comp; + dfs(node, current_comp, used); + components.push_back(current_comp); + } + } + return components.size(); +} + +void InfEngineNgraphNet::createNet(Target targetId) { + if (!hasNetOwner) + { + CV_Assert(!unconnectedNodes.empty()); + ngraph::ResultVector outs; + for (auto& node : unconnectedNodes) + { + auto out = std::make_shared(node); + outs.push_back(out); + } + CV_Assert_N(!inputs_vec.empty(), !outs.empty()); + ngraph_function = std::make_shared(outs, inputs_vec); + + int num_comp = getNumComponents(); + if (num_comp > 1) { + for (int i = num_comp - 1; i >= 0; --i) { + ngraph::ResultVector outputs; + ngraph::ParameterVector inps; + for (auto& node : components.back()) { + if (node->is_parameter()) { + auto parameter = std::dynamic_pointer_cast(node); + inps.push_back(parameter); + } + else if (node->is_output()) { + auto result = std::dynamic_pointer_cast(node); + outputs.push_back(result); + } + } + isInit = false; + CV_Assert_N(!inps.empty(), !outputs.empty()); + ngraph_function = std::make_shared(outputs, inps); + release(); + components.pop_back(); + init(targetId); + } + } else { + release(); + components.clear(); + init(targetId); + } + } +} + +void InfEngineNgraphNet::init(Target targetId) +{ + if (!hasNetOwner) + { + if (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) { + auto nodes = ngraph_function->get_ordered_ops(); + for (auto& node : nodes) { + auto parameter = std::dynamic_pointer_cast(node); + if (parameter && parameter->get_element_type() == ngraph::element::f32) { + parameter->set_element_type(ngraph::element::f16); + } + auto constant = std::dynamic_pointer_cast(node); + if (constant && constant->get_element_type() == ngraph::element::f32) { + auto data = constant->get_vector(); + std::vector new_data(data.size()); + for (size_t i = 0; i < data.size(); ++i) { + new_data[i] = ngraph::float16(data[i]); + } + auto new_const = std::make_shared(ngraph::element::f16, constant->get_shape(), new_data); + new_const->set_friendly_name(constant->get_friendly_name()); + ngraph::replace_node(constant, new_const); + } + } + ngraph_function->validate_nodes_and_infer_types(); + } + cnn = InferenceEngine::CNNNetwork(ngraph_function); +#ifdef _DEBUG // TODO + //cnn.serialize("/tmp/cnn.xml", "/tmp/cnn.bin"); +#endif + } + + switch (targetId) + { + case DNN_TARGET_CPU: + device_name = "CPU"; + break; + case DNN_TARGET_OPENCL: + case DNN_TARGET_OPENCL_FP16: + device_name = "GPU"; + break; + case DNN_TARGET_MYRIAD: + device_name = "MYRIAD"; + break; + case DNN_TARGET_FPGA: + device_name = "FPGA"; + break; + default: + CV_Error(Error::StsNotImplemented, "Unknown target"); + }; + + if (!hasNetOwner) { + for (size_t i = 0; i < ngraph_function->get_output_size(); ++i) { + 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); + if (iter != requestedOutputs.end()) { + requestedOutputs.erase(iter); + cnn.addOutput(name); + } + } + } + } else { + for (const auto& name : requestedOutputs) + { + cnn.addOutput(name); + } + } + + for (const auto& it : cnn.getInputsInfo()) + { + const std::string& name = it.first; + auto blobIt = allBlobs.find(name); + CV_Assert(blobIt != allBlobs.end()); + it.second->setPrecision(blobIt->second->getTensorDesc().getPrecision()); + } + + for (const auto& it : cnn.getOutputsInfo()) + { + const std::string& name = it.first; + auto blobIt = allBlobs.find(name); + CV_Assert(blobIt != allBlobs.end()); + it.second->setPrecision(blobIt->second->getTensorDesc().getPrecision()); // Should be always FP32 + } + + initPlugin(cnn); +} + +ngraph::ParameterVector InfEngineNgraphNet::setInputs(const std::vector& inputs, + const std::vector& names) { + CV_Assert_N(inputs.size() == names.size()); + ngraph::ParameterVector current_inp; + for (size_t i = 0; i < inputs.size(); i++) + { + std::vector shape = getShape(inputs[i]); + auto inp = std::make_shared(ngraph::element::f32, ngraph::Shape(shape)); + inp->set_friendly_name(names[i]); + + auto it = std::find_if(inputs_vec.begin(), inputs_vec.end(), + [&inp](const std::shared_ptr& a) { + return a->get_friendly_name() == inp->get_friendly_name(); + }); + if (it == inputs_vec.end()) { + inputs_vec.push_back(inp); + current_inp.push_back(inp); + } else { + current_inp.push_back(*it); + } + } + return current_inp; +} + +void InfEngineNgraphNet::setUnconnectedNodes(Ptr& node) { + unconnectedNodes.insert(node->node); +} + +void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) +{ + CV_Assert(!isInitialized()); + + try + { + AutoLock lock(getInitializationMutex()); + InferenceEngine::Core& ie = getCore(); + { + isInit = true; + std::vector candidates; + std::string param_pluginPath = utils::getConfigurationParameterString("OPENCV_DNN_IE_EXTRA_PLUGIN_PATH", ""); + if (!param_pluginPath.empty()) + { + candidates.push_back(param_pluginPath); + } + bool found = false; + for (size_t i = 0; i != candidates.size(); ++i) + { + const std::string& libName = candidates[i]; + try + { + InferenceEngine::IExtensionPtr extension = + InferenceEngine::make_so_pointer(libName); + + ie.AddExtension(extension, "CPU"); + CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << libName); + found = true; + break; + } + catch(...) {} + } + if (!found && !candidates.empty()) + { + CV_LOG_WARNING(NULL, "DNN-IE: Can't load extension plugin (extra layers for some networks). Specify path via OPENCV_DNN_IE_EXTRA_PLUGIN_PATH parameter"); + } + // Some of networks can work without a library of extra layers. + // OpenCV fallbacks as extensions. + ie.AddExtension(std::make_shared(), "CPU"); +#ifndef _WIN32 + // Limit the number of CPU threads. + if (device_name == "CPU") + ie.SetConfig({{ + InferenceEngine::PluginConfigParams::KEY_CPU_THREADS_NUM, format("%d", getNumThreads()), + }}, device_name); +#endif + } + std::map config; + if (device_name == "MYRIAD") { + config.emplace("VPU_DETECT_NETWORK_BATCH", CONFIG_VALUE(NO)); + } + netExec = ie.LoadNetwork(net, device_name, config); + } + catch (const std::exception& ex) + { + CV_Error(Error::StsError, format("Failed to initialize Inference Engine backend (device = %s): %s", device_name.c_str(), ex.what())); + } +} + +bool InfEngineNgraphNet::isInitialized() +{ + return isInit; +} + +bool NgraphBackendLayer::getMemoryShapes(const std::vector &inputs, + const int requiredOutputs, + std::vector &outputs, + std::vector &internals) const +{ + InferenceEngine::ICNNNetwork::InputShapes inShapes = t_net.getInputShapes(); + InferenceEngine::ICNNNetwork::InputShapes::iterator itr; + bool equal_flag = true; + size_t i = 0; + for (itr = inShapes.begin(); itr != inShapes.end(); ++itr) + { + InferenceEngine::SizeVector currentInShape(inputs[i].begin(), inputs[i].end()); + if (itr->second != currentInShape) + { + itr->second = currentInShape; + equal_flag = false; + } + i++; + } + + if (!equal_flag) + { + InferenceEngine::CNNNetwork curr_t_net(t_net); + curr_t_net.reshape(inShapes); + } + std::vector dims = t_net.getOutputsInfo()[name]->getDims(); + outputs.push_back(MatShape(dims.begin(), dims.end())); + return false; +} + +bool NgraphBackendLayer::supportBackend(int backendId) +{ + CV_LOG_DEBUG(NULL, "NgraphBackendLayer::supportBackend(" << backendId << ")"); + return backendId == DNN_BACKEND_DEFAULT || + (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); +} + +void NgraphBackendLayer::forward(InputArrayOfArrays inputs, OutputArrayOfArrays outputs, + OutputArrayOfArrays internals) +{ + CV_Error(Error::StsInternal, "Choose Inference Engine as a preferable backend."); +} + + +static InferenceEngine::Layout estimateLayout(const Mat& m) +{ + if (m.dims == 4) + return InferenceEngine::Layout::NCHW; + else if (m.dims == 2) + return InferenceEngine::Layout::NC; + else + return InferenceEngine::Layout::ANY; +} + +static InferenceEngine::DataPtr wrapToInfEngineDataNode(const Mat& m, const std::string& name = "") +{ + std::vector shape = getShape(m); + if (m.type() == CV_32F) + return InferenceEngine::DataPtr(new InferenceEngine::Data(name, + {InferenceEngine::Precision::FP32, shape, estimateLayout(m)})); + else if (m.type() == CV_8U) + return InferenceEngine::DataPtr(new InferenceEngine::Data(name, + {InferenceEngine::Precision::U8, shape, estimateLayout(m)})); + else + CV_Error(Error::StsNotImplemented, format("Unsupported data type %s", typeToString(m.type()).c_str())); +} + +InferenceEngine::Blob::Ptr wrapToNgraphBlob(const Mat& m, const std::vector& shape, + InferenceEngine::Layout layout) +{ + if (m.type() == CV_32F) + return InferenceEngine::make_shared_blob( + {InferenceEngine::Precision::FP32, shape, layout}, (float*)m.data); + else if (m.type() == CV_8U) + return InferenceEngine::make_shared_blob( + {InferenceEngine::Precision::U8, shape, layout}, (uint8_t*)m.data); + else + CV_Error(Error::StsNotImplemented, format("Unsupported data type %s", typeToString(m.type()).c_str())); +} + +InferenceEngine::Blob::Ptr wrapToNgraphBlob(const Mat& m, InferenceEngine::Layout layout) +{ + std::vector shape = getShape(m); + return wrapToNgraphBlob(m, shape, layout); +} + +NgraphBackendWrapper::NgraphBackendWrapper(int targetId, const cv::Mat& m) + : BackendWrapper(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, targetId) +{ + dataPtr = wrapToInfEngineDataNode(m); + blob = wrapToNgraphBlob(m, estimateLayout(m)); +} + +NgraphBackendWrapper::NgraphBackendWrapper(Ptr wrapper) + : BackendWrapper(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, wrapper->targetId) +{ + Ptr ieWrapper = wrapper.dynamicCast(); + CV_Assert(!ieWrapper.empty()); + InferenceEngine::DataPtr srcData = ieWrapper->dataPtr; + dataPtr = InferenceEngine::DataPtr(new InferenceEngine::Data(srcData->getName(), srcData->getTensorDesc())); + blob = ieWrapper->blob; +} + +Ptr NgraphBackendWrapper::create(Ptr wrapper) +{ + return Ptr(new NgraphBackendWrapper(wrapper)); +} + +NgraphBackendWrapper::~NgraphBackendWrapper() +{ + // nothing +} + +void NgraphBackendWrapper::copyToHost() +{ + CV_LOG_DEBUG(NULL, "NgraphBackendWrapper::copyToHost()"); + //CV_Error(Error::StsNotImplemented, ""); +} + +void NgraphBackendWrapper::setHostDirty() +{ + CV_LOG_DEBUG(NULL, "NgraphBackendWrapper::setHostDirty()"); + //CV_Error(Error::StsNotImplemented, ""); +} + +InferenceEngine::Blob::Ptr copyBlob(const InferenceEngine::Blob::Ptr& blob) +{ + InferenceEngine::Blob::Ptr copy; + auto description = blob->getTensorDesc(); + InferenceEngine::Precision precision = description.getPrecision(); + if (precision == InferenceEngine::Precision::FP32) + { + copy = InferenceEngine::make_shared_blob(description); + } + else if (precision == InferenceEngine::Precision::U8) + { + copy = InferenceEngine::make_shared_blob(description); + } + else + CV_Error(Error::StsNotImplemented, "Unsupported blob precision"); + copy->allocate(); + return copy; +} + +InferenceEngine::DataPtr ngraphDataNode(const Ptr& ptr) +{ + CV_Assert(!ptr.empty()); + Ptr p = ptr.dynamicCast(); + CV_Assert(!p.empty()); + return p->dataPtr; +} + + +void forwardNgraph(const std::vector >& outBlobsWrappers, + Ptr& node, bool isAsync) +{ + CV_Assert(!node.empty()); + Ptr ieNode = node.dynamicCast(); + CV_Assert(!ieNode.empty()); + ieNode->net->forward(outBlobsWrappers, isAsync); +} + +void InfEngineNgraphNet::addBlobs(const std::vector >& ptrs) +{ + auto wrappers = ngraphWrappers(ptrs); + for (const auto& wrapper : wrappers) + { + std::string name = wrapper->dataPtr->getName(); + name = name.empty() ? kDefaultInpLayerName : name; + allBlobs.insert({name, wrapper->blob}); + } +} + +void InfEngineNgraphNet::NgraphReqWrapper::makePromises(const std::vector >& outsWrappers) +{ + auto outs = ngraphWrappers(outsWrappers); + outProms.clear(); + outProms.resize(outs.size()); + outsNames.resize(outs.size()); + for (int i = 0; i < outs.size(); ++i) + { + outs[i]->futureMat = outProms[i].getArrayResult(); + outsNames[i] = outs[i]->dataPtr->getName(); + } +} + +Mat ngraphBlobToMat(const InferenceEngine::Blob::Ptr& blob) +{ + std::vector dims = blob->getTensorDesc().getDims(); + std::vector size(dims.begin(), dims.end()); + auto precision = blob->getTensorDesc().getPrecision(); + + int type = -1; + switch (precision) + { + case InferenceEngine::Precision::FP32: type = CV_32F; break; + case InferenceEngine::Precision::U8: type = CV_8U; break; + default: + CV_Error(Error::StsNotImplemented, "Unsupported blob precision"); + } + return Mat(size, type, (void*)blob->buffer()); +} + +void InfEngineNgraphNet::forward(const std::vector >& outBlobsWrappers, bool isAsync) +{ + CV_LOG_DEBUG(NULL, "InfEngineNgraphNet::forward(" << (isAsync ? "async" : "sync") << ")"); + + // Look for finished requests. + Ptr reqWrapper; + for (auto& wrapper : infRequests) + { + if (wrapper->isReady) + { + reqWrapper = wrapper; + break; + } + } + if (reqWrapper.empty()) + { + reqWrapper = Ptr(new NgraphReqWrapper()); + try + { + reqWrapper->req = netExec.CreateInferRequest(); + } + catch (const std::exception& ex) + { + CV_Error(Error::StsAssert, format("Failed to initialize Inference Engine backend: %s", ex.what())); + } + infRequests.push_back(reqWrapper); + + InferenceEngine::BlobMap inpBlobs, outBlobs; + for (const auto& it : cnn.getInputsInfo()) + { + const std::string& name = it.first; + auto blobIt = allBlobs.find(name); + CV_Assert(blobIt != allBlobs.end()); + inpBlobs[name] = isAsync ? copyBlob(blobIt->second) : blobIt->second; + } + for (const auto& it : cnn.getOutputsInfo()) + { + const std::string& name = it.first; + auto blobIt = allBlobs.find(name); + CV_Assert(blobIt != allBlobs.end()); + outBlobs[name] = isAsync ? copyBlob(blobIt->second) : blobIt->second; + } + reqWrapper->req.SetInput(inpBlobs); + reqWrapper->req.SetOutput(outBlobs); + + InferenceEngine::IInferRequest::Ptr infRequestPtr = reqWrapper->req; + infRequestPtr->SetUserData(reqWrapper.get(), 0); + + infRequestPtr->SetCompletionCallback( + [](InferenceEngine::IInferRequest::Ptr request, InferenceEngine::StatusCode status) + { + CV_LOG_DEBUG(NULL, "DNN(nGraph): completionCallback(" << (int)status << ")"); + + NgraphReqWrapper* wrapper; + request->GetUserData((void**)&wrapper, 0); + CV_Assert(wrapper && "Internal error"); + + size_t processedOutputs = 0; + try + { + for (; processedOutputs < wrapper->outProms.size(); ++processedOutputs) + { + const std::string& name = wrapper->outsNames[processedOutputs]; + Mat m = ngraphBlobToMat(wrapper->req.GetBlob(name)); + + try + { + CV_Assert(status == InferenceEngine::StatusCode::OK); + wrapper->outProms[processedOutputs].setValue(m.clone()); + } + catch (...) + { + try { + wrapper->outProms[processedOutputs].setException(std::current_exception()); + } catch(...) { + CV_LOG_ERROR(NULL, "DNN: Exception occured during async inference exception propagation"); + } + } + } + } + catch (...) + { + std::exception_ptr e = std::current_exception(); + for (; processedOutputs < wrapper->outProms.size(); ++processedOutputs) + { + try { + wrapper->outProms[processedOutputs].setException(e); + } catch(...) { + CV_LOG_ERROR(NULL, "DNN: Exception occured during async inference exception propagation"); + } + } + } + wrapper->isReady = true; + } + ); + } + + if (isAsync) + { + // Copy actual data to infer request's input blobs. + for (const auto& it : cnn.getInputsInfo()) + { + const std::string& name = it.first; + auto blobIt = allBlobs.find(name); + Mat srcMat = ngraphBlobToMat(blobIt->second); + Mat dstMat = ngraphBlobToMat(reqWrapper->req.GetBlob(name)); + srcMat.copyTo(dstMat); + } + + // Set promises to output blobs wrappers. + reqWrapper->makePromises(outBlobsWrappers); + + reqWrapper->isReady = false; + reqWrapper->req.StartAsync(); + } + else + { + reqWrapper->req.Infer(); + } +} + +#else +void forwardNgraph(const std::vector >& outBlobsWrappers, + Ptr& node, bool isAsync) +{ + CV_Assert(false && "nGraph is not enabled in this OpenCV build"); +} +#endif + +}} diff --git a/modules/dnn/src/ie_ngraph.hpp b/modules/dnn/src/ie_ngraph.hpp new file mode 100644 index 0000000000..39da2e0407 --- /dev/null +++ b/modules/dnn/src/ie_ngraph.hpp @@ -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-2019, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. + +#ifndef __OPENCV_DNN_IE_NGRAPH_HPP__ +#define __OPENCV_DNN_IE_NGRAPH_HPP__ + +#include "op_inf_engine.hpp" + +#ifdef HAVE_DNN_NGRAPH + +#include + +#endif // HAVE_DNN_NGRAPH + +namespace cv { namespace dnn { + +#ifdef HAVE_DNN_NGRAPH + +class InfEngineNgraphNode; + + +class InfEngineNgraphNet +{ +public: + InfEngineNgraphNet(); + InfEngineNgraphNet(InferenceEngine::CNNNetwork& net); + + void addOutput(const std::string& name); + + bool isInitialized(); + void init(Target targetId); + + void forward(const std::vector >& outBlobsWrappers, bool isAsync); + + 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); + void setNodePtr(std::shared_ptr* ptr); +private: + void release(); + int getNumComponents(); + void dfs(std::shared_ptr& node, std::vector>& comp, + std::unordered_map& used); + + ngraph::ParameterVector inputs_vec; + std::shared_ptr ngraph_function; + std::vector>> components; + std::unordered_map* > all_nodes; + + InferenceEngine::ExecutableNetwork netExec; + InferenceEngine::BlobMap allBlobs; + std::string device_name; + bool isInit = false; + + struct NgraphReqWrapper + { + NgraphReqWrapper() : isReady(true) {} + + void makePromises(const std::vector >& outs); + + InferenceEngine::InferRequest req; + std::vector outProms; + std::vector outsNames; + bool isReady; + }; + std::vector > infRequests; + + InferenceEngine::CNNNetwork cnn; + bool hasNetOwner; + std::vector requestedOutputs; + std::unordered_set> unconnectedNodes; +}; + +class InfEngineNgraphNode : public BackendNode +{ +public: + InfEngineNgraphNode(std::shared_ptr&& _node); + InfEngineNgraphNode(std::shared_ptr& _node); + + void setName(const std::string& name); + + // Inference Engine network object that allows to obtain the outputs of this layer. + std::shared_ptr node; + Ptr net; +}; + +class NgraphBackendWrapper : public BackendWrapper +{ +public: + NgraphBackendWrapper(int targetId, const Mat& m); + NgraphBackendWrapper(Ptr wrapper); + ~NgraphBackendWrapper(); + + static Ptr create(Ptr wrapper); + + virtual void copyToHost() CV_OVERRIDE; + virtual void setHostDirty() CV_OVERRIDE; + + InferenceEngine::DataPtr dataPtr; + InferenceEngine::Blob::Ptr blob; + AsyncArray futureMat; +}; + +InferenceEngine::DataPtr ngraphDataNode(const Ptr& ptr); + +// This is a fake class to run networks from Model Optimizer. Objects of that +// class simulate responses of layers are imported by OpenCV and supported by +// Inference Engine. The main difference is that they do not perform forward pass. +class NgraphBackendLayer : public Layer +{ +public: + NgraphBackendLayer(const InferenceEngine::CNNNetwork &t_net_) : t_net(t_net_) {}; + + virtual bool getMemoryShapes(const std::vector &inputs, + const int requiredOutputs, + std::vector &outputs, + std::vector &internals) const CV_OVERRIDE; + + virtual void forward(InputArrayOfArrays inputs, OutputArrayOfArrays outputs, + OutputArrayOfArrays internals) CV_OVERRIDE; + + virtual bool supportBackend(int backendId) CV_OVERRIDE; + +private: + InferenceEngine::CNNNetwork t_net; +}; + +#endif // HAVE_DNN_NGRAPH + +void forwardNgraph(const std::vector >& outBlobsWrappers, + Ptr& node, bool isAsync); + +}} // namespace cv::dnn + + +#endif // __OPENCV_DNN_IE_NGRAPH_HPP__ diff --git a/modules/dnn/src/layers/batch_norm_layer.cpp b/modules/dnn/src/layers/batch_norm_layer.cpp index 791d8f1e0b..7766a49a33 100644 --- a/modules/dnn/src/layers/batch_norm_layer.cpp +++ b/modules/dnn/src/layers/batch_norm_layer.cpp @@ -13,6 +13,8 @@ Implementation of Batch Normalization layer. #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include #ifdef HAVE_OPENCL @@ -156,7 +158,7 @@ public: { return (backendId == DNN_BACKEND_OPENCV) || (backendId == DNN_BACKEND_HALIDE && haveHalide()) || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine() && (preferableTarget == DNN_TARGET_CPU || dims == 4)); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine() && (preferableTarget == DNN_TARGET_CPU || dims == 4)); } #ifdef HAVE_OPENCL @@ -363,6 +365,20 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE + { + auto ieInpNode = nodes[0].dynamicCast()->node; + std::vector shape(ieInpNode->get_shape().size(), 1); + shape[1] = weights_.total(); + auto weight = std::make_shared(ngraph::element::f32, ngraph::Shape(shape), weights_.data); + auto bias = std::make_shared(ngraph::element::f32, ngraph::Shape(shape), bias_.data); + auto scale_node = std::make_shared(ieInpNode, weight, ngraph::op::AutoBroadcastType::NUMPY); + auto scale_shift = std::make_shared(scale_node, bias, ngraph::op::AutoBroadcastType::NUMPY); + return Ptr(new InfEngineNgraphNode(scale_shift)); + } +#endif // HAVE_DNN_NGRAPH + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/blank_layer.cpp b/modules/dnn/src/layers/blank_layer.cpp index ef44ed79c4..0163a2a37d 100644 --- a/modules/dnn/src/layers/blank_layer.cpp +++ b/modules/dnn/src/layers/blank_layer.cpp @@ -41,6 +41,7 @@ //M*/ #include "../precomp.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" namespace cv { @@ -57,7 +58,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine()); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine()); } bool getMemoryShapes(const std::vector &inputs, @@ -131,6 +132,18 @@ public: return Ptr(new InfEngineBackendNode(ieLayer)); } #endif // HAVE_INF_ENGINE + + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + ngraph::NodeVector inp{ieInpNode}; + auto blank = std::make_shared(inp, 0); + return Ptr(new InfEngineNgraphNode(blank)); + } +#endif // HAVE_DNN_NGRAPH }; Ptr BlankLayer::create(const LayerParams& params) diff --git a/modules/dnn/src/layers/concat_layer.cpp b/modules/dnn/src/layers/concat_layer.cpp index 929d6bd9af..98864f95f8 100644 --- a/modules/dnn/src/layers/concat_layer.cpp +++ b/modules/dnn/src/layers/concat_layer.cpp @@ -44,6 +44,7 @@ #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #ifdef HAVE_OPENCL #include "opencl_kernels_dnn.hpp" @@ -105,7 +106,7 @@ public: { return backendId == DNN_BACKEND_OPENCV || (backendId == DNN_BACKEND_HALIDE && haveHalide() && axis == 1 && !padding) || // By channels - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine() && !padding); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine() && !padding); } class ChannelConcatInvoker : public ParallelLoopBody @@ -309,6 +310,23 @@ public: return Ptr(new InfEngineBackendNode(ieLayer)); } #endif // HAVE_INF_ENGINE + + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert(inputs.size() == nodes.size()); + ngraph::NodeVector inp_nodes; + for (auto& node : nodes) { + inp_nodes.push_back(node.dynamicCast()->node); + } + + InferenceEngine::DataPtr data = ngraphDataNode(inputs[0]); + auto concat = std::make_shared(inp_nodes, clamp(axis, data->getDims().size())); + return Ptr(new InfEngineNgraphNode(concat)); + } +#endif // HAVE_DNN_NGRAPH }; Ptr ConcatLayer::create(const LayerParams& params) diff --git a/modules/dnn/src/layers/const_layer.cpp b/modules/dnn/src/layers/const_layer.cpp index 7a33d6ec84..2c6b51efde 100644 --- a/modules/dnn/src/layers/const_layer.cpp +++ b/modules/dnn/src/layers/const_layer.cpp @@ -26,7 +26,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { - return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_INFERENCE_ENGINE; + return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019; } virtual bool getMemoryShapes(const std::vector &inputs, diff --git a/modules/dnn/src/layers/convolution_layer.cpp b/modules/dnn/src/layers/convolution_layer.cpp index 0d5bef7cdf..4d1fe5f5ae 100644 --- a/modules/dnn/src/layers/convolution_layer.cpp +++ b/modules/dnn/src/layers/convolution_layer.cpp @@ -44,6 +44,8 @@ #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include "opencv2/core/hal/hal.hpp" #include "opencv2/core/hal/intrin.hpp" #include @@ -253,7 +255,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { #ifdef HAVE_INF_ENGINE - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) { if (kernel_size.size() == 3) return preferableTarget == DNN_TARGET_CPU; @@ -528,6 +530,73 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector > &inputs, + const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert_N(inputs.size() == 1, nodes.size() == 1); + auto& ieInpNode = nodes[0].dynamicCast()->node; + std::vector dims = ieInpNode->get_shape(); + CV_Assert(dims.size() == 4 || dims.size() == 5); + const int inpCn = dims[1]; + const int outCn = blobs[0].size[0]; + const int inpGroupCn = blobs[0].size[1]; + const int group = inpCn / inpGroupCn; + + std::vector kernel_shape = getShape(blobs[0]); + auto ieWeights = std::make_shared(ngraph::element::f32, kernel_shape, blobs[0].data); + if (fusedWeights) + { + if (weightsMat.isContinuous()) + { + ieWeights = std::make_shared(ngraph::element::f32, kernel_shape, weightsMat.data); + } + else + { + Mat newWeights = blobs[0].reshape(1, outCn); + Mat cvWeights = weightsMat.colRange(0, newWeights.cols); + cvWeights.copyTo(newWeights); + ieWeights = std::make_shared(ngraph::element::f32, kernel_shape, blobs[0].data); + } + } + + ngraph::op::PadType pad_type = ngraph::op::PadType::EXPLICIT; + if (!padMode.empty()) + pad_type = padMode == "VALID" ? ngraph::op::PadType::VALID : ngraph::op::PadType::SAME_UPPER; + + std::shared_ptr conv_node; + if (group != 1) { + conv_node = std::make_shared( + ieInpNode, ieWeights, + ngraph::Strides(strides), + ngraph::Strides(dilations), + ngraph::CoordinateDiff(std::vector(pads_begin.begin(), pads_begin.end())), + ngraph::CoordinateDiff(std::vector(pads_end.begin(), pads_end.end())), + ngraph::Strides{}, + group, + pad_type); + } else { + conv_node = std::make_shared( + ieInpNode, ieWeights, + ngraph::Strides(strides), + ngraph::CoordinateDiff(std::vector(pads_begin.begin(), pads_begin.end())), + ngraph::CoordinateDiff(std::vector(pads_end.begin(), pads_end.end())), + ngraph::Strides(dilations), + pad_type); + } + + if (hasBias() || fusedBias) + { + std::vector shape(conv_node->get_shape().size(), 1); + shape[1] = outCn; + auto bias = std::make_shared(ngraph::element::f32, ngraph::Shape(shape), biasvec.data()); + auto conv_bias = std::make_shared(conv_node, bias, ngraph::op::AutoBroadcastType::NUMPY); + return Ptr(new InfEngineNgraphNode(conv_bias)); + } + return Ptr(new InfEngineNgraphNode(conv_node)); + } +#endif // HAVE_DNN_NGRAPH + class ParallelConv : public cv::ParallelLoopBody { public: @@ -1251,7 +1320,24 @@ public: const int outGroupCn = blobs[0].size[1]; // Weights are in IOHW or IODHW layout const int group = numOutput / outGroupCn; - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) { + if (padMode.empty()) { + for (int i = 0; i < adjust_pads.size(); i++) { + if (pads_end[i] < adjust_pads[i]) + return false; + } + } else if (padMode == "SAME") { + for (int i = 0; i < adjust_pads.size(); i++) { + if (kernel_size[i] < pads_begin[i] + 1 + adjust_pads[i]) + return false; + } + } else if (padMode == "VALID") + return false; + + return group == 1; + } + + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { if (kernel_size.size() == 3 && preferableTarget != DNN_TARGET_CPU) { return false; @@ -1932,6 +2018,70 @@ public: } #endif // HAVE_INF_ENGINE + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector > &inputs, + const std::vector >& nodes) CV_OVERRIDE + { + const int outGroupCn = blobs[0].size[1]; + const int group = numOutput / outGroupCn; + CV_Assert(group == 1); + + auto& ieInpNode = nodes[0].dynamicCast()->node; + std::vector kernel_shape = getShape(blobs[0]); + auto ieWeights = std::make_shared(ngraph::element::f32, kernel_shape, blobs[0].data); + + if (fusedWeights) + { + int inpCn = blobs[0].size[0]; + Mat newWeights = blobs[0].reshape(1, inpCn); + transpose(weightsMat, newWeights); + } + size_t batch = ieInpNode->get_shape()[0]; + std::vector out_shape = {batch, (size_t)numOutput}; + std::vector paddings_end; + std::vector inpShape = ieInpNode->get_shape(); + if (padMode.empty()) + { + for (int i = 0; i < pads_end.size(); i++) { + out_shape.push_back(strides[i] * (inpShape[2 + i] - 1) + + kernel_size[i] - pads_begin[i] - pads_end[i] + adjust_pads[i]); + paddings_end.push_back(pads_end[i] - adjust_pads[i]); + } + } + else if (padMode == "SAME") + { + for (int i = 0; i < pads_begin.size(); i++) { + out_shape.push_back(strides[i] * (inpShape[2 + i] - 1) + 1 + adjust_pads[i]); + paddings_end.push_back(kernel_size[i] - pads_begin[i] - 1 - adjust_pads[i]); + } + } else { + paddings_end = pads_end; + } + + auto deconv = std::make_shared( + ngraph::Shape{out_shape}, + ieWeights, + ieInpNode, + ngraph::Strides(strides), + ngraph::Strides(dilations), + ngraph::CoordinateDiff(std::vector(pads_begin.begin(), pads_begin.end())), + ngraph::CoordinateDiff(std::vector(paddings_end.begin(), paddings_end.end())), + (strides.size() == 2 ? ngraph::Strides{1, 1} : ngraph::Strides{1, 1, 1})); + if (hasBias() || fusedBias) + { + std::vector shape(deconv->get_shape().size(), 1); + shape[1] = numOutput; + auto bias = std::make_shared(ngraph::element::f32, ngraph::Shape(shape), blobs[1].data); + auto deconv_bias = std::make_shared(deconv, bias, ngraph::op::AutoBroadcastType::NUMPY); + return Ptr(new InfEngineNgraphNode(deconv_bias)); + } + + + return Ptr(new InfEngineNgraphNode(deconv)); + } +#endif // HAVE_DNN_NGRAPH + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/detection_output_layer.cpp b/modules/dnn/src/layers/detection_output_layer.cpp index 10ad4db110..d629a71384 100644 --- a/modules/dnn/src/layers/detection_output_layer.cpp +++ b/modules/dnn/src/layers/detection_output_layer.cpp @@ -43,6 +43,7 @@ #include "../precomp.hpp" #include "layers_common.hpp" #include "../op_inf_engine.hpp" + #include #include #include "../nms.inl.hpp" @@ -51,6 +52,41 @@ #include "opencl_kernels_dnn.hpp" #endif +#ifdef HAVE_DNN_NGRAPH +#include "../ie_ngraph.hpp" +#include + +namespace ngraph { +namespace op { + +class Dummy : public Op { +public: + Dummy() : Op("Dummy", {}) { + constructor_validate_and_infer_types(); + } + + void validate_and_infer_types() override { + set_output_type(0, ngraph::element::Type(), {}); + } + + std::shared_ptr copy_with_new_args(const NodeVector& new_args) const override { + if (!new_args.empty()) + throw ngraph_error("Incorrect number of new arguments"); + return std::make_shared(); + } + + static constexpr NodeTypeInfo type_info{"Dummy", 1}; + const NodeTypeInfo& get_type_info() const override { + return type_info; + } +}; + +constexpr NodeTypeInfo Dummy::type_info; + +} // namespace op +} // namespace ngraph +#endif + namespace cv { namespace dnn @@ -198,7 +234,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && !_locPredTransposed && _bboxesNormalized); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && !_locPredTransposed && _bboxesNormalized); } bool getMemoryShapes(const std::vector &inputs, @@ -941,6 +977,36 @@ public: return Ptr(new InfEngineBackendNode(l)); } #endif // HAVE_INF_ENGINE + + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert(nodes.size() == 3); + auto& box_logits = nodes[0].dynamicCast()->node; + auto& class_preds = nodes[1].dynamicCast()->node; + auto& proposals = nodes[2].dynamicCast()->node; + + ngraph::op::DetectionOutputAttrs attrs; + attrs.num_classes = _numClasses; + attrs.background_label_id = _backgroundLabelId; + attrs.top_k = _topK > 0 ? _topK : _keepTopK; + attrs.variance_encoded_in_target = _varianceEncodedInTarget; + attrs.keep_top_k = {_keepTopK}; + attrs.nms_threshold = _nmsThreshold; + attrs.confidence_threshold = _confidenceThreshold; + attrs.share_location = _shareLocation; + attrs.clip_before_nms = _clip; + attrs.code_type = std::string{"caffe.PriorBoxParameter." + _codeType}; + attrs.normalized = true; + + auto aux_class_preds = std::make_shared(); + auto aux_box_preds = std::make_shared(); + auto det_out = std::make_shared(box_logits, class_preds, + proposals, aux_class_preds, aux_box_preds, attrs); + return Ptr(new InfEngineNgraphNode(det_out)); + } +#endif // HAVE_DNN_NGRAPH }; float util::caffe_box_overlap(const util::NormalizedBBox& a, const util::NormalizedBBox& b) diff --git a/modules/dnn/src/layers/elementwise_layers.cpp b/modules/dnn/src/layers/elementwise_layers.cpp index 2ea1302b82..8a0ddcdd75 100644 --- a/modules/dnn/src/layers/elementwise_layers.cpp +++ b/modules/dnn/src/layers/elementwise_layers.cpp @@ -44,6 +44,8 @@ #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include #include @@ -158,6 +160,15 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + auto node = func.initNgraphAPI(ieInpNode); + return Ptr(new InfEngineNgraphNode(node)); + } +#endif // HAVE_DNN_NGRAPH + virtual bool tryFuse(Ptr& top) CV_OVERRIDE { return func.tryFuse(top); @@ -249,8 +260,10 @@ struct ReLUFunctor bool supportBackend(int backendId, int) { #ifdef HAVE_INF_ENGINE - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) return slope >= 0 || !INF_ENGINE_VER_MAJOR_EQ(INF_ENGINE_RELEASE_2019R1); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + return true; #endif return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE; } @@ -352,6 +365,17 @@ struct ReLUFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + if (slope) { + auto param = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, &slope); + return std::make_shared(node, param); + } + return std::make_shared(node); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} @@ -373,7 +397,7 @@ struct ReLU6Functor bool supportBackend(int backendId, int) { return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || - backendId == DNN_BACKEND_INFERENCE_ENGINE; + backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const @@ -455,6 +479,13 @@ struct ReLU6Functor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + return std::make_shared(node, minValue, maxValue); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} @@ -469,7 +500,7 @@ struct TanHFunctor bool supportBackend(int backendId, int) { return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || - backendId == DNN_BACKEND_INFERENCE_ENGINE; + backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const @@ -527,6 +558,13 @@ struct TanHFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + return std::make_shared(node); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} @@ -599,6 +637,13 @@ struct SwishFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + CV_Error(Error::StsNotImplemented, ""); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} @@ -672,6 +717,13 @@ struct MishFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + CV_Error(Error::StsNotImplemented, ""); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} @@ -687,7 +739,7 @@ struct SigmoidFunctor bool supportBackend(int backendId, int) { return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || - backendId == DNN_BACKEND_INFERENCE_ENGINE; + backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const @@ -745,6 +797,13 @@ struct SigmoidFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + return std::make_shared(node); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} @@ -761,7 +820,7 @@ struct ELUFunctor bool supportBackend(int backendId, int) { return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || - backendId == DNN_BACKEND_INFERENCE_ENGINE; + backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const @@ -819,6 +878,13 @@ struct ELUFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + return std::make_shared(node, 1.0); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} @@ -833,7 +899,7 @@ struct AbsValFunctor bool supportBackend(int backendId, int) { #ifdef HAVE_INF_ENGINE - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) return !INF_ENGINE_VER_MAJOR_EQ(INF_ENGINE_RELEASE_2019R1); #endif return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE; @@ -894,6 +960,16 @@ struct AbsValFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + float coeff = -0.999999f; + // float coeff = preferableTarget == DNN_TARGET_MYRIAD ? -0.999f : -0.999999f; + auto slope = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, &coeff); + return std::make_shared(node, slope); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} @@ -967,6 +1043,13 @@ struct BNLLFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + CV_Error(Error::StsNotImplemented, ""); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} @@ -987,10 +1070,10 @@ struct PowerFunctor bool supportBackend(int backendId, int targetId) { - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) return (targetId != DNN_TARGET_OPENCL && targetId != DNN_TARGET_OPENCL_FP16) || power == 1.0 || power == 0.5; else - return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE; + return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const @@ -1077,6 +1160,22 @@ struct PowerFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + auto scale_node = std::make_shared(ngraph::element::f32, + ngraph::Shape{1}, &scale); + auto shift_node = std::make_shared(ngraph::element::f32, + ngraph::Shape{1}, &shift); + auto power_node = std::make_shared(ngraph::element::f32, + ngraph::Shape{1}, &power); + + auto mul = std::make_shared(scale_node, node, ngraph::op::AutoBroadcastType::NUMPY); + auto scale_shift = std::make_shared(mul, shift_node, ngraph::op::AutoBroadcastType::NUMPY); + return std::make_shared(scale_shift, power_node, ngraph::op::AutoBroadcastType::NUMPY); + } +#endif // HAVE_DNN_NGRAPH + bool tryFuse(Ptr& top) { if (power != 1.0f && shift != 0.0f) @@ -1122,7 +1221,7 @@ struct ChannelsPReLUFunctor bool supportBackend(int backendId, int) { return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || - backendId == DNN_BACKEND_INFERENCE_ENGINE; + backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const @@ -1215,6 +1314,16 @@ struct ChannelsPReLUFunctor } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + std::shared_ptr initNgraphAPI(const std::shared_ptr& node) + { + const size_t numChannels = scale.total(); + auto slope = std::make_shared(ngraph::element::f32, ngraph::Shape{numChannels}, scale.data); + return std::make_shared(node, slope); + } +#endif // HAVE_DNN_NGRAPH + + bool tryFuse(Ptr&) { return false; } void getScaleShift(Mat&, Mat&) const {} diff --git a/modules/dnn/src/layers/eltwise_layer.cpp b/modules/dnn/src/layers/eltwise_layer.cpp index f077866bdc..978b1b6f4a 100644 --- a/modules/dnn/src/layers/eltwise_layer.cpp +++ b/modules/dnn/src/layers/eltwise_layer.cpp @@ -44,6 +44,7 @@ #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #ifdef HAVE_OPENCL #include "opencl_kernels_dnn.hpp" @@ -102,8 +103,8 @@ public: { return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && !variableChannels && - (preferableTarget != DNN_TARGET_OPENCL || coeffs.empty())); + ((((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (preferableTarget != DNN_TARGET_OPENCL || coeffs.empty())) + || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && !variableChannels)); } bool getMemoryShapes(const std::vector &inputs, @@ -521,6 +522,36 @@ public: } #endif // HAVE_INF_ENGINE + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto curr_node = nodes[0].dynamicCast()->node; + if (!coeffs.empty()) { + auto coeff = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, &coeffs[0]); + curr_node = std::make_shared(curr_node, coeff, ngraph::op::AutoBroadcastType::NUMPY); + } + + for (size_t i = 1; i < nodes.size(); i++) + { + auto next_node = nodes[i].dynamicCast()->node; + if (!coeffs.empty()) { + auto coeff = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, &coeffs[i]); + next_node = std::make_shared(next_node, coeff, ngraph::op::AutoBroadcastType::NUMPY); + } + switch (op) { + case SUM: curr_node = std::make_shared(curr_node, next_node); break; + case PROD: curr_node = std::make_shared(curr_node, next_node); break; + case DIV: curr_node = std::make_shared(curr_node, next_node); break; + case MAX: curr_node = std::make_shared(curr_node, next_node); break; + default: CV_Error(Error::StsNotImplemented, "Unsupported eltwise operation"); + } + } + return Ptr(new InfEngineNgraphNode(curr_node)); + } +#endif // HAVE_DNN_NGRAPH + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/flatten_layer.cpp b/modules/dnn/src/layers/flatten_layer.cpp index f1250e7e3e..b4b259928f 100644 --- a/modules/dnn/src/layers/flatten_layer.cpp +++ b/modules/dnn/src/layers/flatten_layer.cpp @@ -43,6 +43,8 @@ #include "../precomp.hpp" #include "layers_common.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include #include #include @@ -65,7 +67,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine()); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine()); } bool getMemoryShapes(const std::vector &inputs, @@ -176,6 +178,34 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH +virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE +{ + auto& ieInpNode = nodes[0].dynamicCast()->node; + std::vector dims = ieInpNode->get_shape(); + + int numAxes = dims.size(); + int startAxis = clamp(_startAxis, numAxes); + int endAxis = clamp(_endAxis, numAxes); + + CV_Assert(startAxis >= 0); + CV_Assert(endAxis >= startAxis && endAxis < numAxes); + int64_t flattenedDimensionSize = std::accumulate(dims.begin() + startAxis, + dims.begin() + endAxis + 1, 1, std::multiplies()); + + std::vector outputShapeVec(dims.begin(), dims.begin() + startAxis); + outputShapeVec.push_back(flattenedDimensionSize); + outputShapeVec.insert(outputShapeVec.end(), dims.begin() + endAxis + 1, dims.end()); + + auto shape = std::make_shared(ngraph::element::i64, + ngraph::Shape({outputShapeVec.size()}), outputShapeVec.data()); + auto reshape = std::make_shared(ieInpNode, shape, true); + return Ptr(new InfEngineNgraphNode(reshape)); + } +#endif // HAVE_DNN_NGRAPH + // HAVE_INF_ENGINE + int _startAxis; int _endAxis; }; diff --git a/modules/dnn/src/layers/fully_connected_layer.cpp b/modules/dnn/src/layers/fully_connected_layer.cpp index c9baf79d00..065062dc99 100644 --- a/modules/dnn/src/layers/fully_connected_layer.cpp +++ b/modules/dnn/src/layers/fully_connected_layer.cpp @@ -44,6 +44,7 @@ #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" + #include #ifdef HAVE_OPENCL @@ -51,6 +52,10 @@ using namespace cv::dnn::ocl4dnn; #endif +#ifdef HAVE_DNN_NGRAPH +#include "../ie_ngraph.hpp" +#endif + namespace cv { namespace dnn @@ -124,7 +129,7 @@ public: { return backendId == DNN_BACKEND_OPENCV || (backendId == DNN_BACKEND_HALIDE && haveHalide() && axis == 1) || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine() && axis == 1); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine() && axis == 1); } virtual bool setActivation(const Ptr& layer) CV_OVERRIDE @@ -456,6 +461,31 @@ public: } #endif // HAVE_INF_ENGINE + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + int batch = ieInpNode->get_shape()[0]; + + std::vector data = {(size_t)batch, (size_t)blobs[0].size[1]}; + auto new_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, data.data()); + auto inp = std::make_shared(ieInpNode, new_shape, true); + + std::vector weight_shape{(size_t)blobs[0].size[0], (size_t)blobs[0].size[1]}; + auto ieWeights = std::make_shared(ngraph::element::f32, weight_shape, blobs[0].data); + auto matmul = std::make_shared(inp, ieWeights, false, true); + if (bias) { + auto bias_node = std::make_shared(ngraph::element::f32, + ngraph::Shape{(size_t)blobs[1].size[1]}, blobs[1].data); + auto fc = std::make_shared(matmul, bias_node, ngraph::op::AutoBroadcastType::NUMPY); + return Ptr(new InfEngineNgraphNode(fc)); + } + return Ptr(new InfEngineNgraphNode(matmul)); + } +#endif // HAVE_DNN_NGRAPH + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/lrn_layer.cpp b/modules/dnn/src/layers/lrn_layer.cpp index de63f23cd6..6c2ab34a0b 100644 --- a/modules/dnn/src/layers/lrn_layer.cpp +++ b/modules/dnn/src/layers/lrn_layer.cpp @@ -44,6 +44,8 @@ #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include "opencv2/imgproc.hpp" #include "opencv2/dnn/shape_utils.hpp" #include "opencv2/core/hal/hal.hpp" @@ -90,8 +92,12 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { return bias == (int)bias; + } + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) { + return type == CHANNEL_NRM && bias == (int)bias; + } return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE; } @@ -398,6 +404,19 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE + { + float alphaSize = alpha; + if (!normBySize) + alphaSize *= (type == SPATIAL_NRM ? size*size : size); + + auto& ieInpNode = nodes[0].dynamicCast()->node; + auto lrn = std::make_shared(ieInpNode, (double)alphaSize, (double)beta, (double)bias, (size_t)size); + return Ptr(new InfEngineNgraphNode(lrn)); + } +#endif // HAVE_DNN_NGRAPH + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/mvn_layer.cpp b/modules/dnn/src/layers/mvn_layer.cpp index 126c86d983..5d0c267f49 100644 --- a/modules/dnn/src/layers/mvn_layer.cpp +++ b/modules/dnn/src/layers/mvn_layer.cpp @@ -43,6 +43,8 @@ #include "../precomp.hpp" #include "layers_common.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include #ifdef HAVE_OPENCL @@ -117,7 +119,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { #ifdef HAVE_INF_ENGINE - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) return !zeroDev && (preferableTarget != DNN_TARGET_MYRIAD || eps <= 1e-7f); else #endif // HAVE_INF_ENGINE @@ -382,6 +384,16 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + auto mvn = std::make_shared(ieInpNode, acrossChannels, normVariance, eps); + return Ptr(new InfEngineNgraphNode(mvn)); + } +#endif // HAVE_DNN_NGRAPH + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/normalize_bbox_layer.cpp b/modules/dnn/src/layers/normalize_bbox_layer.cpp index b6b973d226..63f93e2eb5 100644 --- a/modules/dnn/src/layers/normalize_bbox_layer.cpp +++ b/modules/dnn/src/layers/normalize_bbox_layer.cpp @@ -43,6 +43,7 @@ #include "../precomp.hpp" #include "layers_common.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" namespace cv { namespace dnn { @@ -63,7 +64,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) { if (pnorm != 2) return false; @@ -308,6 +309,45 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + const size_t batch = ieInpNode->get_shape()[0]; + const size_t numChannels = ieInpNode->get_shape()[1]; + + std::vector axes_data; + if (!acrossSpatial) { + axes_data.push_back(1); + } else { + axes_data.resize(ieInpNode->get_shape().size()); + std::iota(axes_data.begin(), axes_data.end(), 0); + } + auto axes = std::make_shared(ngraph::element::i64, ngraph::Shape{axes_data.size()}, axes_data); + auto norm = std::make_shared(ieInpNode, axes, epsilon, ngraph::op::EpsMode::ADD); + + CV_Assert(blobs.empty() || numChannels == blobs[0].total()); + std::vector shape(ieInpNode->get_shape().size(), 1); + shape[0] = blobs.empty() ? 1 : batch; + shape[1] = numChannels; + std::shared_ptr weight; + if (blobs.empty()) + { + std::vector ones(numChannels, 1); + weight = std::make_shared(ngraph::element::f32, ngraph::Shape(shape), ones.data()); + } + else + { + // weight->get_shape().size() > 1 ~> channel_shared = false + weight = std::make_shared( + ngraph::element::f32, ngraph::Shape(shape), blobs[0].data); + } + auto mul = std::make_shared(norm, weight, ngraph::op::AutoBroadcastType::NUMPY); + return Ptr(new InfEngineNgraphNode(mul)); + } +#endif // HAVE_DNN_NGRAPH + private: int startAxis, endAxis; }; diff --git a/modules/dnn/src/layers/padding_layer.cpp b/modules/dnn/src/layers/padding_layer.cpp index cffb84d692..f25a0873ba 100644 --- a/modules/dnn/src/layers/padding_layer.cpp +++ b/modules/dnn/src/layers/padding_layer.cpp @@ -13,6 +13,8 @@ Implementation of padding layer, which adds paddings to input blob. #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include namespace cv @@ -94,7 +96,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { #ifdef HAVE_INF_ENGINE - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) return INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R1) && (preferableTarget != DNN_TARGET_MYRIAD || (dstRanges.size() == 4 && paddings[0].first == 0 && paddings[0].second == 0)); @@ -207,6 +209,29 @@ public: } #endif +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + std::vector begins(paddings.size(), 0), ends(paddings.size(), 0); + for (int i = 0; i < paddings.size(); ++i) + { + begins[i] = static_cast(paddings[i].first); + ends[i] = static_cast(paddings[i].second); + } + auto padding_below = std::make_shared(ngraph::element::i64, ngraph::Shape{begins.size()}, begins.data()); + auto padding_above = std::make_shared(ngraph::element::i64, ngraph::Shape{ends.size()}, ends.data()); + auto pad_mode = paddingType == "constant" ? ngraph::op::PadMode::CONSTANT : ngraph::op::PadMode::REFLECT; // SYMMETRIC + auto arg_pad_value = std::make_shared(ngraph::element::f32, ngraph::Shape{}, &paddingValue);; + + auto pad = paddingType == "constant" ? + std::make_shared(ieInpNode, padding_below, padding_above, arg_pad_value, pad_mode) : + std::make_shared(ieInpNode, padding_below, padding_above, pad_mode); + return Ptr(new InfEngineNgraphNode(pad)); + } +#endif + private: std::vector > paddings; // Pairs pad before, pad after. std::vector dstRanges; diff --git a/modules/dnn/src/layers/permute_layer.cpp b/modules/dnn/src/layers/permute_layer.cpp index 009ceeb1d5..43abc5697a 100644 --- a/modules/dnn/src/layers/permute_layer.cpp +++ b/modules/dnn/src/layers/permute_layer.cpp @@ -43,6 +43,7 @@ #include "../precomp.hpp" #include "layers_common.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #include #include @@ -105,7 +106,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine()); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine()); } bool getMemoryShapes(const std::vector &inputs, @@ -379,6 +380,18 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + auto tr_axes = std::make_shared(ngraph::element::i64, + ngraph::Shape({_order.size()}), _order.data()); + auto transpose = std::make_shared(ieInpNode, tr_axes); + return Ptr(new InfEngineNgraphNode(transpose)); + } +#endif // HAVE_DNN_NGRAPH + size_t _count; std::vector _order; diff --git a/modules/dnn/src/layers/pooling_layer.cpp b/modules/dnn/src/layers/pooling_layer.cpp index 380178d576..5727e2b3f9 100644 --- a/modules/dnn/src/layers/pooling_layer.cpp +++ b/modules/dnn/src/layers/pooling_layer.cpp @@ -45,6 +45,13 @@ #include "opencv2/core/hal/intrin.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" + +#ifdef HAVE_DNN_NGRAPH +#include "../ie_ngraph.hpp" +#include +#include +#endif + #include #include #include @@ -160,7 +167,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { if (computeMaxIdx) return false; @@ -181,6 +188,9 @@ public: return false; #endif } + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) { + return type != STOCHASTIC; + } else return (kernel_size.size() == 3 && backendId == DNN_BACKEND_OPENCV && preferableTarget == DNN_TARGET_CPU) || ((kernel_size.empty() || kernel_size.size() == 2) && (backendId == DNN_BACKEND_OPENCV || @@ -333,6 +343,50 @@ public: #endif // HAVE_INF_ENGINE + +#ifdef HAVE_DNN_NGRAPH +virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE +{ + CV_Assert_N((inputs.size() == 1 && (type == MAX || type == AVE)) || inputs.size() == 2, nodes.size() == inputs.size()); + auto& ieInpNode = nodes[0].dynamicCast()->node; + + ngraph::op::PadType pad_type = ngraph::op::PadType::EXPLICIT; + if (!padMode.empty()) + pad_type = padMode == "VALID" ? ngraph::op::PadType::VALID : ngraph::op::PadType::SAME_UPPER; + + auto rounding_type = ceilMode ? ngraph::op::RoundingType::CEIL : ngraph::op::RoundingType::FLOOR; + if (type == AVE) { + auto exclude_pad = !avePoolPaddedArea; + auto ave_pool = std::make_shared(ieInpNode, ngraph::Strides(strides), + ngraph::Shape(pads_begin), ngraph::Shape(pads_end), ngraph::Shape(kernel_size), + exclude_pad, rounding_type, pad_type); + return Ptr(new InfEngineNgraphNode(ave_pool)); + } + else if (type == MAX) { + auto max_pool = std::make_shared(ieInpNode, ngraph::Strides(strides), + ngraph::Shape(pads_begin), ngraph::Shape(pads_end), ngraph::Shape(kernel_size), + rounding_type, pad_type); + return Ptr(new InfEngineNgraphNode(max_pool)); + } + else if (type == ROI) { + auto& coords = nodes[1].dynamicCast()->node; + auto roi = std::make_shared(ieInpNode, coords, + ngraph::Shape{(size_t)pooledSize.height, (size_t)pooledSize.width}, spatialScale, "max"); + return Ptr(new InfEngineNgraphNode(roi)); + } + else if (type == PSROI) { + auto& coords = nodes[1].dynamicCast()->node; + auto psroi = std::make_shared(ieInpNode, coords, + (size_t)psRoiOutChannels, (size_t)pooledSize.width, spatialScale, 1, 1, "average"); + return Ptr(new InfEngineNgraphNode(psroi)); + } + else + CV_Error(Error::StsNotImplemented, "Unsupported pooling type"); +} +#endif // HAVE_DNN_NGRAPH + + class PoolingInvoker : public ParallelLoopBody { public: diff --git a/modules/dnn/src/layers/prior_box_layer.cpp b/modules/dnn/src/layers/prior_box_layer.cpp index 4e0a6e018f..fd37004da3 100644 --- a/modules/dnn/src/layers/prior_box_layer.cpp +++ b/modules/dnn/src/layers/prior_box_layer.cpp @@ -43,6 +43,13 @@ #include "../precomp.hpp" #include "layers_common.hpp" #include "../op_inf_engine.hpp" + +#ifdef HAVE_DNN_NGRAPH +#include "../ie_ngraph.hpp" +#include +#include +#endif + #include #include #include @@ -272,8 +279,12 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { +#ifdef HAVE_DNN_NGRAPH + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + return _explicitSizes || _stepX == _stepY; +#endif return backendId == DNN_BACKEND_OPENCV || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine() && + (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && haveInfEngine() && ( _explicitSizes || (_minSize.size() == 1 && _maxSize.size() <= 1))); } @@ -545,6 +556,66 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert(nodes.size() == 2); + auto layer = nodes[0].dynamicCast()->node; + auto image = nodes[1].dynamicCast()->node; + auto layer_shape = std::make_shared(layer); + auto image_shape = std::make_shared(image); + + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{1}, std::vector{2}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{1}, std::vector{4}); + auto strides = std::make_shared(ngraph::element::i64, ngraph::Shape{1}, std::vector{1}); + + auto slice_layer = std::make_shared(layer_shape, lower_bounds, upper_bounds, strides); + auto slice_image = std::make_shared(image_shape, lower_bounds, upper_bounds, strides); + + if (_explicitSizes) + { + CV_Assert_N(!_boxWidths.empty(), !_boxHeights.empty(), !_variance.empty()); + CV_Assert(_boxWidths.size() == _boxHeights.size()); + ngraph::op::PriorBoxClusteredAttrs attrs; + attrs.widths = _boxWidths; + attrs.heights = _boxHeights; + attrs.clip = _clip; + CV_CheckEQ(_offsetsX.size(), (size_t)1, ""); CV_CheckEQ(_offsetsY.size(), (size_t)1, ""); CV_CheckEQ(_offsetsX[0], _offsetsY[0], ""); + attrs.offset = _offsetsX[0]; + attrs.step_heights = _stepY; + attrs.step_widths = _stepX; + attrs.variances = _variance; + + auto priorBox = std::make_shared(slice_layer, slice_image, attrs); + auto axis = std::make_shared(ngraph::element::i64, ngraph::Shape{1}, std::vector{0}); + auto unsqueeze = std::make_shared(priorBox, axis); + return Ptr(new InfEngineNgraphNode(unsqueeze)); + } + else + { + ngraph::op::PriorBoxAttrs attrs; + attrs.min_size = _minSize; + attrs.max_size = _maxSize; + // doesn't work with empty aspectRatio + attrs.aspect_ratio = !_aspectRatios.empty()? _aspectRatios : std::vector{1.0f}; + attrs.clip = _clip; + attrs.flip = false; + attrs.variance = _variance; + CV_CheckEQ(_offsetsX.size(), (size_t)1, ""); CV_CheckEQ(_offsetsY.size(), (size_t)1, ""); CV_CheckEQ(_offsetsX[0], _offsetsY[0], ""); + attrs.offset = _offsetsX[0]; + + attrs.step = _stepX; + attrs.scale_all_sizes = !_aspectRatios.empty(); + + auto priorBox = std::make_shared(slice_layer, slice_image, attrs); + auto axis = std::make_shared(ngraph::element::i64, ngraph::Shape{1}, std::vector{0}); + auto unsqueeze = std::make_shared(priorBox, axis); + return Ptr(new InfEngineNgraphNode(unsqueeze)); + } + } +#endif // HAVE_DNN_NGRAPH + + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/proposal_layer.cpp b/modules/dnn/src/layers/proposal_layer.cpp index 5f5c029bfd..e0930e8abb 100644 --- a/modules/dnn/src/layers/proposal_layer.cpp +++ b/modules/dnn/src/layers/proposal_layer.cpp @@ -8,6 +8,11 @@ #include "layers_common.hpp" #include "../op_inf_engine.hpp" +#ifdef HAVE_DNN_NGRAPH +#include "../ie_ngraph.hpp" +#include +#endif + namespace cv { namespace dnn { class ProposalLayerImpl CV_FINAL : public ProposalLayer @@ -87,7 +92,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && preferableTarget != DNN_TARGET_MYRIAD); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && preferableTarget != DNN_TARGET_MYRIAD); } bool getMemoryShapes(const std::vector &inputs, @@ -348,6 +353,45 @@ public: } #endif // HAVE_INF_ENGINE + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert(nodes.size() == 3); + ngraph::op::ProposalAttrs attr; + attr.base_size = baseSize; + attr.nms_thresh = nmsThreshold; + attr.feat_stride = featStride; + attr.min_size = 16; + attr.pre_nms_topn = keepTopBeforeNMS; + attr.post_nms_topn = keepTopAfterNMS; + + std::vector ratiosVec(ratios.size()); + for (int i = 0; i < ratios.size(); ++i) + ratiosVec[i] = ratios.get(i); + attr.ratio = ratiosVec; + + std::vector scalesVec(scales.size()); + for (int i = 0; i < scales.size(); ++i) + scalesVec[i] = scales.get(i); + attr.scale = scalesVec; + + auto& class_probs = nodes[0].dynamicCast()->node; + auto& class_logits = nodes[1].dynamicCast()->node; + auto& image_shape = nodes[2].dynamicCast()->node; + + CV_Assert_N(image_shape->get_shape().size() == 2, image_shape->get_shape().front() == 1); + auto shape = std::make_shared(ngraph::element::i64, + ngraph::Shape{1}, + std::vector{(int64_t)image_shape->get_shape().back()}); + auto reshape = std::make_shared(image_shape, shape, true); + + auto proposal = std::make_shared(class_probs, class_logits, reshape, attr); + return Ptr(new InfEngineNgraphNode(proposal)); + } +#endif // HAVE_DNN_NGRAPH + private: // A first half of channels are background scores. We need only a second one. static Mat getObjectScores(const Mat& m) diff --git a/modules/dnn/src/layers/reorg_layer.cpp b/modules/dnn/src/layers/reorg_layer.cpp index 659a79521a..94f49e63bb 100644 --- a/modules/dnn/src/layers/reorg_layer.cpp +++ b/modules/dnn/src/layers/reorg_layer.cpp @@ -42,6 +42,7 @@ #include "../precomp.hpp" #include "../op_inf_engine.hpp" + #include #include @@ -49,6 +50,11 @@ #include "opencl_kernels_dnn.hpp" #endif +#ifdef HAVE_DNN_NGRAPH +#include "../ie_ngraph.hpp" +#include +#endif + namespace cv { namespace dnn @@ -135,7 +141,8 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { - return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_INFERENCE_ENGINE; + return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || + backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } #ifdef HAVE_OPENCL @@ -187,6 +194,16 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector > &inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + auto reorg = std::make_shared(ieInpNode, ngraph::Strides{(size_t)reorgStride}); + return Ptr(new InfEngineNgraphNode(reorg)); + } +#endif // HAVE_DNN_NGRAPH + virtual int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/layers/reshape_layer.cpp b/modules/dnn/src/layers/reshape_layer.cpp index 5cbfc03e59..14d3ac5fef 100644 --- a/modules/dnn/src/layers/reshape_layer.cpp +++ b/modules/dnn/src/layers/reshape_layer.cpp @@ -43,6 +43,8 @@ #include "../precomp.hpp" #include "layers_common.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include namespace cv @@ -179,7 +181,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine()); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine()); } bool getMemoryShapes(const std::vector &inputs, @@ -268,6 +270,21 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert(outShapes.size() == 1); + auto& ieInpNode = nodes[0].dynamicCast()->node; + + std::vector out(outShapes[0].begin(), outShapes[0].end()); + auto shape = std::make_shared(ngraph::element::i64, + ngraph::Shape{out.size()}, out.data()); + auto reshape = std::make_shared(ieInpNode, shape, true); + return Ptr(new InfEngineNgraphNode(reshape)); + } +#endif // HAVE_DNN_NGRAPH + private: std::vector outShapes; }; diff --git a/modules/dnn/src/layers/resize_layer.cpp b/modules/dnn/src/layers/resize_layer.cpp index 339f2b7932..88ad078fe0 100644 --- a/modules/dnn/src/layers/resize_layer.cpp +++ b/modules/dnn/src/layers/resize_layer.cpp @@ -9,6 +9,11 @@ #include "../op_inf_engine.hpp" #include +#ifdef HAVE_DNN_NGRAPH +#include "../ie_ngraph.hpp" +#include +#endif + namespace cv { namespace dnn { class ResizeLayerImpl : public ResizeLayer @@ -52,7 +57,8 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { #ifdef HAVE_INF_ENGINE - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || + backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) { return (interpolation == "nearest" && scaleWidth == scaleHeight) || (interpolation == "bilinear"); @@ -191,6 +197,35 @@ public: return Ptr(); } + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + + ngraph::op::InterpolateAttrs attrs; + attrs.pads_begin.push_back(0); + attrs.pads_end.push_back(0); + attrs.axes = ngraph::AxisSet{2, 3}; + attrs.align_corners = false; + + if (interpolation == "nearest") { + attrs.mode = "nearest"; + attrs.antialias = false; + } else if (interpolation == "bilinear") { + attrs.mode = "linear"; + } else { + CV_Error(Error::StsNotImplemented, "Unsupported interpolation: " + interpolation); + } + + std::vector shape = {outHeight, outWidth}; + auto out_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, shape.data()); + auto interp = std::make_shared(ieInpNode, out_shape, attrs); + return Ptr(new InfEngineNgraphNode(interp)); + } +#endif // HAVE_DNN_NGRAPH + protected: int outWidth, outHeight, zoomFactorWidth, zoomFactorHeight; String interpolation; @@ -224,7 +259,12 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { - return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_INFERENCE_ENGINE; +#ifdef HAVE_INF_ENGINE + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 + || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + return true; +#endif + return backendId == DNN_BACKEND_OPENCV; } virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE @@ -260,6 +300,23 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + ngraph::op::InterpolateAttrs attrs; + attrs.pads_begin.push_back(0); + attrs.pads_end.push_back(0); + attrs.axes = ngraph::AxisSet{2, 3}; + attrs.mode = "linear"; + std::vector shape = {outHeight, outWidth}; + auto out_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, shape.data()); + auto interp = std::make_shared(ieInpNode, out_shape, attrs); + return Ptr(new InfEngineNgraphNode(interp)); + } +#endif // HAVE_DNN_NGRAPH + }; Ptr InterpLayer::create(const LayerParams& params) diff --git a/modules/dnn/src/layers/scale_layer.cpp b/modules/dnn/src/layers/scale_layer.cpp index 4486a0f6de..620b65741c 100644 --- a/modules/dnn/src/layers/scale_layer.cpp +++ b/modules/dnn/src/layers/scale_layer.cpp @@ -13,6 +13,8 @@ Implementation of Scale layer. #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include namespace cv @@ -51,7 +53,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && axis == 1); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && axis == 1); } void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE @@ -222,6 +224,34 @@ public: } #endif // HAVE_INF_ENGINE + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert(!blobs.empty()); + const size_t numChannels = blobs[0].total(); + auto ieInpNode = nodes[0].dynamicCast()->node; + + std::vector shape(ieInpNode->get_shape().size(), 1); + shape[1] = numChannels; + auto weight = hasWeights ? + std::make_shared(ngraph::element::f32, + ngraph::Shape(shape), blobs[0].data) : + std::make_shared(ngraph::element::f32, + ngraph::Shape(shape), std::vector(numChannels, 1).data()); + + auto bias = hasBias ? + std::make_shared(ngraph::element::f32, + ngraph::Shape(shape), blobs.back().data) : + std::make_shared(ngraph::element::f32, + ngraph::Shape(shape), std::vector(numChannels, 0).data()); + + auto scale_node = std::make_shared(ieInpNode, weight, ngraph::op::AutoBroadcastType::NUMPY); + auto scale_shift = std::make_shared(scale_node, bias, ngraph::op::AutoBroadcastType::NUMPY); + return Ptr(new InfEngineNgraphNode(scale_shift)); + } +#endif // HAVE_DNN_NGRAPH + void getScaleShift(Mat& scale, Mat& shift) const CV_OVERRIDE { scale = hasWeights ? blobs[0] : Mat(); diff --git a/modules/dnn/src/layers/slice_layer.cpp b/modules/dnn/src/layers/slice_layer.cpp index 430555161b..ea2562380f 100644 --- a/modules/dnn/src/layers/slice_layer.cpp +++ b/modules/dnn/src/layers/slice_layer.cpp @@ -42,6 +42,8 @@ #include "../precomp.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include "layers_common.hpp" #include @@ -112,7 +114,7 @@ public: virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && #ifdef HAVE_INF_ENGINE INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R1) && #endif @@ -316,6 +318,35 @@ public: } #endif #endif + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert_N(nodes.size() <= 2); + auto& ieInpNode = nodes[0].dynamicCast()->node; + CV_Assert(sliceRanges[0].size() == ieInpNode->get_shape().size()); + + std::vector offsets, dims; + for (int i = 0; i < sliceRanges[0].size(); ++i) + { + offsets.push_back(sliceRanges[0][i].start); + dims.push_back(sliceRanges[0][i].end); + } + + auto lower_bounds = std::make_shared(ngraph::element::i64, + ngraph::Shape{offsets.size()}, offsets.data()); + auto upper_bounds = std::make_shared(ngraph::element::i64, + ngraph::Shape{dims.size()}, dims.data()); + auto strides = std::make_shared(ngraph::element::i64, + ngraph::Shape{dims.size()}, std::vector((int64_t)dims.size(), 1)); + + auto slice = std::make_shared(ieInpNode, lower_bounds, upper_bounds, + strides, ngraph::AxisSet{}, ngraph::AxisSet{}); + return Ptr(new InfEngineNgraphNode(slice)); + } +#endif // HAVE_DNN_NGRAPH + }; class CropLayerImpl CV_FINAL : public SliceLayerImpl diff --git a/modules/dnn/src/layers/softmax_layer.cpp b/modules/dnn/src/layers/softmax_layer.cpp index 47d6ed9848..75e31006de 100644 --- a/modules/dnn/src/layers/softmax_layer.cpp +++ b/modules/dnn/src/layers/softmax_layer.cpp @@ -44,6 +44,8 @@ #include "layers_common.hpp" #include "../op_halide.hpp" #include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" + #include #include using std::max; @@ -90,7 +92,7 @@ public: { return backendId == DNN_BACKEND_OPENCV || (backendId == DNN_BACKEND_HALIDE && haveHalide() && axisRaw == 1) || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine() && !logSoftMax); + ((backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && haveInfEngine() && !logSoftMax); } #ifdef HAVE_OPENCL @@ -321,6 +323,17 @@ public: } #endif // HAVE_INF_ENGINE +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& ieInpNode = nodes[0].dynamicCast()->node; + int axis = clamp(axisRaw, ieInpNode->get_shape().size()); + auto softmax = std::make_shared(ieInpNode, axis); + return Ptr(new InfEngineNgraphNode(softmax)); + } +#endif // HAVE_DNN_NGRAPH + int64 getFLOPS(const std::vector &inputs, const std::vector &outputs) const CV_OVERRIDE { diff --git a/modules/dnn/src/op_inf_engine.cpp b/modules/dnn/src/op_inf_engine.cpp index d784899698..17b2d7271b 100644 --- a/modules/dnn/src/op_inf_engine.cpp +++ b/modules/dnn/src/op_inf_engine.cpp @@ -21,6 +21,54 @@ namespace cv { namespace dnn { #ifdef HAVE_INF_ENGINE +static Backend parseInferenceEngineBackendType(const cv::String& backend) +{ + CV_Assert(!backend.empty()); + if (backend == CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + return DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; + if (backend == CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API) + return DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019; + CV_Error(Error::StsBadArg, cv::format("Unknown IE backend: %s", backend.c_str())); +} +static const char* dumpInferenceEngineBackendType(Backend backend) +{ + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + return CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + return CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API; + CV_Error(Error::StsBadArg, cv::format("Invalid backend ID for IE: %d", backend)); +} +Backend& getInferenceEngineBackendTypeParam() +{ + static Backend param = parseInferenceEngineBackendType( + utils::getConfigurationParameterString("OPENCV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019_TYPE", +#ifdef HAVE_NGRAPH + CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API // future: CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH +#else + CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API +#endif + ) + ); + return param; +} + +CV__DNN_EXPERIMENTAL_NS_BEGIN + +cv::String getInferenceEngineBackendType() +{ + return dumpInferenceEngineBackendType(getInferenceEngineBackendTypeParam()); +} +cv::String setInferenceEngineBackendType(const cv::String& newBackendType) +{ + Backend newBackend = parseInferenceEngineBackendType(newBackendType); + Backend& param = getInferenceEngineBackendTypeParam(); + Backend old = param; + param = newBackend; + return dumpInferenceEngineBackendType(old); +} + +CV__DNN_EXPERIMENTAL_NS_END + // For networks with input layer which has an empty name, IE generates a name id[some_number]. // OpenCV lets users use an empty input name and to prevent unexpected naming, // we can use some predefined name. @@ -161,38 +209,25 @@ private: InferenceEngine::CNNLayer cnnLayer; }; -class InfEngineExtension : public InferenceEngine::IExtension +InferenceEngine::StatusCode InfEngineExtension::getFactoryFor( + InferenceEngine::ILayerImplFactory*& factory, + const InferenceEngine::CNNLayer* cnnLayer, + InferenceEngine::ResponseDesc* resp +) noexcept { -public: - virtual void SetLogCallback(InferenceEngine::IErrorListener&) noexcept {} - virtual void Unload() noexcept {} - virtual void Release() noexcept {} - virtual void GetVersion(const InferenceEngine::Version*&) const noexcept {} - - virtual InferenceEngine::StatusCode getPrimitiveTypes(char**&, unsigned int&, - InferenceEngine::ResponseDesc*) noexcept - { - return InferenceEngine::StatusCode::OK; - } - - InferenceEngine::StatusCode getFactoryFor(InferenceEngine::ILayerImplFactory*& factory, - const InferenceEngine::CNNLayer* cnnLayer, - InferenceEngine::ResponseDesc* resp) noexcept - { - if (cnnLayer->type != kOpenCVLayersType) - return InferenceEngine::StatusCode::NOT_IMPLEMENTED; - factory = new InfEngineCustomLayerFactory(cnnLayer); - return InferenceEngine::StatusCode::OK; - } -}; + if (cnnLayer->type != kOpenCVLayersType) + return InferenceEngine::StatusCode::NOT_IMPLEMENTED; + factory = new InfEngineCustomLayerFactory(cnnLayer); + return InferenceEngine::StatusCode::OK; +} InfEngineBackendNode::InfEngineBackendNode(const InferenceEngine::Builder::Layer& _layer) - : BackendNode(DNN_BACKEND_INFERENCE_ENGINE), layer(_layer) {} + : BackendNode(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019), layer(_layer) {} InfEngineBackendNode::InfEngineBackendNode(Ptr& cvLayer_, std::vector& inputs, std::vector& outputs, std::vector& internals) - : BackendNode(DNN_BACKEND_INFERENCE_ENGINE), layer(cvLayer_->name), + : BackendNode(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019), layer(cvLayer_->name), cvLayer(cvLayer_) { CV_Assert(!cvLayer->name.empty()); @@ -269,7 +304,7 @@ void InfEngineBackendNet::connect(const std::vector >& input #endif } -void InfEngineBackendNet::init(int targetId) +void InfEngineBackendNet::init(Target targetId) { if (!hasNetOwner) { @@ -403,7 +438,7 @@ static InferenceEngine::Layout estimateLayout(const Mat& m) static InferenceEngine::DataPtr wrapToInfEngineDataNode(const Mat& m, const std::string& name = "") { - std::vector shape(&m.size[0], &m.size[0] + m.dims); + std::vector shape = getShape(m); if (m.type() == CV_32F) return InferenceEngine::DataPtr(new InferenceEngine::Data(name, {InferenceEngine::Precision::FP32, shape, estimateLayout(m)})); @@ -429,7 +464,7 @@ InferenceEngine::Blob::Ptr wrapToInfEngineBlob(const Mat& m, const std::vector shape(&m.size[0], &m.size[0] + m.dims); + std::vector shape = getShape(m); return wrapToInfEngineBlob(m, shape, layout); } @@ -461,14 +496,14 @@ InferenceEngine::DataPtr infEngineDataNode(const Ptr& ptr) } InfEngineBackendWrapper::InfEngineBackendWrapper(int targetId, const cv::Mat& m) - : BackendWrapper(DNN_BACKEND_INFERENCE_ENGINE, targetId) + : BackendWrapper(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, targetId) { dataPtr = wrapToInfEngineDataNode(m); blob = wrapToInfEngineBlob(m, estimateLayout(m)); } InfEngineBackendWrapper::InfEngineBackendWrapper(Ptr wrapper) - : BackendWrapper(DNN_BACKEND_INFERENCE_ENGINE, wrapper->targetId) + : BackendWrapper(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, wrapper->targetId) { Ptr ieWrapper = wrapper.dynamicCast(); CV_Assert(!ieWrapper.empty()); @@ -505,7 +540,7 @@ static std::map& getShar return sharedPlugins; } #else -static InferenceEngine::Core& getCore() +InferenceEngine::Core& getCore() { static InferenceEngine::Core core; return core; @@ -564,7 +599,11 @@ static bool detectMyriadX_() #else try { +#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R3) auto netExec = getCore().LoadNetwork(cnn, "MYRIAD", {{"VPU_PLATFORM", "VPU_2480"}}); +#else + auto netExec = getCore().LoadNetwork(cnn, "MYRIAD", {{"VPU_MYRIAD_PLATFORM", "VPU_MYRIAD_2480"}}); +#endif #endif auto infRequest = netExec.CreateInferRequest(); } catch(...) { @@ -703,7 +742,7 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::CNNNetwork& net) } catch (const std::exception& ex) { - CV_Error(Error::StsAssert, format("Failed to initialize Inference Engine backend: %s", ex.what())); + CV_Error(Error::StsError, format("Failed to initialize Inference Engine backend (device = %s): %s", device_name.c_str(), ex.what())); } } @@ -743,6 +782,7 @@ void InfEngineBackendNet::InfEngineReqWrapper::makePromises(const std::vector >& outBlobsWrappers, bool isAsync) { + CV_LOG_DEBUG(NULL, "InfEngineBackendNet::forward(" << (isAsync ? "async" : "sync") << ")"); // Look for finished requests. Ptr reqWrapper; for (auto& wrapper : infRequests) @@ -790,6 +830,8 @@ void InfEngineBackendNet::forward(const std::vector >& outBl infRequestPtr->SetCompletionCallback( [](InferenceEngine::IInferRequest::Ptr request, InferenceEngine::StatusCode status) { + CV_LOG_DEBUG(NULL, "DNN(IE): completionCallback(" << (int)status << ")"); + InfEngineReqWrapper* wrapper; request->GetUserData((void**)&wrapper, 0); CV_Assert(wrapper && "Internal error"); @@ -915,8 +957,9 @@ bool InfEngineBackendLayer::getMemoryShapes(const std::vector &inputs, bool InfEngineBackendLayer::supportBackend(int backendId) { + CV_LOG_DEBUG(NULL, "InfEngineBackendLayer::supportBackend(" << backendId << ")"); return backendId == DNN_BACKEND_DEFAULT || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine()); + (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019); } void InfEngineBackendLayer::forward(InputArrayOfArrays inputs, OutputArrayOfArrays outputs, @@ -1029,7 +1072,18 @@ cv::String getInferenceEngineVPUType() static cv::String vpu_type = getInferenceEngineVPUType_(); return vpu_type; } + #else // HAVE_INF_ENGINE + +cv::String getInferenceEngineBackendType() +{ + CV_Error(Error::StsNotImplemented, "This OpenCV build doesn't include InferenceEngine support"); +} +cv::String setInferenceEngineBackendType(const cv::String& newBackendType) +{ + CV_UNUSED(newBackendType); + CV_Error(Error::StsNotImplemented, "This OpenCV build doesn't include InferenceEngine support"); +} cv::String getInferenceEngineVPUType() { CV_Error(Error::StsNotImplemented, "This OpenCV build doesn't include InferenceEngine support"); diff --git a/modules/dnn/src/op_inf_engine.hpp b/modules/dnn/src/op_inf_engine.hpp index b025ab05bf..8524ad9477 100644 --- a/modules/dnn/src/op_inf_engine.hpp +++ b/modules/dnn/src/op_inf_engine.hpp @@ -71,6 +71,8 @@ namespace cv { namespace dnn { #ifdef HAVE_INF_ENGINE +Backend& getInferenceEngineBackendTypeParam(); + class InfEngineBackendNet { public: @@ -88,7 +90,7 @@ public: bool isInitialized(); - void init(int targetId); + void init(Target targetId); void forward(const std::vector >& outBlobsWrappers, bool isAsync); @@ -210,12 +212,44 @@ private: InferenceEngine::CNNNetwork t_net; }; +class InfEngineExtension : public InferenceEngine::IExtension +{ +public: + virtual void SetLogCallback(InferenceEngine::IErrorListener&) noexcept {} + virtual void Unload() noexcept {} + virtual void Release() noexcept {} + virtual void GetVersion(const InferenceEngine::Version*&) const noexcept {} + + virtual InferenceEngine::StatusCode getPrimitiveTypes(char**&, unsigned int&, + InferenceEngine::ResponseDesc*) noexcept + { + return InferenceEngine::StatusCode::OK; + } + + InferenceEngine::StatusCode getFactoryFor(InferenceEngine::ILayerImplFactory*& factory, + const InferenceEngine::CNNLayer* cnnLayer, + InferenceEngine::ResponseDesc* resp) noexcept; +}; + + CV__DNN_EXPERIMENTAL_NS_BEGIN bool isMyriadX(); CV__DNN_EXPERIMENTAL_NS_END +InferenceEngine::Core& getCore(); + +template +static inline std::vector getShape(const Mat& mat) +{ + std::vector result(mat.dims); + for (int i = 0; i < mat.dims; i++) + result[i] = (T)mat.size[i]; + return result; +} + + #endif // HAVE_INF_ENGINE bool haveInfEngine(); diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index e266d3b464..b1d7178798 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -1350,6 +1350,8 @@ void TFImporter::populateNet(Net dstNet) setKSize(layerParams, layer); setStrides(layerParams, layer); setPadding(layerParams, layer); + // Test_TensorFlow_nets.EAST_text_detection/1, NGRAPH/CPU + layerParams.set("ceil_mode", false); int id = dstNet.addLayer(name, "Pooling", layerParams); layer_id[name] = id; diff --git a/modules/dnn/test/test_backends.cpp b/modules/dnn/test/test_backends.cpp index 57672d80bc..8959612b43 100644 --- a/modules/dnn/test/test_backends.cpp +++ b/modules/dnn/test/test_backends.cpp @@ -78,7 +78,7 @@ public: { if (outputLayer == "detection_out") { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { // Inference Engine produces detections terminated by a row which starts from -1. out = out.reshape(1, out.total() / 7); @@ -142,7 +142,7 @@ TEST_P(DNNTestNetwork, Inception_5h) { applyTestTag(CV_TEST_TAG_MEMORY_512MB); double l1 = default_l1, lInf = default_lInf; - if (backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_CPU || target == DNN_TARGET_OPENCL)) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_CPU || target == DNN_TARGET_OPENCL)) { l1 = 1.72e-5; lInf = 8e-4; @@ -157,8 +157,10 @@ TEST_P(DNNTestNetwork, Inception_5h) TEST_P(DNNTestNetwork, ENet) { applyTestTag(target == DNN_TARGET_CPU ? "" : CV_TEST_TAG_MEMORY_512MB); - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); processNet("dnn/Enet-model-best.net", "", Size(512, 512), "l367_Deconvolution", @@ -187,7 +189,7 @@ TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe_Different_Width_Height) if (backend == DNN_BACKEND_HALIDE) applyTestTag(CV_TEST_TAG_DNN_SKIP_HALIDE); #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); #endif @@ -221,13 +223,13 @@ TEST_P(DNNTestNetwork, MobileNet_SSD_v1_TensorFlow_Different_Width_Height) if (backend == DNN_BACKEND_HALIDE) applyTestTag(CV_TEST_TAG_DNN_SKIP_HALIDE); #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); #endif #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019020000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R2); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif Mat sample = imread(findDataFile("dnn/street.png")); @@ -276,9 +278,9 @@ TEST_P(DNNTestNetwork, OpenPose_pose_coco) if (backend == DNN_BACKEND_HALIDE) applyTestTag(CV_TEST_TAG_DNN_SKIP_HALIDE); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.0056 : 0.0; @@ -295,9 +297,9 @@ TEST_P(DNNTestNetwork, OpenPose_pose_mpi) if (backend == DNN_BACKEND_HALIDE) applyTestTag(CV_TEST_TAG_DNN_SKIP_HALIDE); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif // output range: [-0.001, 0.97] @@ -314,9 +316,9 @@ TEST_P(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages) if (backend == DNN_BACKEND_HALIDE) applyTestTag(CV_TEST_TAG_DNN_SKIP_HALIDE); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif // The same .caffemodel but modified .prototxt @@ -330,8 +332,8 @@ TEST_P(DNNTestNetwork, OpenFace) { #if defined(INF_ENGINE_RELEASE) #if INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif #endif if (backend == DNN_BACKEND_HALIDE) @@ -359,13 +361,13 @@ TEST_P(DNNTestNetwork, Inception_v2_SSD_TensorFlow) CV_TEST_TAG_DEBUG_LONG ); #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); #endif #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019020000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R2); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif if (backend == DNN_BACKEND_HALIDE) applyTestTag(CV_TEST_TAG_DNN_SKIP_HALIDE); @@ -404,13 +406,13 @@ TEST_P(DNNTestNetwork, FastNeuralStyle_eccv16) if (backend == DNN_BACKEND_HALIDE) applyTestTag(CV_TEST_TAG_DNN_SKIP_HALIDE); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); #if defined(INF_ENGINE_RELEASE) #if INF_ENGINE_VER_MAJOR_LE(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif #endif diff --git a/modules/dnn/test/test_caffe_importer.cpp b/modules/dnn/test/test_caffe_importer.cpp index 22cedbb9d3..3ec6f948d7 100644 --- a/modules/dnn/test/test_caffe_importer.cpp +++ b/modules/dnn/test/test_caffe_importer.cpp @@ -112,8 +112,10 @@ TEST(Test_Caffe, read_googlenet) TEST_P(Test_Caffe_nets, Axpy) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); String proto = _tf("axpy.prototxt"); Net net = readNetFromCaffe(proto); @@ -299,7 +301,7 @@ TEST_P(Reproducibility_MobileNet_SSD, Accuracy) } // There is something wrong with Reshape layer in Myriad plugin. - if (backendId == DNN_BACKEND_INFERENCE_ENGINE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { if (targetId == DNN_TARGET_MYRIAD || targetId == DNN_TARGET_OPENCL_FP16) return; @@ -628,10 +630,10 @@ TEST_P(Test_Caffe_nets, FasterRCNN_vgg16) ); #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) + if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); #endif @@ -647,9 +649,9 @@ TEST_P(Test_Caffe_nets, FasterRCNN_zf) (target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB), CV_TEST_TAG_DEBUG_LONG ); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); static Mat ref = (Mat_(3, 7) << 0, 2, 0.90121, 120.407, 115.83, 570.586, 528.395, 0, 7, 0.988779, 469.849, 75.1756, 718.64, 186.762, @@ -664,9 +666,9 @@ TEST_P(Test_Caffe_nets, RFCN) CV_TEST_TAG_LONG, CV_TEST_TAG_DEBUG_VERYLONG ); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); double scoreDiff = (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) ? 4e-3 : default_l1; double iouDiff = (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) ? 8e-2 : default_lInf; diff --git a/modules/dnn/test/test_common.hpp b/modules/dnn/test/test_common.hpp index 3842d64be0..aa7e49537b 100644 --- a/modules/dnn/test/test_common.hpp +++ b/modules/dnn/test/test_common.hpp @@ -11,9 +11,19 @@ #include "opencv2/core/ocl.hpp" #endif +// src/op_inf_engine.hpp +#define INF_ENGINE_VER_MAJOR_GT(ver) (((INF_ENGINE_RELEASE) / 10000) > ((ver) / 10000)) +#define INF_ENGINE_VER_MAJOR_GE(ver) (((INF_ENGINE_RELEASE) / 10000) >= ((ver) / 10000)) +#define INF_ENGINE_VER_MAJOR_LT(ver) (((INF_ENGINE_RELEASE) / 10000) < ((ver) / 10000)) +#define INF_ENGINE_VER_MAJOR_LE(ver) (((INF_ENGINE_RELEASE) / 10000) <= ((ver) / 10000)) +#define INF_ENGINE_VER_MAJOR_EQ(ver) (((INF_ENGINE_RELEASE) / 10000) == ((ver) / 10000)) + + #define CV_TEST_TAG_DNN_SKIP_HALIDE "dnn_skip_halide" #define CV_TEST_TAG_DNN_SKIP_OPENCL "dnn_skip_ocl" #define CV_TEST_TAG_DNN_SKIP_OPENCL_FP16 "dnn_skip_ocl_fp16" +#define CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER "dnn_skip_ie_nn_builder" +#define CV_TEST_TAG_DNN_SKIP_IE_NGRAPH "dnn_skip_ie_ngraph" #define CV_TEST_TAG_DNN_SKIP_IE "dnn_skip_ie" #define CV_TEST_TAG_DNN_SKIP_IE_2018R5 "dnn_skip_ie_2018r5" #define CV_TEST_TAG_DNN_SKIP_IE_2019R1 "dnn_skip_ie_2019r1" @@ -27,6 +37,26 @@ #define CV_TEST_TAG_DNN_SKIP_IE_MYRIAD CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2, CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X +#ifdef HAVE_INF_ENGINE +#if INF_ENGINE_VER_MAJOR_EQ(2018050000) +# define CV_TEST_TAG_DNN_SKIP_IE_VERSION CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2018R5 +#elif INF_ENGINE_VER_MAJOR_EQ(2019010000) +# if INF_ENGINE_RELEASE < 2019010100 +# define CV_TEST_TAG_DNN_SKIP_IE_VERSION CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R1 +# else +# define CV_TEST_TAG_DNN_SKIP_IE_VERSION CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R1_1 +# endif +#elif INF_ENGINE_VER_MAJOR_EQ(2019020000) +# define CV_TEST_TAG_DNN_SKIP_IE_VERSION CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R2 +#elif INF_ENGINE_VER_MAJOR_EQ(2019030000) +# define CV_TEST_TAG_DNN_SKIP_IE_VERSION CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R3 +#endif +#endif // HAVE_INF_ENGINE + +#ifndef CV_TEST_TAG_DNN_SKIP_IE_VERSION +# define CV_TEST_TAG_DNN_SKIP_IE_VERSION CV_TEST_TAG_DNN_SKIP_IE +#endif + namespace cv { namespace dnn { CV__DNN_EXPERIMENTAL_NS_BEGIN @@ -86,9 +116,12 @@ bool validateVPUType(); testing::internal::ParamGenerator< tuple > dnnBackendsAndTargets( bool withInferenceEngine = true, bool withHalide = false, - bool withCpuOCV = true + bool withCpuOCV = true, + bool withNgraph = true ); +testing::internal::ParamGenerator< tuple > dnnBackendsAndTargetsIE(); + class DNNTestLayer : public TestWithParam > { @@ -120,7 +153,8 @@ public: static void checkBackend(int backend, int target, Mat* inp = 0, Mat* ref = 0) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + && target == DNN_TARGET_MYRIAD) { if (inp && ref && inp->dims == 4 && ref->dims == 4 && inp->size[0] != 1 && inp->size[0] != ref->size[0]) @@ -131,7 +165,7 @@ public: } } - void expectNoFallbacks(Net& net) + void expectNoFallbacks(Net& net, bool raiseError = true) { // Check if all the layers are supported with current backend and target. // Some layers might be fused so their timings equal to zero. @@ -140,20 +174,27 @@ public: std::vector names = net.getLayerNames(); CV_Assert(names.size() == timings.size()); + bool hasFallbacks = false; for (int i = 0; i < names.size(); ++i) { Ptr l = net.getLayer(net.getLayerId(names[i])); bool fused = !timings[i]; if ((!l->supportBackend(backend) || l->preferableTarget != target) && !fused) - CV_Error(Error::StsNotImplemented, "Layer [" + l->name + "] of type [" + - l->type + "] is expected to has backend implementation"); + { + hasFallbacks = true; + std::cout << "FALLBACK: Layer [" << l->type << "]:[" << l->name << "] is expected to has backend implementation" << endl; + } } + if (hasFallbacks && raiseError) + CV_Error(Error::StsNotImplemented, "Implementation fallbacks are not expected in this test"); } void expectNoFallbacksFromIE(Net& net) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) expectNoFallbacks(net); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + expectNoFallbacks(net, false); } protected: @@ -166,11 +207,4 @@ protected: } // namespace -// src/op_inf_engine.hpp -#define INF_ENGINE_VER_MAJOR_GT(ver) (((INF_ENGINE_RELEASE) / 10000) > ((ver) / 10000)) -#define INF_ENGINE_VER_MAJOR_GE(ver) (((INF_ENGINE_RELEASE) / 10000) >= ((ver) / 10000)) -#define INF_ENGINE_VER_MAJOR_LT(ver) (((INF_ENGINE_RELEASE) / 10000) < ((ver) / 10000)) -#define INF_ENGINE_VER_MAJOR_LE(ver) (((INF_ENGINE_RELEASE) / 10000) <= ((ver) / 10000)) -#define INF_ENGINE_VER_MAJOR_EQ(ver) (((INF_ENGINE_RELEASE) / 10000) == ((ver) / 10000)) - #endif diff --git a/modules/dnn/test/test_common.impl.hpp b/modules/dnn/test/test_common.impl.hpp index fee39cce68..c74e293a43 100644 --- a/modules/dnn/test/test_common.impl.hpp +++ b/modules/dnn/test/test_common.impl.hpp @@ -21,10 +21,13 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN void PrintTo(const cv::dnn::Backend& v, std::ostream* os) { switch (v) { - case DNN_BACKEND_DEFAULT: *os << "DEFAULT"; return; - case DNN_BACKEND_HALIDE: *os << "HALIDE"; return; - case DNN_BACKEND_INFERENCE_ENGINE: *os << "DLIE"; return; - case DNN_BACKEND_OPENCV: *os << "OCV"; return; + case DNN_BACKEND_DEFAULT: *os << "DEFAULT"; return; + case DNN_BACKEND_HALIDE: *os << "HALIDE"; return; + case DNN_BACKEND_INFERENCE_ENGINE: *os << "DLIE*"; return; + case DNN_BACKEND_OPENCV: *os << "OCV"; return; + case DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019: *os << "DLIE"; return; + case DNN_BACKEND_INFERENCE_ENGINE_NGRAPH: *os << "NGRAPH"; return; + default: /* do nothing */; } // don't use "default:" to emit compiler warnings *os << "DNN_BACKEND_UNKNOWN(" << (int)v << ")"; } @@ -179,7 +182,8 @@ void readFileContent(const std::string& filename, CV_OUT std::vector& cont testing::internal::ParamGenerator< tuple > dnnBackendsAndTargets( bool withInferenceEngine /*= true*/, bool withHalide /*= false*/, - bool withCpuOCV /*= true*/ + bool withCpuOCV /*= true*/, + bool withNgraph /*= true*/ ) { #ifdef HAVE_INF_ENGINE @@ -197,14 +201,25 @@ testing::internal::ParamGenerator< tuple > dnnBackendsAndTarget #ifdef HAVE_INF_ENGINE if (withInferenceEngine) { - available = getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE); + available = getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019); for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i) { if (*i == DNN_TARGET_MYRIAD && !withVPU) continue; - targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE, *i)); + targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, *i)); } } + if (withNgraph) + { + available = getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i) + { + if (*i == DNN_TARGET_MYRIAD && !withVPU) + continue; + targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, *i)); + } + + } #else CV_UNUSED(withInferenceEngine); #endif @@ -222,6 +237,40 @@ testing::internal::ParamGenerator< tuple > dnnBackendsAndTarget return testing::ValuesIn(targets); } +testing::internal::ParamGenerator< tuple > dnnBackendsAndTargetsIE() +{ +#ifdef HAVE_INF_ENGINE + bool withVPU = validateVPUType(); + + std::vector< tuple > targets; + std::vector< Target > available; + + { + available = getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019); + for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i) + { + if (*i == DNN_TARGET_MYRIAD && !withVPU) + continue; + targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019, *i)); + } + } + + { + available = getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i) + { + if (*i == DNN_TARGET_MYRIAD && !withVPU) + continue; + targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, *i)); + } + + } + + return testing::ValuesIn(targets); +#else + return testing::ValuesIn(std::vector< tuple >()); +#endif +} #ifdef HAVE_INF_ENGINE static std::string getTestInferenceEngineVPUType() @@ -306,6 +355,7 @@ void initDNNTests() ); #if defined(INF_ENGINE_RELEASE) registerGlobalSkipTag( + CV_TEST_TAG_DNN_SKIP_IE, #if INF_ENGINE_VER_MAJOR_EQ(2018050000) CV_TEST_TAG_DNN_SKIP_IE_2018R5, #elif INF_ENGINE_VER_MAJOR_EQ(2019010000) @@ -318,7 +368,10 @@ void initDNNTests() #elif INF_ENGINE_VER_MAJOR_EQ(2019030000) CV_TEST_TAG_DNN_SKIP_IE_2019R3, #endif - CV_TEST_TAG_DNN_SKIP_IE +#ifdef HAVE_DNN_NGRAPH + CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, +#endif + CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER ); #endif registerGlobalSkipTag( diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index 61e3cad9a8..fecc5aaa8e 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -261,11 +261,11 @@ TEST_P(Test_Darknet_nets, YoloVoc) applyTestTag(CV_TEST_TAG_LONG, CV_TEST_TAG_MEMORY_1GB); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019010000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); #endif #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); // need to update check function #endif @@ -301,7 +301,7 @@ TEST_P(Test_Darknet_nets, TinyYoloVoc) applyTestTag(CV_TEST_TAG_MEMORY_512MB); #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); // need to update check function #endif @@ -331,15 +331,23 @@ TEST_P(Test_Darknet_nets, TinyYoloVoc) #ifdef HAVE_INF_ENGINE static const std::chrono::milliseconds async_timeout(10000); -typedef testing::TestWithParam > Test_Darknet_nets_async; +typedef testing::TestWithParam > > Test_Darknet_nets_async; TEST_P(Test_Darknet_nets_async, Accuracy) { - if (INF_ENGINE_VER_MAJOR_LT(2019020000)) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + Backend backendId = get<0>(get<1>(GetParam())); + Target targetId = get<1>(get<1>(GetParam())); + + if (INF_ENGINE_VER_MAJOR_LT(2019020000) && backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); applyTestTag(CV_TEST_TAG_MEMORY_512MB); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); + std::string prefix = get<0>(GetParam()); - int target = get<1>(GetParam()); + + if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + throw SkipTestException("No support for async forward"); const int numInputs = 2; std::vector inputs(numInputs); @@ -352,7 +360,8 @@ TEST_P(Test_Darknet_nets_async, Accuracy) Net netSync = readNet(findDataFile("dnn/" + prefix + ".cfg"), findDataFile("dnn/" + prefix + ".weights", false)); - netSync.setPreferableTarget(target); + netSync.setPreferableBackend(backendId); + netSync.setPreferableTarget(targetId); // Run synchronously. std::vector refs(numInputs); @@ -364,7 +373,8 @@ TEST_P(Test_Darknet_nets_async, Accuracy) Net netAsync = readNet(findDataFile("dnn/" + prefix + ".cfg"), findDataFile("dnn/" + prefix + ".weights", false)); - netAsync.setPreferableTarget(target); + netAsync.setPreferableBackend(backendId); + netAsync.setPreferableTarget(targetId); // Run asynchronously. To make test more robust, process inputs in the reversed order. for (int i = numInputs - 1; i >= 0; --i) @@ -381,7 +391,7 @@ TEST_P(Test_Darknet_nets_async, Accuracy) INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_nets_async, Combine( Values("yolo-voc", "tiny-yolo-voc", "yolov3"), - ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE)) + dnnBackendsAndTargets() )); #endif @@ -408,7 +418,7 @@ TEST_P(Test_Darknet_nets, YOLOv3) std::string weights_file = "yolov3.weights"; #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD && + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) { scoreDiff = 0.04; @@ -422,16 +432,16 @@ TEST_P(Test_Darknet_nets, YOLOv3) } #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { if (INF_ENGINE_VER_MAJOR_LE(2018050000) && target == DNN_TARGET_OPENCL) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_VERSION); else if (INF_ENGINE_VER_MAJOR_EQ(2019020000)) { if (target == DNN_TARGET_OPENCL) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_2019R2); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_VERSION); if (target == DNN_TARGET_OPENCL_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_2019R2); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_VERSION); } else if (target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) diff --git a/modules/dnn/test/test_halide_layers.cpp b/modules/dnn/test/test_halide_layers.cpp index a9eff9faa2..757a98c612 100644 --- a/modules/dnn/test/test_halide_layers.cpp +++ b/modules/dnn/test/test_halide_layers.cpp @@ -165,7 +165,7 @@ TEST_P(Deconvolution, Accuracy) Target targetId = get<1>(get<7>(GetParam())); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019010000) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X && inChannels == 6 && outChannels == 4 && group == 1 && kernel == Size(1, 3) && pad == Size(1, 0) @@ -278,7 +278,7 @@ TEST_P(AvePooling, Accuracy) Target targetId = get<1>(get<4>(GetParam())); #if defined(INF_ENGINE_RELEASE) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X && kernel == Size(1, 1) && (stride == Size(1, 1) || stride == Size(2, 2))) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); @@ -324,29 +324,34 @@ TEST_P(MaxPooling, Accuracy) Target targetId = get<1>(get<5>(GetParam())); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD && inSize == Size(7, 6) && kernel == Size(3, 2) && (stride == Size(1, 1) || stride == Size(2, 2)) && (pad == Size(0, 1) || pad == Size(1, 1)) ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD && (kernel == Size(2, 2) || kernel == Size(3, 2)) && stride == Size(1, 1) && (pad == Size(0, 0) || pad == Size(0, 1)) ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019010000) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X && (stride == Size(1, 1) || stride == Size(2, 2)) && (pad == Size(0, 1) || pad == Size(1, 1)) ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_2019R1, CV_TEST_TAG_DNN_SKIP_IE_2019R1_1); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_VERSION); +#endif + +#if defined(INF_ENGINE_RELEASE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && stride != Size(1, 1) && pad != Size(0, 0)) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); #endif LayerParams lp; @@ -386,7 +391,7 @@ TEST_P(FullyConnected, Accuracy) bool hasBias = get<3>(GetParam()); Backend backendId = get<0>(get<4>(GetParam())); Target targetId = get<1>(get<4>(GetParam())); - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && (targetId == DNN_TARGET_OPENCL_FP16 || + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (targetId == DNN_TARGET_OPENCL_FP16 || (targetId == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X))) { applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); @@ -447,8 +452,10 @@ INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, SoftMax, Combine( ////////////////////////////////////////////////////////////////////////////// TEST_P(Test_Halide_layers, MaxPoolUnpool) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); LayerParams pool; pool.set("pool", "max"); @@ -555,8 +562,8 @@ TEST_P(ReLU, Accuracy) Target targetId = get<1>(get<1>(GetParam())); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019020000) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD && negativeSlope < 0) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_2019R3, CV_TEST_TAG_DNN_SKIP_IE_2019R2, CV_TEST_TAG_DNN_SKIP_IE); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD && negativeSlope < 0) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif LayerParams lp; @@ -666,17 +673,17 @@ TEST_P(Concat, Accuracy) Target targetId = get<1>(get<2>(GetParam())); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD && inSize == Vec3i(1, 4, 5) && numChannels == Vec3i(1, 6, 2) ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2018R5); // crash + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); // crash #endif #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019010000) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_CPU + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_CPU && inSize == Vec3i(1, 4, 5) && numChannels == Vec3i(1, 6, 2) ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R1, CV_TEST_TAG_DNN_SKIP_IE_2019R1_1); // TODO: IE_CPU + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); // TODO: IE_CPU #endif Net net; @@ -748,20 +755,25 @@ TEST_P(Eltwise, Accuracy) Target targetId = get<1>(get<4>(GetParam())); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD && + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD && inSize == Vec3i(1, 4, 5)) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019010000) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && numConv > 1) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R1, CV_TEST_TAG_DNN_SKIP_IE_2019R1_1); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && numConv > 1) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif #if defined(INF_ENGINE_RELEASE) - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_OPENCL && + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_OPENCL && op == "sum" && numConv == 1 && !weighted) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); +#endif + +#if defined(INF_ENGINE_RELEASE) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && numConv > 1) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif Net net; diff --git a/modules/dnn/test/test_ie_models.cpp b/modules/dnn/test/test_ie_models.cpp index d630158665..592d87c9fa 100644 --- a/modules/dnn/test/test_ie_models.cpp +++ b/modules/dnn/test/test_ie_models.cpp @@ -268,14 +268,16 @@ std::vector getOutputsNames(const Net& net) return names; } -void runCV(Target target, const std::string& xmlPath, const std::string& binPath, +void runCV(Backend backendId, Target targetId, const std::string& xmlPath, const std::string& binPath, const std::map& inputsMap, std::map& outputsMap) { Net net = readNet(xmlPath, binPath); for (auto& it : inputsMap) net.setInput(it.second, it.first); - net.setPreferableTarget(target); + + net.setPreferableBackend(backendId); + net.setPreferableTarget(targetId); std::vector outNames = getOutputsNames(net); std::vector outs; @@ -289,14 +291,26 @@ void runCV(Target target, const std::string& xmlPath, const std::string& binPath } } -typedef TestWithParam > DNNTestOpenVINO; +typedef TestWithParam, std::string> > DNNTestOpenVINO; TEST_P(DNNTestOpenVINO, models) { initDLDTDataPath(); - Target target = (dnn::Target)(int)get<0>(GetParam()); + const Backend backendId = get<0>(get<0>(GetParam())); + const Target targetId = get<1>(get<0>(GetParam())); + + if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + throw SkipTestException("No support for async forward"); + + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; + std::string modelName = get<1>(GetParam()); - bool isFP16 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD); + bool isFP16 = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD); const std::map& models = getOpenVINOTestModels(); const auto it = models.find(modelName); @@ -310,10 +324,10 @@ TEST_P(DNNTestOpenVINO, models) std::map inputsMap; std::map ieOutputsMap, cvOutputsMap; // Single Myriad device cannot be shared across multiple processes. - if (target == DNN_TARGET_MYRIAD) + if (targetId == DNN_TARGET_MYRIAD) resetMyriadDevice(); - runIE(target, xmlPath, binPath, inputsMap, ieOutputsMap); - runCV(target, xmlPath, binPath, inputsMap, cvOutputsMap); + runIE(targetId, xmlPath, binPath, inputsMap, ieOutputsMap); + runCV(backendId, targetId, xmlPath, binPath, inputsMap, cvOutputsMap); EXPECT_EQ(ieOutputsMap.size(), cvOutputsMap.size()); for (auto& srcIt : ieOutputsMap) @@ -328,7 +342,7 @@ TEST_P(DNNTestOpenVINO, models) INSTANTIATE_TEST_CASE_P(/**/, DNNTestOpenVINO, - Combine(testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE)), + Combine(dnnBackendsAndTargetsIE(), testing::ValuesIn(getOpenVINOTestModelsList()) ) ); diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index 35674814b1..7c5c491fad 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -146,8 +146,11 @@ TEST_P(Test_Caffe_layers, DeConvolution) TEST_P(Test_Caffe_layers, InnerProduct) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); + if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); testLayerUsingCaffeModels("layer_inner_product", true); @@ -235,12 +238,20 @@ TEST_P(Test_Caffe_layers, Concat) { #if defined(INF_ENGINE_RELEASE) #if INF_ENGINE_VER_MAJOR_GE(2019010000) && INF_ENGINE_VER_MAJOR_LT(2019020000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2019R1, CV_TEST_TAG_DNN_SKIP_IE_2019R1_1); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #elif INF_ENGINE_VER_MAJOR_EQ(2019020000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_2019R2); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && + (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) + applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, + CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && + (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) + applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, + CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION); + #endif testLayerUsingCaffeModels("layer_concat"); testLayerUsingCaffeModels("layer_concat_optim", true, false); @@ -249,8 +260,9 @@ TEST_P(Test_Caffe_layers, Concat) TEST_P(Test_Caffe_layers, Fused_Concat) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) - applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) + applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, + CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); checkBackend(); @@ -294,14 +306,15 @@ TEST_P(Test_Caffe_layers, Fused_Concat) TEST_P(Test_Caffe_layers, Eltwise) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); testLayerUsingCaffeModels("layer_eltwise"); } TEST_P(Test_Caffe_layers, PReLU) { - testLayerUsingCaffeModels("layer_prelu", true); + double lInf = (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16) ? 0.021 : 0.0; + testLayerUsingCaffeModels("layer_prelu", true, true, 0.0, lInf); } // TODO: fix an unstable test case @@ -317,8 +330,10 @@ TEST_P(Test_Caffe_layers, layer_prelu_fc) TEST_P(Test_Caffe_layers, Reshape_Split_Slice) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); Net net = readNetFromCaffe(_tf("reshape_and_slice_routines.prototxt")); ASSERT_FALSE(net.empty()); @@ -339,8 +354,8 @@ TEST_P(Test_Caffe_layers, Reshape_Split_Slice) TEST_P(Test_Caffe_layers, Conv_Elu) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE <= 2018050000 - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif Net net = readNetFromTensorflow(_tf("layer_elu_model.pb")); @@ -553,29 +568,38 @@ TEST_F(Layer_RNN_Test, get_set_test) EXPECT_EQ(shape(outputs[1]), shape(nT, nS, nH)); } -TEST(Layer_Test_ROIPooling, Accuracy) +TEST_P(Test_Caffe_layers, ROIPooling_Accuracy) { Net net = readNetFromCaffe(_tf("net_roi_pooling.prototxt")); + ASSERT_FALSE(net.empty()); Mat inp = blobFromNPY(_tf("net_roi_pooling.input.npy")); Mat rois = blobFromNPY(_tf("net_roi_pooling.rois.npy")); Mat ref = blobFromNPY(_tf("net_roi_pooling.npy")); + checkBackend(&inp, &ref); + + net.setPreferableBackend(backend); + net.setPreferableTarget(target); + net.setInput(inp, "input"); net.setInput(rois, "rois"); - net.setPreferableBackend(DNN_BACKEND_OPENCV); Mat out = net.forward(); - normAssert(out, ref); + double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-5; + double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-4; + normAssert(out, ref, "", l1, lInf); } TEST_P(Test_Caffe_layers, FasterRCNN_Proposal) { if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); Net net = readNetFromCaffe(_tf("net_faster_rcnn_proposal.prototxt")); @@ -807,16 +831,21 @@ TEST_P(Test_Caffe_layers, PriorBox_repeated) randu(shape, -1.0f, 1.0f); net.setInput(inp, "data"); net.setInput(shape, "shape"); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); Mat out = net.forward(); Mat ref = blobFromNPY(_tf("priorbox_output.npy")); - normAssert(out, ref, ""); + + double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-5; + double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-4; + normAssert(out, ref, "", l1, lInf); } // Test PriorBoxLayer in case of no aspect ratios (just squared proposals). TEST_P(Test_Caffe_layers, PriorBox_squares) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); LayerParams lp; lp.name = "testPriorBox"; lp.type = "PriorBox"; @@ -970,10 +999,21 @@ INSTANTIATE_TEST_CASE_P(/**/, Layer_Test_DWconv_Prelu, Combine(Values(3, 6), Val // Using Intel's Model Optimizer generate .xml and .bin files: // ./ModelOptimizer -w /path/to/caffemodel -d /path/to/prototxt \ // -p FP32 -i -b ${batch_size} -o /path/to/output/folder -typedef testing::TestWithParam Layer_Test_Convolution_DLDT; +typedef testing::TestWithParam > Layer_Test_Convolution_DLDT; TEST_P(Layer_Test_Convolution_DLDT, Accuracy) { - Target targetId = GetParam(); + const Backend backendId = get<0>(GetParam()); + const Target targetId = get<1>(GetParam()); + + if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + throw SkipTestException("No support for async forward"); + + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; std::string suffix = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? "_fp16" : ""; Net netDefault = readNet(_tf("layer_convolution.caffemodel"), _tf("layer_convolution.prototxt")); @@ -986,6 +1026,7 @@ TEST_P(Layer_Test_Convolution_DLDT, Accuracy) Mat outDefault = netDefault.forward(); net.setInput(inp); + net.setPreferableBackend(backendId); net.setPreferableTarget(targetId); Mat out = net.forward(); @@ -1001,10 +1042,22 @@ TEST_P(Layer_Test_Convolution_DLDT, Accuracy) TEST_P(Layer_Test_Convolution_DLDT, setInput_uint8) { - Target targetId = GetParam(); - Mat inp = blobFromNPY(_tf("blob.npy")); + const Backend backendId = get<0>(GetParam()); + const Target targetId = get<1>(GetParam()); + + if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + throw SkipTestException("No support for async forward"); + + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; + + int blobSize[] = {2, 6, 75, 113}; + Mat inputs[] = {Mat(4, &blobSize[0], CV_8U), Mat()}; - Mat inputs[] = {Mat(inp.dims, inp.size, CV_8U), Mat()}; randu(inputs[0], 0, 255); inputs[0].convertTo(inputs[1], CV_32F); @@ -1014,6 +1067,7 @@ TEST_P(Layer_Test_Convolution_DLDT, setInput_uint8) for (int i = 0; i < 2; ++i) { Net net = readNet(_tf("layer_convolution" + suffix + ".xml"), _tf("layer_convolution" + suffix + ".bin")); + net.setPreferableBackend(backendId); net.setPreferableTarget(targetId); net.setInput(inputs[i]); outs[i] = net.forward(); @@ -1025,7 +1079,19 @@ TEST_P(Layer_Test_Convolution_DLDT, setInput_uint8) TEST_P(Layer_Test_Convolution_DLDT, multithreading) { - Target targetId = GetParam(); + const Backend backendId = get<0>(GetParam()); + const Target targetId = get<1>(GetParam()); + + if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + throw SkipTestException("No support for async forward"); + + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; + std::string suffix = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? "_fp16" : ""; std::string xmlPath = _tf("layer_convolution" + suffix + ".xml"); std::string binPath = _tf("layer_convolution" + suffix + ".bin"); @@ -1035,7 +1101,9 @@ TEST_P(Layer_Test_Convolution_DLDT, multithreading) firstNet.setInput(inp); secondNet.setInput(inp); + firstNet.setPreferableBackend(backendId); firstNet.setPreferableTarget(targetId); + secondNet.setPreferableBackend(backendId); secondNet.setPreferableTarget(targetId); Mat out1, out2; @@ -1053,7 +1121,8 @@ TEST_P(Layer_Test_Convolution_DLDT, multithreading) } INSTANTIATE_TEST_CASE_P(/**/, Layer_Test_Convolution_DLDT, - testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE))); + dnnBackendsAndTargetsIE() +); // 1. Create a .prototxt file with the following network: // layer { @@ -1112,17 +1181,18 @@ std::vector< std::vector > list_sizes{ {1, 2, 3}, {3, 2, 1}, {5, 5, 5}, {13 INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_DLDT_two_inputs_3dim, Combine( Values(CV_8U, CV_32F), Values(CV_8U, CV_32F), - testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE)), + testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)), testing::ValuesIn(list_sizes) )); -typedef testing::TestWithParam > Test_DLDT_two_inputs; +typedef testing::TestWithParam > > Test_DLDT_two_inputs; TEST_P(Test_DLDT_two_inputs, as_backend) { static const float kScale = 0.5f; static const float kScaleInv = 1.0f / kScale; - Target targetId = get<2>(GetParam()); + Backend backendId = get<0>(get<2>(GetParam())); + Target targetId = get<1>(get<2>(GetParam())); Net net; LayerParams lp; @@ -1141,7 +1211,7 @@ TEST_P(Test_DLDT_two_inputs, as_backend) net.setInputsNames({"data", "second_input"}); net.setInput(firstInp, "data", kScale); net.setInput(secondInp, "second_input", kScaleInv); - net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE); + net.setPreferableBackend(backendId); net.setPreferableTarget(targetId); Mat out = net.forward(); @@ -1155,7 +1225,7 @@ TEST_P(Test_DLDT_two_inputs, as_backend) INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_DLDT_two_inputs, Combine( Values(CV_8U, CV_32F), Values(CV_8U, CV_32F), - testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE)) + dnnBackendsAndTargets() )); class UnsupportedLayer : public Layer @@ -1176,10 +1246,11 @@ public: virtual void forward(cv::InputArrayOfArrays inputs, cv::OutputArrayOfArrays outputs, cv::OutputArrayOfArrays internals) CV_OVERRIDE {} }; -TEST(Test_DLDT, fused_output) +typedef DNNTestLayer Test_DLDT_layers; + +static void test_dldt_fused_output(Backend backend, Target target) { static const int kNumChannels = 3; - CV_DNN_REGISTER_LAYER_CLASS(Unsupported, UnsupportedLayer); Net net; { LayerParams lp; @@ -1203,13 +1274,31 @@ TEST(Test_DLDT, fused_output) LayerParams lp; net.addLayerToPrev("unsupported_layer", "Unsupported", lp); } - net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); net.setInput(Mat({1, 1, 1, 1}, CV_32FC1, Scalar(1))); - ASSERT_NO_THROW(net.forward()); + net.forward(); +} + +TEST_P(Test_DLDT_layers, fused_output) +{ + CV_DNN_REGISTER_LAYER_CLASS(Unsupported, UnsupportedLayer); + try + { + test_dldt_fused_output(backend, target); + } + catch (const std::exception& e) + { + ADD_FAILURE() << "Exception: " << e.what(); + } + catch(...) + { + ADD_FAILURE() << "Unknown exception"; + } LayerFactory::unregisterLayer("Unsupported"); } -TEST(Test_DLDT, multiple_networks) +TEST_P(Test_DLDT_layers, multiple_networks) { Net nets[2]; for (int i = 0; i < 2; ++i) @@ -1224,7 +1313,8 @@ TEST(Test_DLDT, multiple_networks) lp.name = format("testConv_%d", i); lp.blobs.push_back(Mat({1, 1, 1, 1}, CV_32F, Scalar(1 + i))); nets[i].addLayerToPrev(lp.name, lp.type, lp); - nets[i].setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE); + nets[i].setPreferableBackend(backend); + nets[i].setPreferableTarget(target); nets[i].setInput(Mat({1, 1, 1, 1}, CV_32FC1, Scalar(1))); } Mat out_1 = nets[0].forward(); @@ -1233,6 +1323,9 @@ TEST(Test_DLDT, multiple_networks) out_1 = nets[0].forward(); normAssert(2 * out_1, out_2); } + +INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_DLDT_layers, dnnBackendsAndTargets()); + #endif // HAVE_INF_ENGINE // Test a custom layer. @@ -1348,7 +1441,7 @@ TEST_P(Test_Caffe_layers, Interp) TEST_P(Test_Caffe_layers, DISABLED_Interp) // requires patched protobuf (available in OpenCV source tree only) #endif { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); // Test a custom layer. diff --git a/modules/dnn/test/test_misc.cpp b/modules/dnn/test/test_misc.cpp index 3e72cfe58e..464ef104b3 100644 --- a/modules/dnn/test/test_misc.cpp +++ b/modules/dnn/test/test_misc.cpp @@ -367,21 +367,34 @@ static const std::chrono::milliseconds async_timeout(10000); // This test runs network in synchronous mode for different inputs and then // runs the same model asynchronously for the same inputs. -typedef testing::TestWithParam > Async; -TEST_P(Async, set_and_forward_single) +typedef testing::TestWithParam > > Async; +TEST_P(Async, model_optimizer_pipeline_set_and_forward_single) { const int dtype = get<0>(GetParam()); - const int target = get<1>(GetParam()); + const Backend backendId = get<0>(get<1>(GetParam())); + const Target targetId = get<1>(get<1>(GetParam())); - const std::string suffix = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "_fp16" : ""; + if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + throw SkipTestException("No support for async forward"); + + const std::string suffix = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? "_fp16" : ""; const std::string& model = findDataFile("dnn/layers/layer_convolution" + suffix + ".bin"); const std::string& proto = findDataFile("dnn/layers/layer_convolution" + suffix + ".xml"); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; + Net netSync = readNet(model, proto); - netSync.setPreferableTarget(target); + netSync.setPreferableBackend(backendId); + netSync.setPreferableTarget(targetId); Net netAsync = readNet(model, proto); - netAsync.setPreferableTarget(target); + netAsync.setPreferableBackend(backendId); + netAsync.setPreferableTarget(targetId); // Generate inputs. const int numInputs = 10; @@ -414,21 +427,33 @@ TEST_P(Async, set_and_forward_single) } } -TEST_P(Async, set_and_forward_all) +TEST_P(Async, model_optimizer_pipeline_set_and_forward_all) { const int dtype = get<0>(GetParam()); - const int target = get<1>(GetParam()); + const Backend backendId = get<0>(get<1>(GetParam())); + const Target targetId = get<1>(get<1>(GetParam())); - const std::string suffix = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "_fp16" : ""; + if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + throw SkipTestException("No support for async forward"); + + const std::string suffix = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? "_fp16" : ""; const std::string& model = findDataFile("dnn/layers/layer_convolution" + suffix + ".bin"); const std::string& proto = findDataFile("dnn/layers/layer_convolution" + suffix + ".xml"); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; Net netSync = readNet(model, proto); - netSync.setPreferableTarget(target); + netSync.setPreferableBackend(backendId); + netSync.setPreferableTarget(targetId); Net netAsync = readNet(model, proto); - netAsync.setPreferableTarget(target); + netAsync.setPreferableBackend(backendId); + netAsync.setPreferableTarget(targetId); // Generate inputs. const int numInputs = 10; @@ -465,25 +490,136 @@ TEST_P(Async, set_and_forward_all) } } +TEST_P(Async, create_layer_pipeline_set_and_forward_all) +{ + const int dtype = get<0>(GetParam()); + const Backend backendId = get<0>(get<1>(GetParam())); + const Target targetId = get<1>(get<1>(GetParam())); + + if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + throw SkipTestException("No support for async forward"); + + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; + + Net netSync; + Net netAsync; + { + int inChannels = 4; + int outChannels = 12; + int group = 3; + Size inSize(113, 75); + Size kernel(4, 5); + Size stride(2, 3); + Size pad(0, 1); + Size dilation(1, 1); + bool hasBias = true; + + int sz[] = {outChannels, inChannels / group, kernel.height, kernel.width}; + Mat weights(4, &sz[0], CV_32F); + randu(weights, -1.0f, 1.0f); + + LayerParams lp; + lp.set("kernel_w", kernel.width); + lp.set("kernel_h", kernel.height); + lp.set("pad_w", pad.width); + lp.set("pad_h", pad.height); + lp.set("stride_w", stride.width); + lp.set("stride_h", stride.height); + lp.set("dilation_w", dilation.width); + lp.set("dilation_h", dilation.height); + lp.set("num_output", outChannels); + lp.set("group", group); + lp.set("bias_term", hasBias); + lp.type = "Convolution"; + lp.name = "testLayer"; + lp.blobs.push_back(weights); + if (hasBias) + { + Mat bias(1, outChannels, CV_32F); + randu(bias, -1.0f, 1.0f); + lp.blobs.push_back(bias); + } + int inpSz[] = {1, inChannels, inSize.height, inSize.width}; + Mat input(4, &inpSz[0], CV_32F); + + netSync.addLayerToPrev(lp.name, lp.type, lp); + + netAsync.addLayerToPrev(lp.name, lp.type, lp); + } + + netSync.setPreferableBackend(backendId); + netSync.setPreferableTarget(targetId); + + netAsync.setPreferableBackend(backendId); + netAsync.setPreferableTarget(targetId); + + // Generate inputs. + const int numInputs = 10; + std::vector inputs(numInputs); + int blobSize[] = {1, 4, 75, 113}; + for (int i = 0; i < numInputs; ++i) + { + inputs[i].create(4, &blobSize[0], dtype); + randu(inputs[i], 0, 255); + } + + // Run synchronously. + std::vector refs(numInputs); + for (int i = 0; i < numInputs; ++i) + { + netSync.setInput(inputs[i]); + refs[i] = netSync.forward().clone(); + } + + // Run asynchronously. To make test more robust, process inputs in the reversed order. + std::vector outs(numInputs); + for (int i = numInputs - 1; i >= 0; --i) + { + netAsync.setInput(inputs[i]); + outs[i] = netAsync.forwardAsync(); + } + + for (int i = numInputs - 1; i >= 0; --i) + { + ASSERT_TRUE(outs[i].valid()); + Mat result; + EXPECT_TRUE(outs[i].get(result, async_timeout)); + normAssert(refs[i], result, format("Index: %d", i).c_str(), 0, 0); + } +} + INSTANTIATE_TEST_CASE_P(/**/, Async, Combine( - Values(CV_32F, CV_8U), - testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE)) + Values(CV_32F, CV_8U), + dnnBackendsAndTargetsIE() )); -typedef testing::TestWithParam Test_Model_Optimizer; +typedef testing::TestWithParam > Test_Model_Optimizer; TEST_P(Test_Model_Optimizer, forward_two_nets) { - const int target = GetParam(); + const Backend backendId = get<0>(GetParam()); + const Target targetId = get<1>(GetParam()); - const std::string suffix = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "_fp16" : ""; + const std::string suffix = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? "_fp16" : ""; const std::string& model = findDataFile("dnn/layers/layer_convolution" + suffix + ".bin"); const std::string& proto = findDataFile("dnn/layers/layer_convolution" + suffix + ".xml"); + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; + Net net0 = readNet(model, proto); - net0.setPreferableTarget(target); + net0.setPreferableTarget(targetId); Net net1 = readNet(model, proto); - net1.setPreferableTarget(target); + net1.setPreferableTarget(targetId); // Generate inputs. int blobSize[] = {2, 6, 75, 113}; @@ -502,7 +638,7 @@ TEST_P(Test_Model_Optimizer, forward_two_nets) normAssert(ref0, ref2, 0, 0); } INSTANTIATE_TEST_CASE_P(/**/, Test_Model_Optimizer, - testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE)) + dnnBackendsAndTargetsIE() ); #endif // HAVE_INF_ENGINE diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index b96f408f26..2122813195 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -98,7 +98,7 @@ TEST_P(Test_ONNX_layers, Convolution) TEST_P(Test_ONNX_layers, Convolution3D) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000) - throw SkipTestException("Test is enabled starts from 2019R1"); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif if (target != DNN_TARGET_CPU) throw SkipTestException("Only CPU is supported"); @@ -109,10 +109,10 @@ TEST_P(Test_ONNX_layers, Convolution3D) TEST_P(Test_ONNX_layers, Two_convolution) { #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif // Reference output values are in range [-0.855, 0.611] testONNXModels("two_convolution"); @@ -129,10 +129,10 @@ TEST_P(Test_ONNX_layers, Deconvolution) TEST_P(Test_ONNX_layers, Deconvolution3D) { -#if defined(INF_ENGINE_RELEASE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_2018R5); +#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif - if (backend != DNN_BACKEND_INFERENCE_ENGINE || target != DNN_TARGET_CPU) + if (backend == DNN_BACKEND_OPENCV || target != DNN_TARGET_CPU) throw SkipTestException("Only DLIE backend on CPU is supported"); testONNXModels("deconv3d"); testONNXModels("deconv3d_bias"); @@ -169,6 +169,10 @@ TEST_P(Test_ONNX_layers, ReduceMean) TEST_P(Test_ONNX_layers, ReduceMean3D) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported if (target != DNN_TARGET_CPU) throw SkipTestException("Only CPU is supported"); testONNXModels("reduce_mean3d"); @@ -181,11 +185,11 @@ TEST_P(Test_ONNX_layers, MaxPooling_Sigmoid) TEST_P(Test_ONNX_layers, Concatenation) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL); - if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); } testONNXModels("concatenation"); } @@ -193,10 +197,12 @@ TEST_P(Test_ONNX_layers, Concatenation) TEST_P(Test_ONNX_layers, Eltwise3D) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000) - throw SkipTestException("Test is enabled starts from 2019R1"); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU) - throw SkipTestException("Only CPU on DLIE backend is supported"); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported testONNXModels("eltwise3d"); } @@ -208,8 +214,12 @@ TEST_P(Test_ONNX_layers, AveragePooling) TEST_P(Test_ONNX_layers, MaxPooling3D) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000) - throw SkipTestException("Test is enabled starts from 2019R1"); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported if (target != DNN_TARGET_CPU) throw SkipTestException("Only CPU is supported"); testONNXModels("max_pool3d", npy, 0, 0, false, false); @@ -218,8 +228,12 @@ TEST_P(Test_ONNX_layers, MaxPooling3D) TEST_P(Test_ONNX_layers, AvePooling3D) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000) - throw SkipTestException("Test is enabled starts from 2019R1"); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported if (target != DNN_TARGET_CPU) throw SkipTestException("Only CPU is supported"); testONNXModels("ave_pool3d"); @@ -228,8 +242,12 @@ TEST_P(Test_ONNX_layers, AvePooling3D) TEST_P(Test_ONNX_layers, PoolConv3D) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000) - throw SkipTestException("Test is enabled starts from 2019R1"); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported if (target != DNN_TARGET_CPU) throw SkipTestException("Only CPU is supported"); testONNXModels("pool_conv_3d"); @@ -242,22 +260,22 @@ TEST_P(Test_ONNX_layers, BatchNormalization) TEST_P(Test_ONNX_layers, BatchNormalization3D) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL); - if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); } testONNXModels("batch_norm_3d"); } TEST_P(Test_ONNX_layers, Transpose) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL); - if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); } testONNXModels("transpose"); } @@ -266,17 +284,17 @@ TEST_P(Test_ONNX_layers, Multiplication) { if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); testONNXModels("mul"); } TEST_P(Test_ONNX_layers, Constant) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif testONNXModels("constant"); } @@ -342,10 +360,10 @@ TEST_P(Test_ONNX_layers, Div) TEST_P(Test_ONNX_layers, DynamicReshape) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL); + if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); } testONNXModels("dynamic_reshape"); } @@ -382,8 +400,10 @@ TEST_P(Test_ONNX_layers, Softmax) TEST_P(Test_ONNX_layers, Split_EltwiseMax) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); testONNXModels("split_max"); } @@ -425,8 +445,8 @@ TEST_P(Test_ONNX_nets, Squeezenet) TEST_P(Test_ONNX_nets, Googlenet) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); const String model = _tf("models/googlenet.onnx", false); @@ -455,9 +475,9 @@ TEST_P(Test_ONNX_nets, CaffeNet) { applyTestTag(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019030000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_2019R3); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif testONNXModels("caffenet", pb); } @@ -466,9 +486,9 @@ TEST_P(Test_ONNX_nets, RCNN_ILSVRC13) { applyTestTag(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2019030000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_2019R3); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif // Reference output values are in range [-4.992, -1.161] testONNXModels("rcnn_ilsvrc13", pb, 0.0045); @@ -510,12 +530,12 @@ TEST_P(Test_ONNX_nets, ResNet101_DUC_HDC) applyTestTag(CV_TEST_TAG_VERYLONG); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019010000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE, CV_TEST_TAG_DNN_SKIP_IE_2019R1, CV_TEST_TAG_DNN_SKIP_IE_2019R1_1); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_OPENCL) { @@ -533,15 +553,15 @@ TEST_P(Test_ONNX_nets, TinyYolov2) if (cvtest::skipUnstableTests) throw SkipTestException("Skip unstable test"); #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16) ) - applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); + applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif // output range: [-11; 8] @@ -568,11 +588,11 @@ TEST_P(Test_ONNX_nets, LResNet100E_IR) (target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB), CV_TEST_TAG_DEBUG_LONG ); - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL); - if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); } double l1 = default_l1; @@ -582,7 +602,7 @@ TEST_P(Test_ONNX_nets, LResNet100E_IR) l1 = 0.009; lInf = 0.035; } - else if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_CPU) { + else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_CPU) { l1 = 4.6e-5; lInf = 1.9e-4; } @@ -592,10 +612,10 @@ TEST_P(Test_ONNX_nets, LResNet100E_IR) TEST_P(Test_ONNX_nets, Emotion_ferplus) { #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif double l1 = default_l1; @@ -604,12 +624,12 @@ TEST_P(Test_ONNX_nets, Emotion_ferplus) // Output values are in range [-2.011, 2.111] if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) l1 = 0.007; - else if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16) + else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL_FP16) { l1 = 0.021; lInf = 0.034; } - else if (backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_CPU || target == DNN_TARGET_OPENCL)) { + else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_CPU || target == DNN_TARGET_OPENCL)) { l1 = 2.4e-4; lInf = 6e-4; } @@ -632,7 +652,7 @@ TEST_P(Test_ONNX_nets, DenseNet121) TEST_P(Test_ONNX_nets, Inception_v1) { #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); #endif testONNXModels("inception_v1", pb); @@ -640,11 +660,11 @@ TEST_P(Test_ONNX_nets, Inception_v1) TEST_P(Test_ONNX_nets, Shufflenet) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL); - if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); } testONNXModels("shufflenet", pb); } @@ -652,8 +672,12 @@ TEST_P(Test_ONNX_nets, Shufflenet) TEST_P(Test_ONNX_nets, Resnet34_kinetics) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000) - throw SkipTestException("Test is enabled starts from 2019R1"); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported if (target != DNN_TARGET_CPU) throw SkipTestException("Only CPU is supported"); @@ -675,6 +699,9 @@ TEST_P(Test_ONNX_nets, Resnet34_kinetics) lp.set("order", DictValue::arrayInt(&order[0], 4)); permute.addLayerToPrev("perm", "Permute", lp); + permute.setPreferableBackend(backend); + permute.setPreferableTarget(target); + permute.setInput(blob0); Mat input0 = permute.forward().clone(); diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index ea8cd15659..53578134e3 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -134,8 +134,12 @@ TEST_P(Test_TensorFlow_layers, conv) TEST_P(Test_TensorFlow_layers, Convolution3D) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000) - throw SkipTestException("Test is enabled starts from 2019R1"); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported if (target != DNN_TARGET_CPU) throw SkipTestException("Only CPU is supported"); runTensorFlowNet("conv3d"); @@ -147,12 +151,12 @@ TEST_P(Test_TensorFlow_layers, padding) runTensorFlowNet("spatial_padding"); runTensorFlowNet("mirror_pad"); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019020000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) { if (target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_2019R3, CV_TEST_TAG_DNN_SKIP_IE_2019R2); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); if (target == DNN_TARGET_OPENCL_FP16) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_2019R3, CV_TEST_TAG_DNN_SKIP_IE_2019R2); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); } #endif runTensorFlowNet("keras_pad_concat"); @@ -199,11 +203,11 @@ TEST_P(Test_TensorFlow_layers, batch_norm) TEST_P(Test_TensorFlow_layers, batch_norm3D) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL); - if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); throw SkipTestException(""); } runTensorFlowNet("batch_norm3d"); @@ -211,8 +215,10 @@ TEST_P(Test_TensorFlow_layers, batch_norm3D) TEST_P(Test_TensorFlow_layers, slim_batch_norm) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Output values range: [-40.0597, 207.827] double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.041 : default_l1; double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.33 : default_lInf; @@ -229,8 +235,10 @@ TEST_P(Test_TensorFlow_layers, pooling) TEST_P(Test_TensorFlow_layers, max_pool_grad) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); runTensorFlowNet("max_pool_grad"); } @@ -239,10 +247,10 @@ TEST_P(Test_TensorFlow_layers, ave_pool_same) { // Reference output values are in range [-0.519531, 0.112976] #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019010000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif runTensorFlowNet("ave_pool_same"); } @@ -250,8 +258,12 @@ TEST_P(Test_TensorFlow_layers, ave_pool_same) TEST_P(Test_TensorFlow_layers, MaxPooling3D) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000) - throw SkipTestException("Test is enabled starts from 2019R1"); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported if (target != DNN_TARGET_CPU) throw SkipTestException("Only CPU is supported"); runTensorFlowNet("max_pool3d"); @@ -260,8 +272,12 @@ TEST_P(Test_TensorFlow_layers, MaxPooling3D) TEST_P(Test_TensorFlow_layers, AvePooling3D) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000) - throw SkipTestException("Test is enabled starts from 2019R1"); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported if (target != DNN_TARGET_CPU) throw SkipTestException("Only CPU is supported"); runTensorFlowNet("ave_pool3d"); @@ -293,8 +309,10 @@ TEST_P(Test_TensorFlow_layers, matmul) TEST_P(Test_TensorFlow_layers, reshape) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); runTensorFlowNet("shift_reshape_no_reorder"); runTensorFlowNet("reshape_no_reorder"); runTensorFlowNet("reshape_reduce"); @@ -304,10 +322,10 @@ TEST_P(Test_TensorFlow_layers, reshape) TEST_P(Test_TensorFlow_layers, flatten) { #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2 ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif runTensorFlowNet("flatten", true); @@ -322,8 +340,8 @@ TEST_P(Test_TensorFlow_layers, unfused_flatten) TEST_P(Test_TensorFlow_layers, leaky_relu) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif runTensorFlowNet("leaky_relu_order1"); runTensorFlowNet("leaky_relu_order2"); @@ -333,10 +351,10 @@ TEST_P(Test_TensorFlow_layers, leaky_relu) TEST_P(Test_TensorFlow_layers, l2_normalize) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2019010000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif runTensorFlowNet("l2_normalize"); @@ -346,14 +364,15 @@ TEST_P(Test_TensorFlow_layers, l2_normalize) TEST_P(Test_TensorFlow_layers, l2_normalize_3d) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16) ) - applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); + applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, + CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif runTensorFlowNet("l2_normalize_3d"); @@ -364,11 +383,11 @@ class Test_TensorFlow_nets : public DNNTestLayer {}; TEST_P(Test_TensorFlow_nets, MobileNet_SSD) { #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) { #if INF_ENGINE_VER_MAJOR_GE(2019020000) if (getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif } #endif @@ -403,9 +422,9 @@ TEST_P(Test_TensorFlow_nets, Inception_v2_SSD) { applyTestTag(target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2019010000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD && + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif checkBackend(); @@ -457,7 +476,7 @@ TEST_P(Test_TensorFlow_nets, MobileNet_v1_SSD) float detectionConfThresh = (target == DNN_TARGET_MYRIAD) ? 0.35 : 0.3; #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD && + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) { scoreDiff = 0.061; @@ -480,16 +499,22 @@ TEST_P(Test_TensorFlow_nets, Faster_RCNN) static std::string names[] = {"faster_rcnn_inception_v2_coco_2018_01_28", "faster_rcnn_resnet50_coco_2018_01_28"}; - checkBackend(); #ifdef INF_ENGINE_RELEASE - if (backend == DNN_BACKEND_INFERENCE_ENGINE && + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (INF_ENGINE_VER_MAJOR_LT(2019020000) || target != DNN_TARGET_CPU)) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + // segfault: inference-engine/thirdparty/clDNN/src/gpu/detection_output_cpu.cpp:111: + // Assertion `prior_height > 0' failed. + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); + if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); - double scoresDiff = backend == DNN_BACKEND_INFERENCE_ENGINE ? 2.9e-5 : 1e-5; + checkBackend(); + + double scoresDiff = backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 ? 2.9e-5 : 1e-5; for (int i = 0; i < 2; ++i) { std::string proto = findDataFile("dnn/" + names[i] + ".pbtxt"); @@ -512,8 +537,9 @@ TEST_P(Test_TensorFlow_nets, Faster_RCNN) TEST_P(Test_TensorFlow_nets, MobileNet_v1_SSD_PPN) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) - applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) + applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, + CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif checkBackend(); std::string proto = findDataFile("dnn/ssd_mobilenet_v1_ppn_coco.pbtxt"); @@ -583,12 +609,12 @@ TEST_P(Test_TensorFlow_nets, EAST_text_detection) ); #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16 && + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL_FP16 && INF_ENGINE_VER_MAJOR_EQ(2019020000)) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_2019R2); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif checkBackend(); @@ -621,7 +647,7 @@ TEST_P(Test_TensorFlow_nets, EAST_text_detection) double l1_geometry = default_l1, lInf_geometry = default_lInf; if (target == DNN_TARGET_OPENCL_FP16) { - lInf_scores = backend == DNN_BACKEND_INFERENCE_ENGINE ? 0.16 : 0.11; + lInf_scores = backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 ? 0.16 : 0.11; l1_geometry = 0.28; lInf_geometry = 5.94; } else if (target == DNN_TARGET_MYRIAD) @@ -679,8 +705,10 @@ TEST_P(Test_TensorFlow_layers, quantized) TEST_P(Test_TensorFlow_layers, lstm) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16); runTensorFlowNet("lstm", true); @@ -689,12 +717,18 @@ TEST_P(Test_TensorFlow_layers, lstm) TEST_P(Test_TensorFlow_layers, split) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD && + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); runTensorFlowNet("split"); - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); +} + +TEST_P(Test_TensorFlow_layers, split_equals) +{ + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); runTensorFlowNet("split_equals"); } @@ -706,9 +740,10 @@ TEST_P(Test_TensorFlow_layers, resize_nearest_neighbor) TEST_P(Test_TensorFlow_layers, slice) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) - applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); + applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, + CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); runTensorFlowNet("slice_4d"); runTensorFlowNet("strided_slice"); } @@ -722,10 +757,10 @@ TEST_P(Test_TensorFlow_layers, softmax) TEST_P(Test_TensorFlow_layers, slim_softmax_v2) { #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD && + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2 ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif runTensorFlowNet("slim_softmax_v2"); } @@ -738,8 +773,10 @@ TEST_P(Test_TensorFlow_layers, relu6) TEST_P(Test_TensorFlow_layers, subpixel) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); runTensorFlowNet("subpixel"); } @@ -758,10 +795,10 @@ TEST_P(Test_TensorFlow_layers, resize_bilinear) TEST_P(Test_TensorFlow_layers, squeeze) { #if defined(INF_ENGINE_RELEASE) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2 ) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif int inpShapes[][4] = {{1, 3, 4, 2}, {1, 3, 1, 2}, {1, 3, 4, 1}, {1, 3, 4, 1}}; // TensorFlow's shape (NHWC) int outShapes[][3] = {{3, 4, 2}, {1, 3, 2}, {1, 3, 4}, {1, 3, 4}}; diff --git a/modules/dnn/test/test_torch_importer.cpp b/modules/dnn/test/test_torch_importer.cpp index 3e0ab75bee..889156a62d 100644 --- a/modules/dnn/test/test_torch_importer.cpp +++ b/modules/dnn/test/test_torch_importer.cpp @@ -100,7 +100,7 @@ public: lInf = lInf ? lInf : default_lInf; normAssert(outRef, outBlobs[0], "", l1, lInf); - if (check2ndBlob && backend != DNN_BACKEND_INFERENCE_ENGINE) + if (check2ndBlob && backend == DNN_BACKEND_OPENCV) { Mat out2 = outBlobs[1]; Mat ref2 = readTorchBlob(_tf(prefix + "_output_2" + suffix), isBinary); @@ -136,8 +136,8 @@ TEST_P(Test_Torch_layers, run_reshape_change_batch_size) TEST_P(Test_Torch_layers, run_reshape) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); runTorchNet("net_reshape_batch"); runTorchNet("net_reshape_channels", "", false, true); } @@ -209,8 +209,8 @@ TEST_P(Test_Torch_layers, net_lp_pooling) TEST_P(Test_Torch_layers, net_conv_gemm_lrn) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); runTorchNet("net_conv_gemm_lrn", "", false, true, true, target == DNN_TARGET_OPENCL_FP16 ? 0.046 : 0.0, target == DNN_TARGET_OPENCL_FP16 ? 0.023 : 0.0); @@ -235,9 +235,10 @@ TEST_P(Test_Torch_layers, net_padding) TEST_P(Test_Torch_layers, net_non_spatial) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) - applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); + applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, + CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); runTorchNet("net_non_spatial", "", false, true); } @@ -251,9 +252,10 @@ TEST_P(Test_Torch_layers, run_paralel) TEST_P(Test_Torch_layers, net_residual) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE == 2018050000 - if (backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL || + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)) - applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); + applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, + CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif runTorchNet("net_residual", "", false, true); } @@ -263,8 +265,8 @@ class Test_Torch_nets : public DNNTestLayer {}; TEST_P(Test_Torch_nets, OpenFace_accuracy) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000) - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif checkBackend(); @@ -339,11 +341,11 @@ TEST_P(Test_Torch_nets, ENet_accuracy) checkBackend(); if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) throw SkipTestException(""); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU) { - if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16); - if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL); - if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD); + if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); + if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); throw SkipTestException(""); } @@ -395,17 +397,17 @@ TEST_P(Test_Torch_nets, ENet_accuracy) TEST_P(Test_Torch_nets, FastNeuralStyle_accuracy) { #if defined INF_ENGINE_RELEASE - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X); + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); #endif checkBackend(); #if defined(INF_ENGINE_RELEASE) #if INF_ENGINE_RELEASE <= 2018050000 - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL) - applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_2018R5); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif #endif diff --git a/modules/ts/include/opencv2/ts.hpp b/modules/ts/include/opencv2/ts.hpp index e0388083fb..5364143d15 100644 --- a/modules/ts/include/opencv2/ts.hpp +++ b/modules/ts/include/opencv2/ts.hpp @@ -219,6 +219,8 @@ static inline void applyTestTag(const std::string& tag1, const std::string& tag2 { applyTestTag_(tag1); applyTestTag_(tag2); applyTestTag_(tag3); checkTestTags(); } static inline void applyTestTag(const std::string& tag1, const std::string& tag2, const std::string& tag3, const std::string& tag4) { applyTestTag_(tag1); applyTestTag_(tag2); applyTestTag_(tag3); applyTestTag_(tag4); checkTestTags(); } +static inline void applyTestTag(const std::string& tag1, const std::string& tag2, const std::string& tag3, const std::string& tag4, const std::string& tag5) +{ applyTestTag_(tag1); applyTestTag_(tag2); applyTestTag_(tag3); applyTestTag_(tag4); applyTestTag_(tag5); checkTestTags(); } /** Append global skip test tags