1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

Update Intel's Inference Engine deep learning backend (#11587)

* Update Intel's Inference Engine deep learning backend

* Remove cpu_extension dependency

* Update Darknet accuracy tests
This commit is contained in:
Dmitry Kurtaev
2018-05-31 14:05:21 +03:00
committed by Vadim Pisarevsky
parent 80770aacd7
commit f96f934426
20 changed files with 280 additions and 113 deletions
+1 -1
View File
@@ -288,7 +288,7 @@ namespace cv {
permute_params.set("order", paramOrder);
darknet::LayerParameter lp;
std::string layer_name = cv::format("premute_%d", layer_id);
std::string layer_name = cv::format("permute_%d", layer_id);
lp.layer_name = layer_name;
lp.layer_type = permute_params.type;
lp.layerParams = permute_params;
+4 -2
View File
@@ -1182,7 +1182,9 @@ struct Net::Impl
for (it = layers.begin(); it != layers.end(); ++it)
{
LayerData &ld = it->second;
bool fused = ld.skip && ld.id != 0;
if (ld.id == 0)
continue;
bool fused = ld.skip;
Ptr<Layer> layer = ld.layerInstance;
if (!layer->supportBackend(preferableBackend))
@@ -1259,7 +1261,7 @@ struct Net::Impl
CV_Assert(!ieNode.empty());
ieNode->net = net;
if (preferableTarget == DNN_TARGET_OPENCL_FP16 && !fused)
if ((preferableTarget == DNN_TARGET_OPENCL_FP16 || preferableTarget == DNN_TARGET_MYRIAD) && !fused)
{
ieNode->layer->precision = InferenceEngine::Precision::FP16;
auto weightableLayer = std::dynamic_pointer_cast<InferenceEngine::WeightableLayer>(ieNode->layer);
@@ -117,7 +117,7 @@ public:
{
return backendId == DNN_BACKEND_DEFAULT ||
backendId == DNN_BACKEND_HALIDE && haveHalide() ||
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine() && this->type != "Sigmoid";
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine();
}
virtual Ptr<BackendNode> tryAttach(const Ptr<BackendNode>& node) CV_OVERRIDE
@@ -334,6 +334,7 @@ struct ReLUFunctor
lp.type = "ReLU";
std::shared_ptr<InferenceEngine::ReLULayer> ieLayer(new InferenceEngine::ReLULayer(lp));
ieLayer->negative_slope = slope;
ieLayer->params["negative_slope"] = format("%f", slope);
return ieLayer;
}
#endif // HAVE_INF_ENGINE
@@ -431,6 +432,8 @@ struct ReLU6Functor
std::shared_ptr<InferenceEngine::ClampLayer> ieLayer(new InferenceEngine::ClampLayer(lp));
ieLayer->min_value = minValue;
ieLayer->max_value = maxValue;
ieLayer->params["min"] = format("%f", minValue);
ieLayer->params["max"] = format("%f", maxValue);
return ieLayer;
}
#endif // HAVE_INF_ENGINE
@@ -556,8 +559,9 @@ struct SigmoidFunctor
#ifdef HAVE_INF_ENGINE
InferenceEngine::CNNLayerPtr initInfEngine(InferenceEngine::LayerParams& lp)
{
CV_Error(Error::StsNotImplemented, "Sigmoid");
return InferenceEngine::CNNLayerPtr();
lp.type = "Sigmoid";
std::shared_ptr<InferenceEngine::CNNLayer> ieLayer(new InferenceEngine::CNNLayer(lp));
return ieLayer;
}
#endif // HAVE_INF_ENGINE
+24 -9
View File
@@ -271,7 +271,7 @@ public:
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_DEFAULT ||
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine() && !_explicitSizes;
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine();
}
bool getMemoryShapes(const std::vector<MatShape> &inputs,
@@ -484,18 +484,33 @@ public:
#ifdef HAVE_INF_ENGINE
InferenceEngine::LayerParams lp;
lp.name = name;
lp.type = "PriorBox";
lp.type = _explicitSizes ? "PriorBoxClustered" : "PriorBox";
lp.precision = InferenceEngine::Precision::FP32;
std::shared_ptr<InferenceEngine::CNNLayer> ieLayer(new InferenceEngine::CNNLayer(lp));
ieLayer->params["min_size"] = format("%f", _minSize);
ieLayer->params["max_size"] = _maxSize > 0 ? format("%f", _maxSize) : "";
if (!_aspectRatios.empty())
if (_explicitSizes)
{
ieLayer->params["aspect_ratio"] = format("%f", _aspectRatios[0]);
for (int i = 1; i < _aspectRatios.size(); ++i)
ieLayer->params["aspect_ratio"] += format(",%f", _aspectRatios[i]);
CV_Assert(!_boxWidths.empty(), !_boxHeights.empty(),
_boxWidths.size() == _boxHeights.size());
ieLayer->params["width"] = format("%f", _boxWidths[0]);
ieLayer->params["height"] = format("%f", _boxHeights[0]);
for (int i = 1; i < _boxWidths.size(); ++i)
{
ieLayer->params["width"] += format(",%f", _boxWidths[i]);
ieLayer->params["height"] += format(",%f", _boxHeights[i]);
}
}
else
{
ieLayer->params["min_size"] = format("%f", _minSize);
ieLayer->params["max_size"] = _maxSize > 0 ? format("%f", _maxSize) : "";
if (!_aspectRatios.empty())
{
ieLayer->params["aspect_ratio"] = format("%f", _aspectRatios[0]);
for (int i = 1; i < _aspectRatios.size(); ++i)
ieLayer->params["aspect_ratio"] += format(",%f", _aspectRatios[i]);
}
}
ieLayer->params["flip"] = "0"; // We already flipped aspect ratios.
-5
View File
@@ -95,11 +95,6 @@ public:
return false;
}
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_DEFAULT;
}
float logistic_activate(float x) { return 1.F / (1.F + exp(-x)); }
void softmax_activate(const float* input, const int n, const float temp, float* output)
@@ -6,6 +6,7 @@
// Third party copyrights are property of their respective owners.
#include "../precomp.hpp"
#include "layers_common.hpp"
#include "../op_inf_engine.hpp"
#include <opencv2/imgproc.hpp>
namespace cv { namespace dnn {
@@ -39,6 +40,12 @@ public:
return (outputs[0][2] == inputs[0][2]) && (outputs[0][3] == inputs[0][3]);
}
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_DEFAULT ||
backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine();
}
virtual void finalize(const std::vector<Mat*>& inputs, std::vector<Mat> &outputs) CV_OVERRIDE
{
if (!outWidth && !outHeight)
@@ -75,6 +82,26 @@ public:
}
}
}
virtual Ptr<BackendNode> initInfEngine(const std::vector<Ptr<BackendWrapper> >&) CV_OVERRIDE
{
#ifdef HAVE_INF_ENGINE
InferenceEngine::LayerParams lp;
lp.name = name;
lp.type = "Resample";
lp.precision = InferenceEngine::Precision::FP32;
std::shared_ptr<InferenceEngine::CNNLayer> ieLayer(new InferenceEngine::CNNLayer(lp));
ieLayer->params["type"] = "caffe.ResampleParameter.NEAREST";
ieLayer->params["antialias"] = "0";
ieLayer->params["width"] = cv::format("%d", outWidth);
ieLayer->params["height"] = cv::format("%d", outHeight);
return Ptr<BackendNode>(new InfEngineBackendNode(ieLayer));
#endif // HAVE_INF_ENGINE
return Ptr<BackendNode>();
}
private:
int outWidth, outHeight, zoomFactor;
bool alignCorners;
+22 -25
View File
@@ -18,11 +18,6 @@ namespace cv { namespace dnn {
#ifdef HAVE_INF_ENGINE
static int infEngineVersion()
{
return std::atoi(InferenceEngine::GetInferenceEngineVersion()->buildNumber);
}
InfEngineBackendNode::InfEngineBackendNode(const InferenceEngine::CNNLayerPtr& _layer)
: BackendNode(DNN_BACKEND_INFERENCE_ENGINE), layer(_layer) {}
@@ -59,27 +54,23 @@ infEngineWrappers(const std::vector<Ptr<BackendWrapper> >& ptrs)
return wrappers;
}
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<size_t> reversedShape(&m.size[0], &m.size[0] + m.dims);
std::reverse(reversedShape.begin(), reversedShape.end());
if (infEngineVersion() > 5855)
{
InferenceEngine::Layout l = InferenceEngine::Layout::ANY;
if (m.dims == 4)
l = InferenceEngine::Layout::NCHW;
else if (m.dims == 2)
l = InferenceEngine::Layout::NC;
return InferenceEngine::DataPtr(
new InferenceEngine::Data(name, reversedShape, InferenceEngine::Precision::FP32, l)
);
}
else
{
return InferenceEngine::DataPtr(
new InferenceEngine::Data(name, reversedShape, InferenceEngine::Precision::FP32)
);
}
return InferenceEngine::DataPtr(
new InferenceEngine::Data(name, reversedShape, InferenceEngine::Precision::FP32, estimateLayout(m))
);
}
InferenceEngine::TBlob<float>::Ptr wrapToInfEngineBlob(const Mat& m, const std::vector<size_t>& shape,
@@ -108,7 +99,7 @@ InfEngineBackendWrapper::InfEngineBackendWrapper(int targetId, const cv::Mat& m)
: BackendWrapper(DNN_BACKEND_INFERENCE_ENGINE, targetId)
{
dataPtr = wrapToInfEngineDataNode(m);
blob = wrapToInfEngineBlob(m);
blob = wrapToInfEngineBlob(m, estimateLayout(m));
}
InfEngineBackendWrapper::~InfEngineBackendWrapper()
@@ -252,7 +243,8 @@ InfEngineBackendNet::getLayerByName(const char *layerName, InferenceEngine::CNNL
void InfEngineBackendNet::setTargetDevice(InferenceEngine::TargetDevice device) noexcept
{
if (device != InferenceEngine::TargetDevice::eCPU &&
device != InferenceEngine::TargetDevice::eGPU)
device != InferenceEngine::TargetDevice::eGPU &&
device != InferenceEngine::TargetDevice::eMYRIAD)
CV_Error(Error::StsNotImplemented, "");
targetDevice = device;
}
@@ -352,6 +344,11 @@ void InfEngineBackendNet::init(int targetId)
case DNN_TARGET_CPU: setTargetDevice(InferenceEngine::TargetDevice::eCPU); break;
case DNN_TARGET_OPENCL_FP16: setPrecision(InferenceEngine::Precision::FP16); // Fallback to the next.
case DNN_TARGET_OPENCL: setTargetDevice(InferenceEngine::TargetDevice::eGPU); break;
case DNN_TARGET_MYRIAD:
{
setPrecision(InferenceEngine::Precision::FP16);
setTargetDevice(InferenceEngine::TargetDevice::eMYRIAD); break;
}
default:
CV_Error(Error::StsError, format("Unknown target identifier: %d", targetId));
}
@@ -368,7 +365,7 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
InferenceEngine::ResponseDesc resp;
plugin = InferenceEngine::PluginDispatcher({""}).getSuitablePlugin(targetDevice);
if (infEngineVersion() > 5855 && targetDevice == InferenceEngine::TargetDevice::eCPU)
if (targetDevice == InferenceEngine::TargetDevice::eCPU)
{
#ifdef _WIN32
InferenceEngine::IExtensionPtr extension =