1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 15:23:05 +04:00

Merge pull request #15184 from l-bat:IE_R2

Support new IE API (#15184)

* Add support OpenVINO R2 for layers

* Add Core API

* Fix tests

* Fix expectNoFallbacksFromIE for ONNX nets

* Remove deprecated API

* Remove td

* Remove TargetDevice

* Fix Async

* Add test

* Fix detectMyriadX

* Fix test

* Fix warning
This commit is contained in:
Lubov Batanina
2019-08-06 22:20:26 +03:00
committed by Alexander Alekhin
parent cf93a05d2d
commit 0e1ef8f8e1
13 changed files with 247 additions and 130 deletions
+109 -70
View File
@@ -45,13 +45,13 @@ infEngineWrappers(const std::vector<Ptr<BackendWrapper> >& ptrs)
InfEngineBackendNet::InfEngineBackendNet() : netBuilder("")
{
hasNetOwner = false;
targetDevice = InferenceEngine::TargetDevice::eCPU;
device_name = "CPU";
}
InfEngineBackendNet::InfEngineBackendNet(InferenceEngine::CNNNetwork& net) : netBuilder(""), cnn(net)
{
hasNetOwner = true;
targetDevice = InferenceEngine::TargetDevice::eCPU;
device_name = "CPU";
}
void InfEngineBackendNet::connect(const std::vector<Ptr<BackendWrapper> >& inputs,
@@ -66,16 +66,13 @@ void InfEngineBackendNet::connect(const std::vector<Ptr<BackendWrapper> >& input
for (size_t i = 0; i < inpWrappers.size(); ++i)
{
const auto& inp = inpWrappers[i];
const std::string& inpName = inp->dataPtr->name;
const std::string& inpName = inp->dataPtr->getName();
int inpId;
it = layers.find(inpName);
if (it == layers.end())
{
InferenceEngine::Builder::InputLayer inpLayer(!inpName.empty() ? inpName : kDefaultInpLayerName);
std::vector<size_t> shape(inp->blob->dims());
std::reverse(shape.begin(), shape.end());
std::vector<size_t> shape(inp->blob->getTensorDesc().getDims());
inpLayer.setPort(InferenceEngine::Port(shape));
inpId = netBuilder.addLayer(inpLayer);
@@ -89,7 +86,11 @@ void InfEngineBackendNet::connect(const std::vector<Ptr<BackendWrapper> >& input
}
CV_Assert(!outputs.empty());
InferenceEngine::DataPtr dataPtr = infEngineDataNode(outputs[0]);
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
dataPtr->name = layerName;
#else
dataPtr->setName(layerName);
#endif
}
void InfEngineBackendNet::init(int targetId)
@@ -115,21 +116,22 @@ void InfEngineBackendNet::init(int targetId)
switch (targetId)
{
case DNN_TARGET_CPU:
targetDevice = InferenceEngine::TargetDevice::eCPU;
break;
case DNN_TARGET_OPENCL: case DNN_TARGET_OPENCL_FP16:
targetDevice = InferenceEngine::TargetDevice::eGPU;
break;
case DNN_TARGET_MYRIAD:
targetDevice = InferenceEngine::TargetDevice::eMYRIAD;
break;
case DNN_TARGET_FPGA:
targetDevice = InferenceEngine::TargetDevice::eFPGA;
break;
default:
CV_Error(Error::StsError, format("Unknown target identifier: %d", 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");
};
for (const auto& name : requestedOutputs)
{
@@ -141,14 +143,14 @@ void InfEngineBackendNet::init(int targetId)
const std::string& name = it.first;
auto blobIt = allBlobs.find(name);
CV_Assert(blobIt != allBlobs.end());
it.second->setPrecision(blobIt->second->precision());
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->precision()); // Should be always FP32
it.second->setPrecision(blobIt->second->getTensorDesc().getPrecision()); // Should be always FP32
}
initPlugin(cnn);
@@ -223,16 +225,13 @@ static InferenceEngine::Layout estimateLayout(const Mat& m)
static InferenceEngine::DataPtr wrapToInfEngineDataNode(const Mat& m, const std::string& name = "")
{
std::vector<size_t> reversedShape(&m.size[0], &m.size[0] + m.dims);
std::reverse(reversedShape.begin(), reversedShape.end());
std::vector<size_t> shape(&m.size[0], &m.size[0] + m.dims);
if (m.type() == CV_32F)
return InferenceEngine::DataPtr(
new InferenceEngine::Data(name, reversedShape, InferenceEngine::Precision::FP32, estimateLayout(m))
);
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, reversedShape, InferenceEngine::Precision::U8, estimateLayout(m))
);
return InferenceEngine::DataPtr(new InferenceEngine::Data(name,
{InferenceEngine::Precision::U8, shape, estimateLayout(m)}));
else
CV_Error(Error::StsNotImplemented, format("Unsupported data type %d", m.type()));
}
@@ -241,33 +240,33 @@ InferenceEngine::Blob::Ptr wrapToInfEngineBlob(const Mat& m, const std::vector<s
InferenceEngine::Layout layout)
{
if (m.type() == CV_32F)
return InferenceEngine::make_shared_blob<float>(InferenceEngine::Precision::FP32,
layout, shape, (float*)m.data);
return InferenceEngine::make_shared_blob<float>(
{InferenceEngine::Precision::FP32, shape, layout}, (float*)m.data);
else if (m.type() == CV_8U)
return InferenceEngine::make_shared_blob<uint8_t>(InferenceEngine::Precision::U8,
layout, shape, (uint8_t*)m.data);
return InferenceEngine::make_shared_blob<uint8_t>(
{InferenceEngine::Precision::U8, shape, layout}, (uint8_t*)m.data);
else
CV_Error(Error::StsNotImplemented, format("Unsupported data type %d", m.type()));
}
InferenceEngine::Blob::Ptr wrapToInfEngineBlob(const Mat& m, InferenceEngine::Layout layout)
{
std::vector<size_t> reversedShape(&m.size[0], &m.size[0] + m.dims);
std::reverse(reversedShape.begin(), reversedShape.end());
return wrapToInfEngineBlob(m, reversedShape, layout);
std::vector<size_t> shape(&m.size[0], &m.size[0] + m.dims);
return wrapToInfEngineBlob(m, shape, layout);
}
InferenceEngine::Blob::Ptr cloneBlob(const InferenceEngine::Blob::Ptr& blob)
{
InferenceEngine::Precision precision = blob->precision();
InferenceEngine::Blob::Ptr copy;
auto description = blob->getTensorDesc();
InferenceEngine::Precision precision = description.getPrecision();
if (precision == InferenceEngine::Precision::FP32)
{
copy = InferenceEngine::make_shared_blob<float>(precision, blob->layout(), blob->dims());
copy = InferenceEngine::make_shared_blob<float>(description);
}
else if (precision == InferenceEngine::Precision::U8)
{
copy = InferenceEngine::make_shared_blob<uint8_t>(precision, blob->layout(), blob->dims());
copy = InferenceEngine::make_shared_blob<uint8_t>(description);
}
else
CV_Error(Error::StsNotImplemented, "Unsupported blob precision");
@@ -296,10 +295,8 @@ InfEngineBackendWrapper::InfEngineBackendWrapper(Ptr<BackendWrapper> wrapper)
Ptr<InfEngineBackendWrapper> ieWrapper = wrapper.dynamicCast<InfEngineBackendWrapper>();
CV_Assert(!ieWrapper.empty());
InferenceEngine::DataPtr srcData = ieWrapper->dataPtr;
dataPtr = InferenceEngine::DataPtr(
new InferenceEngine::Data(srcData->name, srcData->dims, srcData->precision,
srcData->layout)
);
dataPtr = InferenceEngine::DataPtr(new InferenceEngine::Data(srcData->getName(), srcData->getTensorDesc()));
blob = ieWrapper->blob;
}
@@ -323,12 +320,19 @@ void InfEngineBackendWrapper::setHostDirty()
}
static std::map<InferenceEngine::TargetDevice, InferenceEngine::InferenceEnginePluginPtr>& getSharedPlugins()
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
static std::map<std::string, InferenceEngine::InferenceEnginePluginPtr>& getSharedPlugins()
{
static std::map<InferenceEngine::TargetDevice, InferenceEngine::InferenceEnginePluginPtr> sharedPlugins;
static std::map<std::string, InferenceEngine::InferenceEnginePluginPtr> sharedPlugins;
return sharedPlugins;
}
#else
static InferenceEngine::Core& getCore()
{
static InferenceEngine::Core core;
return core;
}
#endif
#if !defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT)
static bool detectMyriadX_()
@@ -361,24 +365,29 @@ static bool detectMyriadX_()
InferenceEngine::CNNNetwork cnn = InferenceEngine::CNNNetwork(
InferenceEngine::Builder::convertToICNNNetwork(builder.build()));
InferenceEngine::TargetDevice device = InferenceEngine::TargetDevice::eMYRIAD;
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
InferenceEngine::InferenceEnginePluginPtr enginePtr;
{
AutoLock lock(getInitializationMutex());
auto& sharedPlugins = getSharedPlugins();
auto pluginIt = sharedPlugins.find(device);
auto pluginIt = sharedPlugins.find("MYRIAD");
if (pluginIt != sharedPlugins.end()) {
enginePtr = pluginIt->second;
} else {
auto dispatcher = InferenceEngine::PluginDispatcher({""});
enginePtr = dispatcher.getSuitablePlugin(device);
sharedPlugins[device] = enginePtr;
enginePtr = dispatcher.getPluginByDevice("MYRIAD");
sharedPlugins["MYRIAD"] = enginePtr;
}
}
auto plugin = InferenceEngine::InferencePlugin(enginePtr);
try
{
auto netExec = plugin.LoadNetwork(cnn, {{"VPU_PLATFORM", "VPU_2480"}});
#else
try
{
auto netExec = getCore().LoadNetwork(cnn, "MYRIAD", {{"VPU_PLATFORM", "VPU_2480"}});
#endif
auto infRequest = netExec.CreateInferRequest();
} catch(...) {
return false;
@@ -387,38 +396,41 @@ static bool detectMyriadX_()
}
#endif // !defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT)
void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
void InfEngineBackendNet::initPlugin(InferenceEngine::CNNNetwork& net)
{
CV_Assert(!isInitialized());
try
{
AutoLock lock(getInitializationMutex());
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
auto& sharedPlugins = getSharedPlugins();
auto pluginIt = sharedPlugins.find(targetDevice);
auto pluginIt = sharedPlugins.find(device_name);
if (pluginIt != sharedPlugins.end())
{
enginePtr = pluginIt->second;
}
else
#endif
{
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
auto dispatcher = InferenceEngine::PluginDispatcher({""});
if (targetDevice == InferenceEngine::TargetDevice::eFPGA)
if (device_name == "FPGA")
enginePtr = dispatcher.getPluginByDevice("HETERO:FPGA,CPU");
else
enginePtr = dispatcher.getSuitablePlugin(targetDevice);
sharedPlugins[targetDevice] = enginePtr;
enginePtr = dispatcher.getPluginByDevice(device_name);
sharedPlugins[device_name] = enginePtr;
#else
isInit = true;
#endif
std::vector<std::string> candidates;
std::string param_pluginPath = utils::getConfigurationParameterString("OPENCV_DNN_IE_EXTRA_PLUGIN_PATH", "");
if (!param_pluginPath.empty())
{
candidates.push_back(param_pluginPath);
}
if (targetDevice == InferenceEngine::TargetDevice::eCPU ||
targetDevice == InferenceEngine::TargetDevice::eFPGA)
if (device_name == "CPU" || device_name == "FPGA")
{
std::string suffixes[] = {"_avx2", "_sse4", ""};
bool haveFeature[] = {
@@ -448,7 +460,12 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
{
InferenceEngine::IExtensionPtr extension =
InferenceEngine::make_so_pointer<InferenceEngine::IExtension>(libName);
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
enginePtr->AddExtension(extension, 0);
#else
getCore().AddExtension(extension, "CPU");
#endif
CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << libName);
found = true;
break;
@@ -462,14 +479,24 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
// Some of networks can work without a library of extra layers.
#ifndef _WIN32
// Limit the number of CPU threads.
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
enginePtr->SetConfig({{
InferenceEngine::PluginConfigParams::KEY_CPU_THREADS_NUM, format("%d", getNumThreads()),
}}, 0);
#else
if (device_name == "CPU")
getCore().SetConfig({{
InferenceEngine::PluginConfigParams::KEY_CPU_THREADS_NUM, format("%d", getNumThreads()),
}}, device_name);
#endif
#endif
}
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
plugin = InferenceEngine::InferencePlugin(enginePtr);
netExec = plugin.LoadNetwork(net, {});
#else
netExec = getCore().LoadNetwork(net, device_name);
#endif
}
catch (const std::exception& ex)
{
@@ -479,7 +506,11 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
bool InfEngineBackendNet::isInitialized()
{
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
return (bool)enginePtr;
#else
return isInit;
#endif
}
void InfEngineBackendNet::addBlobs(const std::vector<cv::Ptr<BackendWrapper> >& ptrs)
@@ -487,7 +518,7 @@ void InfEngineBackendNet::addBlobs(const std::vector<cv::Ptr<BackendWrapper> >&
auto wrappers = infEngineWrappers(ptrs);
for (const auto& wrapper : wrappers)
{
std::string name = wrapper->dataPtr->name;
std::string name = wrapper->dataPtr->getName();
name = name.empty() ? kDefaultInpLayerName : name;
allBlobs.insert({name, wrapper->blob});
}
@@ -502,7 +533,7 @@ void InfEngineBackendNet::InfEngineReqWrapper::makePromises(const std::vector<Pt
for (int i = 0; i < outs.size(); ++i)
{
outs[i]->futureMat = outProms[i].getArrayResult();
outsNames[i] = outs[i]->dataPtr->name;
outsNames[i] = outs[i]->dataPtr->getName();
}
}
@@ -626,11 +657,12 @@ void InfEngineBackendNet::forward(const std::vector<Ptr<BackendWrapper> >& outBl
Mat infEngineBlobToMat(const InferenceEngine::Blob::Ptr& blob)
{
// NOTE: Inference Engine sizes are reversed.
std::vector<size_t> dims = blob->dims();
std::vector<int> size(dims.rbegin(), dims.rend());
std::vector<size_t> dims = blob->getTensorDesc().getDims();
std::vector<int> size(dims.begin(), dims.end());
auto precision = blob->getTensorDesc().getPrecision();
int type = -1;
switch (blob->precision())
switch (precision)
{
case InferenceEngine::Precision::FP32: type = CV_32F; break;
case InferenceEngine::Precision::U8: type = CV_8U; break;
@@ -684,7 +716,10 @@ void InfEngineBackendLayer::forward(InputArrayOfArrays inputs, OutputArrayOfArra
InferenceEngine::Blob::Ptr convertFp16(const InferenceEngine::Blob::Ptr& blob)
{
auto halfs = InferenceEngine::make_shared_blob<int16_t>(InferenceEngine::Precision::FP16, blob->layout(), blob->dims());
auto halfs = InferenceEngine::make_shared_blob<int16_t>({
InferenceEngine::Precision::FP16, blob->getTensorDesc().getDims(),
blob->getTensorDesc().getLayout()
});
halfs->allocate();
Mat floatsData(1, blob->size(), CV_32F, blob->buffer());
Mat halfsData(1, blob->size(), CV_16SC1, halfs->buffer());
@@ -731,7 +766,11 @@ void resetMyriadDevice()
{
#ifdef HAVE_INF_ENGINE
AutoLock lock(getInitializationMutex());
getSharedPlugins().erase(InferenceEngine::TargetDevice::eMYRIAD);
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
getSharedPlugins().erase("MYRIAD");
#else
getCore().UnregisterPlugin("MYRIAD");
#endif
#endif // HAVE_INF_ENGINE
}