From: Dmitry Kurtaev Date: Fri, 23 Dec 2022 16:58:41 +0000 (+0300) Subject: Merge pull request #22957 from dkurt:new_openvino_api X-Git-Tag: accepted/tizen/unified/20230127.161057~1^2~15 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8681686d8f7ba0b29adc3dfc33ae96cefa49f604;p=platform%2Fupstream%2Fopencv.git Merge pull request #22957 from dkurt:new_openvino_api Switch to new OpenVINO API after 2022.1 release * Pass Layer_Test_Convolution_DLDT.Accuracy/0 test * Pass test Test_Caffe_layers.Softmax * Failed 136 tests * Fix Concat. Failed 120 tests * Custom nGraph ops. 19 failed tests * Set and get properties from Core * Read model from buffer * Change MaxPooling layer output names. Restore reshape * Cosmetic changes * Cosmetic changes * Override getOutputsInfo * Fixes for OpenVINO < 2022.1 * Async inference for 2021.4 and less * Compile model with config * Fix serialize for 2022.1 * Asynchronous inference with 2022.1 * Handle 1d outputs * Work with model with dynamic output shape * Fixes with 1d output for old API * Control outputs by nGraph function for all OpenVINO versions * Refer inputs in PrePostProcessor by indices * Fix cycled dependency between InfEngineNgraphNode and InfEngineNgraphNet. Add InferRequest callback only for async inference. Do not capture InferRequest object. * Fix tests thresholds * Fix HETERO:GPU,CPU plugin issues with unsupported layer --- diff --git a/modules/dnn/src/ie_ngraph.cpp b/modules/dnn/src/ie_ngraph.cpp index bb65faf4eb..9a80c5e328 100644 --- a/modules/dnn/src/ie_ngraph.cpp +++ b/modules/dnn/src/ie_ngraph.cpp @@ -35,6 +35,7 @@ static bool DNN_IE_SERIALIZE = utils::getConfigurationParameterBool("OPENCV_DNN_ static std::string kDefaultInpLayerName = "opencv_ngraph_empty_inp_layer_name"; static constexpr const char* kOpenCVLayersType = "opencv_ngraph_layer"; +#if INF_ENGINE_VER_MAJOR_LT(INF_ENGINE_RELEASE_2022_1) static std::string shapesToStr(const std::vector& mats) { std::ostringstream shapes; @@ -62,6 +63,7 @@ static void strToShapes(const std::string& str, std::vector ss >> shapes[i][j]; } } +#endif // OpenVINO < 2022.1 static std::vector > ngraphWrappers(const std::vector >& ptrs) @@ -76,6 +78,61 @@ ngraphWrappers(const std::vector >& ptrs) return wrappers; } +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + +class NgraphCustomOp: public ov::op::Op { +public: + OPENVINO_OP(kOpenCVLayersType); + + NgraphCustomOp(const ngraph::OutputVector& inputs, Ptr& cvLayer, const std::vector& outputs, const std::vector& internals): + Op(inputs), cvLayer(cvLayer), outputs(outputs), internals(internals) + { + constructor_validate_and_infer_types(); + } + + void validate_and_infer_types() override + { + set_output_size(outputs.size()); + for (int i = 0; i < outputs.size(); ++i) + { + ov::PartialShape shape; + for (int j = 0; j < outputs[i].dims; ++j) { + shape.push_back(outputs[i].size[j]); + } + set_output_type(i, get_input_element_type(0), shape); + } + } + + std::shared_ptr clone_with_new_inputs(const ngraph::OutputVector& new_args) const override + { + return std::make_shared(new_args, cvLayer, outputs, internals); + } + + bool has_evaluate() const { + return true; + } + + bool evaluate(ov::TensorVector& outputs, const ov::TensorVector& inputs) const override { + std::vector inpMats, outMats; + infEngineBlobsToMats(inputs, inpMats); + infEngineBlobsToMats(outputs, outMats); + try + { + cvLayer->forward(inpMats, outMats, internals); + return true; + } + catch (...) + { + return false; + } + } + + Ptr& cvLayer; + std::vector outputs, internals; +}; + +#else + class NgraphCustomOp: public ngraph::op::Op { public: const ngraph::NodeTypeInfo& get_type_info() const override @@ -324,7 +381,7 @@ public: #endif }; - +#endif // OpenVINO >= 2022.1 InfEngineNgraphNode::InfEngineNgraphNode(std::shared_ptr&& _node) : BackendNode(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH), node(std::move(_node)) {} @@ -337,15 +394,6 @@ InfEngineNgraphNode::InfEngineNgraphNode(const std::vector >& n std::vector& outputs, std::vector& internals) : BackendNode(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH), cvLayer(cvLayer_) { - std::ostringstream oss; - oss << (size_t)cvLayer.get(); - - std::map params = { - {"impl", oss.str()}, - {"outputs", shapesToStr(outputs)}, - {"internals", shapesToStr(internals)} - }; - #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2020_3) ngraph::OutputVector inp_nodes; #else @@ -353,7 +401,19 @@ InfEngineNgraphNode::InfEngineNgraphNode(const std::vector >& n #endif for (const auto& node : nodes) inp_nodes.emplace_back(node.dynamicCast()->node); + +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + node = std::make_shared(inp_nodes, cvLayer, outputs, internals); +#else + std::ostringstream oss; + oss << (size_t)cvLayer.get(); + std::map params = { + {"impl", oss.str()}, + {"outputs", shapesToStr(outputs)}, + {"internals", shapesToStr(internals)} + }; node = std::make_shared(inp_nodes, params); +#endif CV_Assert(!cvLayer->name.empty()); setName(cvLayer->name); @@ -383,7 +443,7 @@ void InfEngineNgraphNet::addOutput(const Ptr& node) CV_Assert(node); CV_Assert(node->node); const std::string& name = node->node->get_friendly_name(); - requestedOutputs.insert({name, node}); + requestedOutputs.insert({name, node.get()}); } void InfEngineNgraphNet::setNodePtr(std::shared_ptr* ptr) { @@ -457,6 +517,9 @@ void InfEngineNgraphNet::createNet(Target targetId) { CV_LOG_DEBUG(NULL, "DNN/NGRAPH: Add 'Result' output: " << output_node_it->first); CV_Assert(output_node_it->second); auto out = std::make_shared(output_node_it->second->node); +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + out->set_friendly_name(output_node_it->first + (output_node_it->second->node->get_output_size() == 1 ? "" : ".0")); +#endif outs.push_back(out); } CV_Assert_N(!inputs_vec.empty(), !outs.empty()); @@ -504,12 +567,20 @@ void InfEngineNgraphNet::createNet(Target targetId) { } } +#if INF_ENGINE_VER_MAJOR_LT(INF_ENGINE_RELEASE_2022_1) +static inline +InferenceEngine::Layout estimateLayout(size_t dims); +#endif + void InfEngineNgraphNet::init(Target targetId) { if (!hasNetOwner) { if (targetId == DNN_TARGET_OPENCL_FP16) { +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + ov::pass::ConvertFP32ToFP16().run_on_model(ngraph_function); +#else auto nodes = ngraph_function->get_ordered_ops(); for (auto& node : nodes) { @@ -533,6 +604,7 @@ void InfEngineNgraphNet::init(Target targetId) } } ngraph_function->validate_nodes_and_infer_types(); +#endif // OpenVINO >= 2022.1 } cnn = InferenceEngine::CNNNetwork(ngraph_function); @@ -580,20 +652,45 @@ void InfEngineNgraphNet::init(Target targetId) 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 = requestedOutputs.find(name); - if (iter != requestedOutputs.end()) { - requestedOutputs.erase(iter); - cnn.addOutput(name); - } - } +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + auto model = cnn.getFunction(); + ov::preprocess::PrePostProcessor ppp(model); + int i = 0; + for (const auto& inp : model->inputs()) { // TODO: not sure why but ngraph_function->inputs() here causes segfault. + const std::string& name = inp.get_node()->get_friendly_name(); + auto blobIt = allBlobs.find(name); + CV_Assert(blobIt != allBlobs.end()); + + auto srcT = blobIt->second.get_element_type(); + if (srcT != inp.get_node()->get_element_type()) { + ppp.input(i++).tensor().set_element_type(srcT); + } + } + + i = 0; + for (const auto& it : model->outputs()) + { + const std::string& name = it.get_node()->get_friendly_name(); + auto blobIt = allBlobs.find(name); + CV_Assert(blobIt != allBlobs.end()); + const auto& src = blobIt->second; + + // A workaround for single dimension output for which OpenCV allocates 2d Mat. + // For example, face-detection-0105 with Result of shape {200} while output blob is {200, 1} + auto outShape = it.get_partial_shape().get_max_shape(); + if (outShape != src.get_shape()) { + size_t sz = std::accumulate(outShape.begin(), outShape.end(), 1, std::multiplies()); + CV_Assert(sz == src.get_size()); + allBlobs[name] = ov::Tensor(src.get_element_type(), outShape, src.data()); } + + ppp.output(i++).tensor().set_element_type(ov::element::f32); // Should be always FP32 } + ppp.build(); + +#else + for (const auto& it : cnn.getInputsInfo()) { const std::string& name = it.first; @@ -607,8 +704,16 @@ void InfEngineNgraphNet::init(Target targetId) const std::string& name = it.first; auto blobIt = allBlobs.find(name); CV_Assert(blobIt != allBlobs.end()); + InferenceEngine::TensorDesc& desc = blobIt->second->getTensorDesc(); + + auto outShape = it.second->getDims(); + if (outShape != desc.getDims()) { + desc.reshape(outShape, estimateLayout(outShape.size())); + } + it.second->setPrecision(blobIt->second->getTensorDesc().getPrecision()); // Should be always FP32 } +#endif // OpenVINO >= 2022.1 initPlugin(cnn); } @@ -660,6 +765,9 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) const std::string& libName = candidates[i]; try { +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + ie.add_extension(libName); +#else InferenceEngine::IExtensionPtr extension = #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4) std::make_shared(libName); @@ -668,6 +776,7 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) #endif ie.AddExtension(extension, "CPU"); +#endif CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << libName); found = true; break; @@ -678,6 +787,7 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) { 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"); } +#if INF_ENGINE_VER_MAJOR_LT(INF_ENGINE_RELEASE_2022_1) // Some of networks can work without a library of extra layers. // OpenCV fallbacks as extensions. try @@ -688,12 +798,17 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) { CV_LOG_INFO(NULL, "DNN-IE: Can't register OpenCV custom layers nGraph extension: " << e.what()); } +#endif // OpenVINO < 2022.1 #ifndef _WIN32 // Limit the number of CPU threads. if (device_name == "CPU") +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + ie.set_property(device_name, ov::inference_num_threads(getNumThreads())); +#else ie.SetConfig({{ InferenceEngine::PluginConfigParams::KEY_CPU_THREADS_NUM, format("%d", getNumThreads()), }}, device_name); +#endif // OpenVINO >= 2022.1 #endif #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_2) if (device_name.find("GPU") == 0) @@ -706,9 +821,13 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) if (!cache_path.empty() && cache_path != "disabled") { CV_LOG_INFO(NULL, "OpenCV/nGraph: using GPU kernels cache: " << cache_path); +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + ie.set_property(device_name, ov::cache_dir(cache_path)); +#else ie.SetConfig({{ InferenceEngine::PluginConfigParams::KEY_CACHE_DIR, cache_path, }}, device_name); +#endif // OpenVINO >= 2022.1 } } #endif @@ -716,9 +835,9 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net) std::map config; if (device_name == "MYRIAD" || device_name == "HDDL") { #if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2020_4) - config.emplace("MYRIAD_DETECT_NETWORK_BATCH", CONFIG_VALUE(NO)); + config.emplace("MYRIAD_DETECT_NETWORK_BATCH", "NO"); #else - config.emplace("VPU_DETECT_NETWORK_BATCH", CONFIG_VALUE(NO)); + config.emplace("VPU_DETECT_NETWORK_BATCH", "NO"); #endif } @@ -757,16 +876,17 @@ bool NgraphBackendLayer::getMemoryShapes(const std::vector &inputs, std::vector &outputs, std::vector &internals) const { - InferenceEngine::ICNNNetwork::InputShapes inShapes = t_net.getInputShapes(); - InferenceEngine::ICNNNetwork::InputShapes::iterator itr; + auto ngraphFunction = t_net.getFunction(); bool equal_flag = true; - size_t i = 0; - for (itr = inShapes.begin(); itr != inShapes.end(); ++itr) + std::map > inShapes; + int i = 0; + for (const auto& inp : ngraphFunction->get_parameters()) { - InferenceEngine::SizeVector currentInShape(inputs[i].begin(), inputs[i].end()); - if (itr->second != currentInShape) + std::vector oldShape = inp->get_shape(); + std::vector newShape(inputs[i].begin(), inputs[i].end()); + inShapes.insert({inp->get_friendly_name(), newShape}); + if (oldShape != newShape) { - itr->second = currentInShape; equal_flag = false; } i++; @@ -777,7 +897,18 @@ bool NgraphBackendLayer::getMemoryShapes(const std::vector &inputs, InferenceEngine::CNNNetwork curr_t_net(t_net); curr_t_net.reshape(inShapes); } +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + std::vector dims; + for (const auto& it : ngraphFunction->outputs()) { + if (it.get_node()->get_friendly_name() == name) { + dims = it.get_partial_shape().get_max_shape(); + } + } + if (dims.empty()) + CV_Error(Error::StsError, format("Unable find result with name %s", name.c_str())); +#else std::vector dims = t_net.getOutputsInfo()[name]->getDims(); +#endif outputs.push_back(MatShape(dims.begin(), dims.end())); return false; } @@ -795,6 +926,21 @@ void NgraphBackendLayer::forward(InputArrayOfArrays inputs, OutputArrayOfArrays CV_Error(Error::StsInternal, "Choose Inference Engine as a preferable backend."); } +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + +ov::Tensor wrapToNgraphBlob(const Mat& m) { + std::vector shape = getShape(m); + if (m.type() == CV_32F) + return ov::Tensor(ov::element::f32, shape, m.data); + else if (m.type() == CV_8U) + return ov::Tensor(ov::element::u8, shape, m.data); + else if (m.type() == CV_32SC1) + return ov::Tensor(ov::element::i32, shape, m.data); + else + CV_Error(Error::StsNotImplemented, format("Unsupported data type %s", typeToString(m.type()).c_str())); +} + +#else static InferenceEngine::Layout estimateLayout(int dims) { @@ -823,19 +969,6 @@ InferenceEngine::Layout estimateLayout(const Mat& m) return estimateLayout(m.dims); } -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) { @@ -845,6 +978,9 @@ InferenceEngine::Blob::Ptr wrapToNgraphBlob(const Mat& m, const std::vector( {InferenceEngine::Precision::U8, shape, layout}, (uint8_t*)m.data); + else if (m.type() == CV_32SC1) + return InferenceEngine::make_shared_blob( + {InferenceEngine::Precision::I32, shape, layout}, (int32_t*)m.data); else CV_Error(Error::StsNotImplemented, format("Unsupported data type %s", typeToString(m.type()).c_str())); } @@ -855,12 +991,15 @@ InferenceEngine::Blob::Ptr wrapToNgraphBlob(const Mat& m, InferenceEngine::Layou return wrapToNgraphBlob(m, shape, layout); } +InferenceEngine::Blob::Ptr wrapToNgraphBlob(const Mat& m) { return wrapToNgraphBlob(m, estimateLayout(m)); } + +#endif // OpenVINO >= 2022.1 + NgraphBackendWrapper::NgraphBackendWrapper(int targetId, const cv::Mat& m) : BackendWrapper(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, targetId) , host((Mat*)&m) { - dataPtr = wrapToInfEngineDataNode(m); - blob = wrapToNgraphBlob(m, estimateLayout(m)); + blob = wrapToNgraphBlob(m); } NgraphBackendWrapper::NgraphBackendWrapper(Ptr wrapper) @@ -868,8 +1007,7 @@ NgraphBackendWrapper::NgraphBackendWrapper(Ptr wrapper) { Ptr ieWrapper = wrapper.dynamicCast(); CV_Assert(!ieWrapper.empty()); - InferenceEngine::DataPtr srcData = ieWrapper->dataPtr; - dataPtr = InferenceEngine::DataPtr(new InferenceEngine::Data(srcData->getName(), srcData->getTensorDesc())); + name = ieWrapper->name; blob = ieWrapper->blob; } @@ -895,6 +1033,12 @@ void NgraphBackendWrapper::setHostDirty() //CV_Error(Error::StsNotImplemented, ""); } +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) +ov::Tensor copyBlob(const ov::Tensor& blob) +{ + return ov::Tensor(blob.get_element_type(), blob.get_shape()); +} +#else InferenceEngine::Blob::Ptr copyBlob(const InferenceEngine::Blob::Ptr& blob) { InferenceEngine::Blob::Ptr copy; @@ -918,88 +1062,13 @@ InferenceEngine::Blob::Ptr copyBlob(const InferenceEngine::Blob::Ptr& blob) return copy; } -InferenceEngine::DataPtr ngraphDataNode(const Ptr& ptr) -{ - CV_Assert(!ptr.empty()); - Ptr p = ptr.dynamicCast(); - CV_Assert(!p.empty()); - return p->dataPtr; -} - -static -InferenceEngine::Blob::Ptr reallocateBlob(Mat &m, const InferenceEngine::TensorDesc& description) -{ - auto dims = description.getDims(); - auto layout = estimateLayout(dims.size()); - MatShape matShape(dims.begin(), dims.end()); - if (description.getPrecision() == InferenceEngine::Precision::FP32) - { - m.create(matShape, CV_32FC1); - return InferenceEngine::make_shared_blob( - {description.getPrecision(), dims, layout}, (float*)m.data); - } - else if (description.getPrecision() == InferenceEngine::Precision::I32) - { - m.create(matShape, CV_32SC1); - return InferenceEngine::make_shared_blob( - {description.getPrecision(), dims, layout}, (int*)m.data); - } - else if (description.getPrecision() == InferenceEngine::Precision::U8) - { - m.create(matShape, CV_8UC1); - return InferenceEngine::make_shared_blob( - {description.getPrecision(), dims, layout}, (uchar*)m.data); - } - std::ostringstream msg; - msg << "Unsupported IE precision: " << description.getPrecision(); - CV_Error(Error::StsNotImplemented, msg.str()); -} - -InferenceEngine::DataPtr ngraphDataOutputNode( - const Ptr& ptr, - const InferenceEngine::TensorDesc& description, - const std::string name) -{ - CV_Assert(!ptr.empty()); - Ptr p = ptr.dynamicCast(); - CV_Assert(!p.empty()); - NgraphBackendWrapper& w = *p; - const InferenceEngine::TensorDesc& blobDesc = w.blob.get()->getTensorDesc(); - auto dims = description.getDims(); - bool reallocate = false; - if (blobDesc.getPrecision() != description.getPrecision()) - { - reallocate = true; - CV_LOG_WARNING(NULL, "Reallocate output '" << name << "' blob due to wrong precision: " << blobDesc.getPrecision() << " => " << description.getPrecision() << " ndims=" << dims.size()); - } - if (dims.size() != blobDesc.getDims().size()) - { - reallocate = true; - CV_LOG_WARNING(NULL, "Reallocate output '" << name << "' blob due to wrong dims: " << blobDesc.getDims().size() << " => " << dims.size()); - } - if (reallocate) - { - auto layout = estimateLayout(dims.size()); - w.dataPtr = InferenceEngine::DataPtr(new InferenceEngine::Data(name, - {description.getPrecision(), dims, layout})); - w.blob = reallocateBlob(*w.host, description); - } - return w.dataPtr; -} - +#endif // OpenVINO < 2022.1 void InfEngineNgraphNet::reset() { allBlobs.clear(); infRequests.clear(); isInit = false; - - outputsDesc.clear(); - for (const auto& it : cnn.getOutputsInfo()) - { - const std::string& name = it.first; - outputsDesc.insert({name, it.second->getTensorDesc()}); - } } void InfEngineNgraphNet::addBlobs(const std::vector >& ptrs) @@ -1007,7 +1076,7 @@ void InfEngineNgraphNet::addBlobs(const std::vector >& p auto wrappers = ngraphWrappers(ptrs); for (const auto& wrapper : wrappers) { - std::string name = wrapper->dataPtr->getName(); + std::string name = wrapper->name; name = name.empty() ? kDefaultInpLayerName : name; allBlobs.insert({name, wrapper->blob}); } @@ -1022,25 +1091,8 @@ void InfEngineNgraphNet::NgraphReqWrapper::makePromises(const std::vectorfutureMat = 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"); + outsNames[i] = outs[i]->name; } - return Mat(size, type, (void*)blob->buffer()); } void InfEngineNgraphNet::forward(const std::vector >& outBlobsWrappers, bool isAsync) @@ -1070,6 +1122,25 @@ void InfEngineNgraphNet::forward(const std::vector >& outBlo } infRequests.push_back(reqWrapper); +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + int i = 0; + for (const auto& it : netExec.inputs()) + { + const std::string& name = it.get_node()->get_friendly_name(); + auto blobIt = allBlobs.find(name); + CV_Assert(blobIt != allBlobs.end()); + reqWrapper->req.set_input_tensor(i++, isAsync ? copyBlob(blobIt->second) : blobIt->second); + } + + i = 0; + for (const auto& it : netExec.outputs()) + { + const std::string& name = it.get_node()->get_friendly_name(); + auto blobIt = allBlobs.find(name); + CV_Assert(blobIt != allBlobs.end()); + reqWrapper->req.set_output_tensor(i++, isAsync ? copyBlob(blobIt->second) : blobIt->second); + } +#else InferenceEngine::BlobMap inpBlobs, outBlobs; for (const auto& it : cnn.getInputsInfo()) { @@ -1087,6 +1158,53 @@ void InfEngineNgraphNet::forward(const std::vector >& outBlo } reqWrapper->req.SetInput(inpBlobs); reqWrapper->req.SetOutput(outBlobs); +#endif + +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + if (isAsync) { + bool* isReady = &reqWrapper->isReady; + auto* promises = &reqWrapper->outProms; + auto* req = &reqWrapper->req; + reqWrapper->req.set_callback([isReady, promises, req](std::exception_ptr ex) { + CV_LOG_DEBUG(NULL, "DNN(nGraph): completionCallback(" << (int)status << ")"); + + size_t processedOutputs = 0; + try + { + for (; processedOutputs < promises->size(); ++processedOutputs) + { + Mat m = infEngineBlobToMat(req->get_output_tensor(processedOutputs)); + + try + { + (*promises)[processedOutputs].setValue(m.clone()); + } + catch (...) + { + try { + (*promises)[processedOutputs].setException(std::current_exception()); + } catch(...) { + CV_LOG_ERROR(NULL, "DNN: Exception occurred during async inference exception propagation"); + } + } + } + } + catch (...) + { + std::exception_ptr e = std::current_exception(); + for (; processedOutputs < promises->size(); ++processedOutputs) + { + try { + (*promises)[processedOutputs].setException(e); + } catch(...) { + CV_LOG_ERROR(NULL, "DNN: Exception occurred during async inference exception propagation"); + } + } + } + *isReady = true; + }); + } +#else // OpenVINO >= 2022.1 #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4) InferenceEngine::InferRequest infRequest = reqWrapper->req; @@ -1125,7 +1243,7 @@ void InfEngineNgraphNet::forward(const std::vector >& outBlo for (; processedOutputs < wrapper.outProms.size(); ++processedOutputs) { const std::string& name = wrapper.outsNames[processedOutputs]; - Mat m = ngraphBlobToMat(wrapper.req.GetBlob(name)); + Mat m = infEngineBlobToMat(wrapper.req.GetBlob(name)); try { @@ -1157,8 +1275,34 @@ void InfEngineNgraphNet::forward(const std::vector >& outBlo wrapper.isReady = true; } ); +#endif // OpenVINO >= 2022.1 } +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + if (isAsync) + { + // Copy actual data to infer request's input blobs. + int i = 0; + for (const auto& it : cnn.getFunction()->get_parameters()) + { + const std::string& name = it->get_friendly_name(); + auto blobIt = allBlobs.find(name); + Mat srcMat = infEngineBlobToMat(blobIt->second); + Mat dstMat = infEngineBlobToMat(reqWrapper->req.get_input_tensor(i++)); + srcMat.copyTo(dstMat); + } + + // Set promises to output blobs wrappers. + reqWrapper->makePromises(outBlobsWrappers); + + reqWrapper->isReady = false; + reqWrapper->req.start_async(); + } + else + { + reqWrapper->req.infer(); + } +#else if (isAsync) { // Copy actual data to infer request's input blobs. @@ -1166,8 +1310,8 @@ void InfEngineNgraphNet::forward(const std::vector >& outBlo { const std::string& name = it.first; auto blobIt = allBlobs.find(name); - Mat srcMat = ngraphBlobToMat(blobIt->second); - Mat dstMat = ngraphBlobToMat(reqWrapper->req.GetBlob(name)); + Mat srcMat = infEngineBlobToMat(blobIt->second); + Mat dstMat = infEngineBlobToMat(reqWrapper->req.GetBlob(name)); srcMat.copyTo(dstMat); } @@ -1181,6 +1325,7 @@ void InfEngineNgraphNet::forward(const std::vector >& outBlo { reqWrapper->req.Infer(); } +#endif // OpenVINO >= 2022.1 } #endif diff --git a/modules/dnn/src/ie_ngraph.hpp b/modules/dnn/src/ie_ngraph.hpp index 9ccc182fc8..09afc7f117 100644 --- a/modules/dnn/src/ie_ngraph.hpp +++ b/modules/dnn/src/ie_ngraph.hpp @@ -68,7 +68,11 @@ public: std::unordered_map* > all_nodes; InferenceEngine::ExecutableNetwork netExec; +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + std::map allBlobs; +#else InferenceEngine::BlobMap allBlobs; +#endif std::string device_name; bool isInit = false; @@ -87,9 +91,7 @@ public: InferenceEngine::CNNNetwork cnn; bool hasNetOwner; - std::unordered_map > requestedOutputs; - - std::map outputsDesc; + std::unordered_map requestedOutputs; }; class InfEngineNgraphNode : public BackendNode @@ -123,17 +125,15 @@ public: virtual void setHostDirty() CV_OVERRIDE; Mat* host; - InferenceEngine::DataPtr dataPtr; + std::string name; +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + ov::Tensor blob; +#else InferenceEngine::Blob::Ptr blob; +#endif AsyncArray futureMat; }; -InferenceEngine::DataPtr ngraphDataNode(const Ptr& ptr); -InferenceEngine::DataPtr ngraphDataOutputNode( - const Ptr& ptr, - const InferenceEngine::TensorDesc& description, - const std::string name); - // 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. diff --git a/modules/dnn/src/layers/concat_layer.cpp b/modules/dnn/src/layers/concat_layer.cpp index 1b520cf87a..52330a8e42 100644 --- a/modules/dnn/src/layers/concat_layer.cpp +++ b/modules/dnn/src/layers/concat_layer.cpp @@ -403,8 +403,7 @@ public: virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE { - InferenceEngine::DataPtr data = ngraphDataNode(inputs[0]); - const int numDims = data->getDims().size(); + const int numDims = nodes[0].dynamicCast()->node->get_shape().size(); const int cAxis = normalize_axis(axis, numDims); std::vector maxDims(numDims, 0); @@ -412,16 +411,17 @@ public: ngraph::OutputVector inp_nodes; for (int i = 0; i < nodes.size(); ++i) { - inp_nodes.push_back(nodes[i].dynamicCast()->node); + auto inp = nodes[i].dynamicCast()->node; + inp_nodes.push_back(inp); - std::vector inpShape = ngraphDataNode(inputs[i])->getDims(); + std::vector inpShape = inp->get_shape(); for (int i = 0; i < numDims; ++i) maxDims[i] = std::max(maxDims[i], inpShape[i]); } for (int i = 0; i < inp_nodes.size(); ++i) { bool needPadding = false; - std::vector inpShape = ngraphDataNode(inputs[i])->getDims(); + std::vector inpShape = inp_nodes[i].get_shape(); std::vector begins(inpShape.size(), 0), ends(inpShape.size(), 0); for (int j = 0; j < inpShape.size(); ++j) { diff --git a/modules/dnn/src/layers/nary_eltwise_layers.cpp b/modules/dnn/src/layers/nary_eltwise_layers.cpp index 6850cd5211..3f43c024c7 100644 --- a/modules/dnn/src/layers/nary_eltwise_layers.cpp +++ b/modules/dnn/src/layers/nary_eltwise_layers.cpp @@ -6,6 +6,7 @@ #include "layers_common.hpp" #include "../op_cuda.hpp" #include "../op_cann.hpp" +#include "../ie_ngraph.hpp" #include @@ -104,6 +105,12 @@ public: return op == OPERATION::ADD || op == OPERATION::PROD || op == OPERATION::DIV || op == OPERATION::DIV || op == OPERATION::MAX || op == OPERATION::MIN; #endif + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + return (op == OPERATION::ADD || + op == OPERATION::PROD || + op == OPERATION::GREATER_EQUAL || + op == OPERATION::LESS_EQUAL + ); if (op == OPERATION::MAX || op == OPERATION::MIN || op == OPERATION::SUM || op == OPERATION::PROD || op == OPERATION::DIV) return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_CUDA; @@ -743,6 +750,37 @@ public: CV_Assert(inputs.size()); return inputs.size() * total(outputs[0]); } + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE + { + CV_Assert(inputs.size() == 2); + auto& inp0 = nodes[0].dynamicCast()->node; + auto& inp1 = nodes[1].dynamicCast()->node; + + if (inp0->get_element_type() != inp1->get_element_type()) { + auto dtype = preferableTarget == DNN_TARGET_OPENCL_FP16 || preferableTarget == DNN_TARGET_MYRIAD ? + ngraph::element::f16 : ngraph::element::f32; + if (inp0->get_element_type() != dtype) + inp0 = std::make_shared(inp0, dtype); + if (inp1->get_element_type() != dtype) + inp1 = std::make_shared(inp1, dtype); + } + + std::shared_ptr node; + if (op == OPERATION::ADD) + node = std::make_shared(inp0, inp1); + else if (op == OPERATION::PROD) + node = std::make_shared(inp0, inp1); + else if (op == OPERATION::GREATER_EQUAL) + node = std::make_shared(inp0, inp1); + else if (op == OPERATION::LESS_EQUAL) + node = std::make_shared(inp0, inp1); + else + CV_Error(Error::StsNotImplemented, "Operation is not implemented for nGraph backend"); + return Ptr(new InfEngineNgraphNode(node)); + } +#endif }; Ptr NaryEltwiseLayer::create(const LayerParams& params) diff --git a/modules/dnn/src/layers/resize_layer.cpp b/modules/dnn/src/layers/resize_layer.cpp index 356b193ab5..4342b51b78 100644 --- a/modules/dnn/src/layers/resize_layer.cpp +++ b/modules/dnn/src/layers/resize_layer.cpp @@ -401,6 +401,24 @@ public: #else ngraph::op::v4::Interpolate::InterpolateAttrs attrs; +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + if (interpolation == "nearest") { + attrs.mode = ngraph::op::v4::Interpolate::InterpolateMode::NEAREST; + attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::HALF_PIXEL; + } else if (interpolation == "bilinear") { + attrs.mode = ngraph::op::v4::Interpolate::InterpolateMode::LINEAR_ONNX; + attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::ASYMMETRIC; + } else { + CV_Error(Error::StsNotImplemented, format("Unsupported interpolation: %s", interpolation.c_str())); + } + attrs.shape_calculation_mode = ngraph::op::v4::Interpolate::ShapeCalcMode::SIZES; + + if (alignCorners) { + attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::ALIGN_CORNERS; + } + + attrs.nearest_mode = ngraph::op::v4::Interpolate::NearestMode::ROUND_PREFER_FLOOR; +#else if (interpolation == "nearest") { attrs.mode = ngraph::op::v4::Interpolate::InterpolateMode::nearest; attrs.coordinate_transformation_mode = ngraph::op::v4::Interpolate::CoordinateTransformMode::half_pixel; @@ -417,6 +435,7 @@ public: } attrs.nearest_mode = ngraph::op::v4::Interpolate::NearestMode::round_prefer_floor; +#endif // OpenVINO >= 2022.1 std::vector shape = {outHeight, outWidth}; auto out_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, shape.data()); diff --git a/modules/dnn/src/net_openvino.cpp b/modules/dnn/src/net_openvino.cpp index d55c26a0de..5704cb9b64 100644 --- a/modules/dnn/src/net_openvino.cpp +++ b/modules/dnn/src/net_openvino.cpp @@ -275,19 +275,17 @@ void NetImplOpenVINO::initBackend(const std::vector& blobsToKeep_) (netInputLayer->outNames.size() == ld.outputBlobsWrappers.size())); for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i) { - InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.outputBlobsWrappers[i]); std::string outputName = netInputLayer->outNames.empty() ? ld.name : netInputLayer->outNames[i]; outputName = ld.outputBlobsWrappers.size() > 1 ? (outputName + "." + std::to_string(i)) : outputName; - dataPtr->setName(outputName); + ld.outputBlobsWrappers[i].dynamicCast()->name = outputName; } } else { for (int i = 0; i < ld.outputBlobsWrappers.size(); ++i) { - InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.outputBlobsWrappers[i]); std::string outputName = ld.outputBlobsWrappers.size() > 1 ? (ld.name + "." + std::to_string(i)) : ld.name; - dataPtr->setName(outputName); + ld.outputBlobsWrappers[i].dynamicCast()->name = outputName; } } } @@ -311,26 +309,7 @@ void NetImplOpenVINO::initBackend(const std::vector& blobsToKeep_) { 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) - { - auto it = ienet.outputsDesc.find(ld.name); - if (it != ienet.outputsDesc.end()) - { - const InferenceEngine::TensorDesc& descriptor = it->second; - InferenceEngine::DataPtr dataPtr = ngraphDataOutputNode(ld.outputBlobsWrappers[i], descriptor, ld.name); - dataPtr->setName(ld.name); - } - else - { - InferenceEngine::DataPtr dataPtr = ngraphDataNode(ld.outputBlobsWrappers[i]); - dataPtr->setName(ld.name); - } + ld.inputBlobsWrappers[i].dynamicCast()->name = netInputLayer->outNames[i]; } } ienet.addBlobs(ld.inputBlobsWrappers); @@ -456,10 +435,10 @@ void NetImplOpenVINO::initBackend(const std::vector& blobsToKeep_) dynamicCast(); CV_Assert(!inpWrapper.empty()); auto iter = std::find(inputNames.begin(), inputNames.end(), - inpWrapper->dataPtr->getName()); + inpWrapper->name); if (iter == inputNames.end()) { - inputNames.push_back(inpWrapper->dataPtr->getName()); + inputNames.push_back(inpWrapper->name); inputs.push_back(inpLd.outputBlobs[cons_inp]); } curr_pos = cons + 1; @@ -505,7 +484,12 @@ void NetImplOpenVINO::initBackend(const std::vector& blobsToKeep_) CV_LOG_DEBUG(NULL, "DNN/IE: bind output port " << lid << ":" << oid << " (" << ngraph_input_node->get_friendly_name() << ":" << ngraph_input_node->get_type_info().name << ")"); // Handle parameters from other subnets. Output port is not used in this case +#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2020_4) if ((ngraph::op::is_parameter(ngraph_input_node) || ngraph::op::is_constant(ngraph_input_node)) && +#else + if ((ngraph_input_node->is_parameter() || ngraph_input_node->is_constant()) && +#endif + ngraph_input_node->get_output_size() == 1) { inputNodes[i] = Ptr(new InfEngineNgraphNode(ngraph_input_node)); @@ -702,14 +686,33 @@ Net NetImplOpenVINO::createNetworkFromModelOptimizer(InferenceEngine::CNNNetwork CV_TRACE_REGION("register_inputs"); + auto ngraphFunction = ieNet.getFunction(); + CV_Assert(ngraphFunction); + std::vector inputsNames; std::vector inp_shapes; - for (auto& it : ieNet.getInputsInfo()) + for (auto& it : ngraphFunction->get_parameters()) { - inputsNames.push_back(it.first); - std::vector dims = it.second->getTensorDesc().getDims(); + inputsNames.push_back(it->get_friendly_name()); + std::vector dims = it->get_shape(); inp_shapes.push_back(std::vector(dims.begin(), dims.end())); } + // nGraph models produce output "Result" layers which have "/sink_port" suffix in their names. + // Their inputs are actual model outputs and we change friendly name to it. + // By this workaround, we produce similar outputs names comparing to ieNet.getOutputsInfo() + for (int i = 0; i < ngraphFunction->get_output_size(); ++i) { + auto res = ngraphFunction->output(i); +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + const std::string& name = res.get_any_name(); +#else + auto out = res.get_node()->input(0).get_source_output(); + std::string name = out.get_node()->get_friendly_name(); + if (out.get_node()->get_output_size() > 1) + name += "." + std::to_string(out.get_index()); +#endif + if (res.get_node()->get_friendly_name() != name) + res.get_node()->set_friendly_name(name); + } Net cvNet; Ptr openvino_impl_ptr = makePtr(); @@ -736,17 +739,15 @@ Net NetImplOpenVINO::createNetworkFromModelOptimizer(InferenceEngine::CNNNetwork CV_TRACE_REGION_NEXT("register_outputs"); - auto ngraphFunction = ieNet.getFunction(); - CV_Assert(ngraphFunction); std::vector> ngraphOperations = ngraphFunction->get_ops(); - for (auto& it : ieNet.getOutputsInfo()) + for (auto& it : ngraphFunction->get_results()) { CV_TRACE_REGION("output"); - const auto& outputName = it.first; + const auto& outputName = it->get_friendly_name(); LayerParams lp; - int lid = cvNet.addLayer(it.first, "", lp); + int lid = cvNet.addLayer(outputName, "", lp); LayerData& ld = openvino_impl.layers[lid]; @@ -835,10 +836,15 @@ Net openvino_readNetwork( InferenceEngine::CNNNetwork ieNet; try { +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + ov::Tensor weights_blob(ov::element::u8, {bufferWeightsSize}, (void*)bufferWeightsPtr); + ieNet = ie.read_model(model, weights_blob); +#else InferenceEngine::TensorDesc tensorDesc(InferenceEngine::Precision::U8, { bufferWeightsSize }, InferenceEngine::Layout::C); InferenceEngine::Blob::CPtr weights_blob = InferenceEngine::make_shared_blob(tensorDesc, (uint8_t*)bufferWeightsPtr, bufferWeightsSize); ieNet = ie.ReadNetwork(model, weights_blob); +#endif } catch (const std::exception& e) { diff --git a/modules/dnn/src/op_inf_engine.cpp b/modules/dnn/src/op_inf_engine.cpp index e237be07cf..f9e3993d20 100644 --- a/modules/dnn/src/op_inf_engine.cpp +++ b/modules/dnn/src/op_inf_engine.cpp @@ -39,6 +39,86 @@ cv::String setInferenceEngineBackendType(const cv::String& newBackendType) CV__DNN_INLINE_NS_END +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) +namespace InferenceEngine { + +CNNNetwork::CNNNetwork() {} + +CNNNetwork::CNNNetwork(std::shared_ptr model) : model(model) {} + +std::shared_ptr CNNNetwork::getFunction() const { + return model; +} + +void CNNNetwork::serialize(const std::string& xmlPath, const std::string& binPath) { + ov::pass::Serialize(xmlPath, binPath).run_on_model(model); +} + +void CNNNetwork::reshape(const std::map >& shapes) { + std::map partialShapes; + for (const auto& it : shapes) { + ov::PartialShape shape; + shape.insert(shape.begin(), it.second.begin(), it.second.end()); + partialShapes.insert({it.first, shape}); + } + model->reshape(partialShapes); +} + +std::vector Core::GetAvailableDevices() { + return get_available_devices(); +} + +void Core::UnregisterPlugin(const std::string& id) { + unload_plugin(id); +} + +CNNNetwork Core::ReadNetwork(const std::string& xmlPath, const std::string& binPath) { + return read_model(xmlPath, binPath); +} + +ExecutableNetwork Core::LoadNetwork(CNNNetwork net, const std::string& device, + const std::map& config) { + ov::AnyMap props; + for (const auto& it : config) { + props.insert(it); + } + return compile_model(net.getFunction(), device, props); +} + +ExecutableNetwork::ExecutableNetwork() {} + +ExecutableNetwork::ExecutableNetwork(const ov::CompiledModel& copy) : CompiledModel(copy) {} + +ov::InferRequest ExecutableNetwork::CreateInferRequest() { return create_infer_request(); } + +} // namespace InferenceEngine + +Mat infEngineBlobToMat(const ov::Tensor& blob) +{ + std::vector dims = blob.get_shape(); + std::vector size(dims.begin(), dims.end()); + auto precision = blob.get_element_type(); + + int type = -1; + switch (precision) + { + case ov::element::f32: type = CV_32F; break; + case ov::element::u8: type = CV_8U; break; + default: + CV_Error(Error::StsNotImplemented, "Unsupported blob precision"); + } + return Mat(size, type, blob.data()); +} + +void infEngineBlobsToMats(const ov::TensorVector& blobs, + std::vector& mats) +{ + mats.resize(blobs.size()); + for (int i = 0; i < blobs.size(); ++i) + mats[i] = infEngineBlobToMat(blobs[i]); +} + +#else Mat infEngineBlobToMat(const InferenceEngine::Blob::Ptr& blob) { @@ -65,7 +145,7 @@ void infEngineBlobsToMats(const std::vector& blobs, for (int i = 0; i < blobs.size(); ++i) mats[i] = infEngineBlobToMat(blobs[i]); } - +#endif // OpenVINO >= 2022.1 static bool init_IE_plugins() { @@ -130,7 +210,11 @@ static bool detectArmPlugin_() { if (i->find("CPU") != std::string::npos) { +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + const std::string name = ie.get_property(*i, ov::device::full_name); +#else const std::string name = ie.GetMetric(*i, METRIC_KEY(FULL_DEVICE_NAME)).as(); +#endif CV_LOG_INFO(NULL, "CPU plugin: " << name); return name.find("arm_compute::NEON") != std::string::npos; } @@ -150,7 +234,11 @@ static bool detectMyriadX_(const std::string& device) { if (i->find(device) != std::string::npos) { +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) + const std::string name = ie.get_property(*i, ov::device::full_name); +#else const std::string name = ie.GetMetric(*i, METRIC_KEY(FULL_DEVICE_NAME)).as(); +#endif CV_LOG_INFO(NULL, "Myriad device: " << name); return name.find("MyriadX") != std::string::npos || name.find("Myriad X") != std::string::npos || name.find("HDDL") != std::string::npos; } diff --git a/modules/dnn/src/op_inf_engine.hpp b/modules/dnn/src/op_inf_engine.hpp index 6ac4d955cc..45913d3b31 100644 --- a/modules/dnn/src/op_inf_engine.hpp +++ b/modules/dnn/src/op_inf_engine.hpp @@ -19,11 +19,6 @@ #ifdef HAVE_INF_ENGINE -#define INF_ENGINE_RELEASE_2018R5 2018050000 -#define INF_ENGINE_RELEASE_2019R1 2019010000 -#define INF_ENGINE_RELEASE_2019R2 2019020000 -#define INF_ENGINE_RELEASE_2019R3 2019030000 -#define INF_ENGINE_RELEASE_2020_1 2020010000 #define INF_ENGINE_RELEASE_2020_2 2020020000 #define INF_ENGINE_RELEASE_2020_3 2020030000 #define INF_ENGINE_RELEASE_2020_4 2020040000 @@ -31,6 +26,7 @@ #define INF_ENGINE_RELEASE_2021_2 2021020000 #define INF_ENGINE_RELEASE_2021_3 2021030000 #define INF_ENGINE_RELEASE_2021_4 2021040000 +#define INF_ENGINE_RELEASE_2022_1 2022010000 #ifndef INF_ENGINE_RELEASE #warning("IE version have not been provided via command-line. Using 2021.4 by default") @@ -48,7 +44,13 @@ #pragma GCC diagnostic ignored "-Wsuggest-override" #endif +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) +#include +#include +#include +#else #include +#endif #if defined(__GNUC__) && __GNUC__ >= 5 //#pragma GCC diagnostic pop @@ -73,11 +75,17 @@ CV__DNN_INLINE_NS_END Backend& getInferenceEngineBackendTypeParam(); +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) +Mat infEngineBlobToMat(const ov::Tensor& blob); + +void infEngineBlobsToMats(const ov::TensorVector& blobs, + std::vector& mats); +#else Mat infEngineBlobToMat(const InferenceEngine::Blob::Ptr& blob); void infEngineBlobsToMats(const std::vector& blobs, std::vector& mats); - +#endif // OpenVINO >= 2022.1 CV__DNN_INLINE_NS_BEGIN @@ -90,6 +98,52 @@ bool isArmComputePlugin(); CV__DNN_INLINE_NS_END +// A series of wrappers for classes from OpenVINO API 2.0. +// Need just for less conditional compilation inserts. +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2022_1) +namespace InferenceEngine { + +class CNNNetwork { +public: + CNNNetwork(); + + CNNNetwork(std::shared_ptr model); + + std::shared_ptr getFunction() const; + + void serialize(const std::string& xmlPath, const std::string& binPath); + + void reshape(const std::map >& shapes); + +private: + std::shared_ptr model = nullptr; +}; + +typedef ov::InferRequest InferRequest; + +class ExecutableNetwork : public ov::CompiledModel { +public: + ExecutableNetwork(); + + ExecutableNetwork(const ov::CompiledModel& copy); + + ov::InferRequest CreateInferRequest(); +}; + +class Core : public ov::Core { +public: + std::vector GetAvailableDevices(); + + void UnregisterPlugin(const std::string& id); + + CNNNetwork ReadNetwork(const std::string& xmlPath, const std::string& binPath); + + ExecutableNetwork LoadNetwork(CNNNetwork net, const std::string& device, + const std::map& config); +}; + +} +#endif // OpenVINO >= 2022.1 InferenceEngine::Core& getCore(const std::string& id); diff --git a/modules/dnn/test/test_backends.cpp b/modules/dnn/test/test_backends.cpp index 9b8765b92d..7aa9c756fb 100644 --- a/modules/dnn/test/test_backends.cpp +++ b/modules/dnn/test/test_backends.cpp @@ -531,7 +531,7 @@ TEST_P(DNNTestNetwork, FastNeuralStyle_eccv16) if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) { l1 = 0.4; - lInf = 7.45; + lInf = 7.46; } else if (target == DNN_TARGET_CUDA_FP16) { diff --git a/modules/dnn/test/test_caffe_importer.cpp b/modules/dnn/test/test_caffe_importer.cpp index 4043bd118e..8059fc6888 100644 --- a/modules/dnn/test/test_caffe_importer.cpp +++ b/modules/dnn/test/test_caffe_importer.cpp @@ -725,18 +725,21 @@ TEST_P(Test_Caffe_nets, FasterRCNN_vgg16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION); #endif + double scoreDiff = 0.0; #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2022010000) // Check 'backward_compatible_check || in_out_elements_equal' failed at core/src/op/reshape.cpp:427: // While validating node 'v1::Reshape bbox_pred_reshape (bbox_pred[0]:f32{1,84}, Constant_265242[0]:i64{4}) -> (f32{?,?,?,?})' with friendly_name 'bbox_pred_reshape': // Requested output shape {1,6300,4,1} is incompatible with input shape {1, 84} if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION); + if (target == DNN_TARGET_OPENCL_FP16) + scoreDiff = 0.02; #endif static Mat ref = (Mat_(3, 7) << 0, 2, 0.949398, 99.2454, 210.141, 601.205, 462.849, 0, 7, 0.997022, 481.841, 92.3218, 722.685, 175.953, 0, 12, 0.993028, 133.221, 189.377, 350.994, 563.166); - testFaster("faster_rcnn_vgg16.prototxt", "VGG16_faster_rcnn_final.caffemodel", ref); + testFaster("faster_rcnn_vgg16.prototxt", "VGG16_faster_rcnn_final.caffemodel", ref, scoreDiff); } TEST_P(Test_Caffe_nets, FasterRCNN_zf) diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index 0b4c1bccff..2160c81fad 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -638,6 +638,11 @@ TEST_P(Test_Darknet_nets, YOLOv3) double scoreDiff = 8e-5, iouDiff = 3e-4; if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) { +#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2022010000) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + scoreDiff = 0.009; + else +#endif scoreDiff = 0.006; iouDiff = 0.042; } @@ -771,6 +776,7 @@ TEST_P(Test_Darknet_nets, YOLOv4) // accuracy (batch 2) if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16) { + scoreDiff = 0.008f; iouDiff = 0.05f; } // accuracy diff --git a/modules/dnn/test/test_ie_models.cpp b/modules/dnn/test/test_ie_models.cpp index 3622f69bdb..135caa9064 100644 --- a/modules/dnn/test/test_ie_models.cpp +++ b/modules/dnn/test/test_ie_models.cpp @@ -438,6 +438,9 @@ TEST_P(DNNTestOpenVINO, models) { auto dstIt = cvOutputsMap.find(srcIt.first); CV_Assert(dstIt != cvOutputsMap.end()); + + dstIt->second.convertTo(dstIt->second, srcIt.second.type()); + double normInf = cvtest::norm(srcIt.second, dstIt->second, cv::NORM_INF); EXPECT_LE(normInf, eps) << "output=" << srcIt.first; } diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index a54c2fecb1..6afb3a8aa0 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -1292,7 +1292,7 @@ TEST_P(Layer_Test_Convolution_DLDT, Accuracy) if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) ASSERT_EQ(net.getLayer(outLayers[0])->type, "Convolution"); else - ASSERT_EQ(net.getLayer(outLayers[0])->type, "Add"); + ASSERT_EQ(net.getLayer(outLayers[0])->type, "Result"); } TEST_P(Layer_Test_Convolution_DLDT, setInput_uint8) diff --git a/modules/dnn/test/test_model.cpp b/modules/dnn/test/test_model.cpp index d7fc2af73d..d3217a0e49 100644 --- a/modules/dnn/test/test_model.cpp +++ b/modules/dnn/test/test_model.cpp @@ -447,6 +447,10 @@ TEST_P(Test_Model, DetectionOutput) { if (backend == DNN_BACKEND_OPENCV) scoreDiff = 4e-3; +#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2022010000) + else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + scoreDiff = 4e-2; +#endif else scoreDiff = 2e-2; iouDiff = 1.8e-1;