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:
committed by
Vadim Pisarevsky
parent
80770aacd7
commit
f96f934426
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 =
|
||||
|
||||
Reference in New Issue
Block a user