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

Merge remote-tracking branch 'upstream/3.4' into merge-3.4

Revert "documentation: avoid links to 'master' branch from 3.4 maintenance branch"
This reverts commit 9ba9358ecb.

Revert "documentation: avoid links to 'master' branch from 3.4 maintenance branch (2)"
This reverts commit f185802489.
This commit is contained in:
Alexander Alekhin
2018-06-04 19:24:09 +03:00
147 changed files with 5707 additions and 2831 deletions
+3 -3
View File
@@ -42,7 +42,7 @@
#ifndef OPENCV_DNN_HPP
#define OPENCV_DNN_HPP
// This is an umbrealla header to include into you project.
// This is an umbrella header to include into you project.
// We are free to change headers layout in dnn subfolder, so please include
// this header for future compatibility
@@ -52,10 +52,10 @@
This module contains:
- API for new layers creation, layers are building bricks of neural networks;
- set of built-in most-useful Layers;
- API to constuct and modify comprehensive neural networks from layers;
- API to construct and modify comprehensive neural networks from layers;
- functionality for loading serialized networks models from different frameworks.
Functionality of this module is designed only for forward pass computations (i. e. network testing).
Functionality of this module is designed only for forward pass computations (i.e. network testing).
A network training is in principle not supported.
@}
*/
+14 -8
View File
@@ -58,7 +58,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
You can use both API, but factory API is less convenient for native C++ programming and basically designed for use inside importers (see @ref readNetFromCaffe(), @ref readNetFromTorch(), @ref readNetFromTensorflow()).
Built-in layers partially reproduce functionality of corresponding Caffe and Torch7 layers.
In partuclar, the following layers and Caffe importer were tested to reproduce <a href="http://caffe.berkeleyvision.org/tutorial/layers.html">Caffe</a> functionality:
In particular, the following layers and Caffe importer were tested to reproduce <a href="http://caffe.berkeleyvision.org/tutorial/layers.html">Caffe</a> functionality:
- Convolution
- Deconvolution
- Pooling
@@ -108,13 +108,13 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
@f$W_{x?} \in R^{N_h \times N_x}@f$, @f$W_{h?} \in R^{N_h \times N_h}@f$, @f$b_? \in R^{N_h}@f$.
For simplicity and performance purposes we use @f$ W_x = [W_{xi}; W_{xf}; W_{xo}, W_{xg}] @f$
(i.e. @f$W_x@f$ is vertical contacentaion of @f$ W_{x?} @f$), @f$ W_x \in R^{4N_h \times N_x} @f$.
(i.e. @f$W_x@f$ is vertical concatenation of @f$ W_{x?} @f$), @f$ W_x \in R^{4N_h \times N_x} @f$.
The same for @f$ W_h = [W_{hi}; W_{hf}; W_{ho}, W_{hg}], W_h \in R^{4N_h \times N_h} @f$
and for @f$ b = [b_i; b_f, b_o, b_g]@f$, @f$b \in R^{4N_h} @f$.
@param Wh is matrix defining how previous output is transformed to internal gates (i.e. according to abovemtioned notation is @f$ W_h @f$)
@param Wx is matrix defining how current input is transformed to internal gates (i.e. according to abovemtioned notation is @f$ W_x @f$)
@param b is bias vector (i.e. according to abovemtioned notation is @f$ b @f$)
@param Wh is matrix defining how previous output is transformed to internal gates (i.e. according to above mentioned notation is @f$ W_h @f$)
@param Wx is matrix defining how current input is transformed to internal gates (i.e. according to above mentioned notation is @f$ W_x @f$)
@param b is bias vector (i.e. according to above mentioned notation is @f$ b @f$)
*/
CV_DEPRECATED virtual void setWeights(const Mat &Wh, const Mat &Wx, const Mat &b) = 0;
@@ -148,7 +148,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* If setUseTimstampsDim() is set to true then @p input[0] should has at least two dimensions with the following shape: [`T`, `N`, `[data dims]`],
* where `T` specifies number of timestamps, `N` is number of independent streams (i.e. @f$ x_{t_0 + t}^{stream} @f$ is stored inside @p input[0][t, stream, ...]).
*
* If setUseTimstampsDim() is set to fase then @p input[0] should contain single timestamp, its shape should has form [`N`, `[data dims]`] with at least one dimension.
* If setUseTimstampsDim() is set to false then @p input[0] should contain single timestamp, its shape should has form [`N`, `[data dims]`] with at least one dimension.
* (i.e. @f$ x_{t}^{stream} @f$ is stored inside @p input[0][stream, ...]).
*/
@@ -550,7 +550,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* dst(x, y, c) = \frac{ src(x, y, c) }{norm(c)}
* @f]
*
* Where `x, y` - spatial cooridnates, `c` - channel.
* Where `x, y` - spatial coordinates, `c` - channel.
*
* An every sample in the batch is normalized separately. Optionally,
* output is scaled by the trained parameters.
@@ -565,7 +565,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
};
/**
* @brief Resize input 4-dimensional blob by nearest neghbor strategy.
* @brief Resize input 4-dimensional blob by nearest neighbor strategy.
*
* Layer is used to support TensorFlow's resize_nearest_neighbor op.
*/
@@ -581,6 +581,12 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
static Ptr<ProposalLayer> create(const LayerParams& params);
};
class CV_EXPORTS CropAndResizeLayer : public Layer
{
public:
static Ptr<Layer> create(const LayerParams& params);
};
//! @}
//! @}
CV__DNN_EXPERIMENTAL_NS_END
+12 -11
View File
@@ -81,12 +81,13 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
{
DNN_TARGET_CPU,
DNN_TARGET_OPENCL,
DNN_TARGET_OPENCL_FP16
DNN_TARGET_OPENCL_FP16,
DNN_TARGET_MYRIAD
};
/** @brief This class provides all data needed to initialize layer.
*
* It includes dictionary with scalar params (which can be readed by using Dict interface),
* It includes dictionary with scalar params (which can be read by using Dict interface),
* blob params #blobs and optional meta information: #name and #type of layer instance.
*/
class CV_EXPORTS LayerParams : public Dict
@@ -137,7 +138,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* Initialize wrapper from another one. It'll wrap the same host CPU
* memory and mustn't allocate memory on device(i.e. GPU). It might
* has different shape. Use in case of CPU memory reusing for reuse
* associented memory on device too.
* associated memory on device too.
*/
BackendWrapper(const Ptr<BackendWrapper>& base, const MatShape& shape);
@@ -345,7 +346,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
/** @brief Create a network from Intel's Model Optimizer intermediate representation.
* @param[in] xml XML configuration file with network's topology.
* @param[in] bin Binary file with trained weights.
* Networks imported from Intel's Model Optimizer are lauched in Intel's Inference Engine
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
* backend.
*/
CV_WRAP static Net readFromModelOptimizer(const String& xml, const String& bin);
@@ -401,8 +402,8 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
/** @brief Connects #@p outNum output of the first layer to #@p inNum input of the second layer.
* @param outLayerId identifier of the first layer
* @param inpLayerId identifier of the second layer
* @param outNum number of the first layer output
* @param inpLayerId identifier of the second layer
* @param inpNum number of the second layer input
*/
void connect(int outLayerId, int outNum, int inpLayerId, int inpNum);
@@ -563,7 +564,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
*/
CV_WRAP int getLayersCount(const String& layerType) const;
/** @brief Computes bytes number which are requered to store
/** @brief Computes bytes number which are required to store
* all weights and intermediate blobs for model.
* @param netInputShapes vector of shapes for all net inputs.
* @param weights output parameter to store resulting bytes for weights.
@@ -583,7 +584,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
const MatShape& netInputShape,
CV_OUT size_t& weights, CV_OUT size_t& blobs) const;
/** @brief Computes bytes number which are requered to store
/** @brief Computes bytes number which are required to store
* all weights and intermediate blobs for each layer.
* @param netInputShapes vector of shapes for all net inputs.
* @param layerIds output vector to save layer IDs.
@@ -700,13 +701,13 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* * `*.pb` (TensorFlow, https://www.tensorflow.org/)
* * `*.t7` | `*.net` (Torch, http://torch.ch/)
* * `*.weights` (Darknet, https://pjreddie.com/darknet/)
* * `*.bin` (DLDT, https://software.seek.intel.com/deep-learning-deployment)
* * `*.bin` (DLDT, https://software.intel.com/openvino-toolkit)
* @param[in] config Text file contains network configuration. It could be a
* file with the following extensions:
* * `*.prototxt` (Caffe, http://caffe.berkeleyvision.org/)
* * `*.pbtxt` (TensorFlow, https://www.tensorflow.org/)
* * `*.cfg` (Darknet, https://pjreddie.com/darknet/)
* * `*.xml` (DLDT, https://software.seek.intel.com/deep-learning-deployment)
* * `*.xml` (DLDT, https://software.intel.com/openvino-toolkit)
* @param[in] framework Explicit framework name tag to determine a format.
* @returns Net object.
*
@@ -726,7 +727,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* @param[in] xml XML configuration file with network's topology.
* @param[in] bin Binary file with trained weights.
* @returns Net object.
* Networks imported from Intel's Model Optimizer are lauched in Intel's Inference Engine
* Networks imported from Intel's Model Optimizer are launched in Intel's Inference Engine
* backend.
*/
CV_EXPORTS_W Net readNetFromModelOptimizer(const String &xml, const String &bin);
@@ -744,7 +745,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* @details if @p crop is true, input image is resized so one side after resize is equal to corresponding
* dimension in @p size and another one is equal or larger. Then, crop from the center is performed.
* If @p crop is false, direct resize without cropping and preserving aspect ratio is performed.
* @returns 4-dimansional Mat with NCHW dimensions order.
* @returns 4-dimensional Mat with NCHW dimensions order.
*/
CV_EXPORTS_W Mat blobFromImage(InputArray image, double scalefactor=1.0, const Size& size = Size(),
const Scalar& mean = Scalar(), bool swapRB=true, bool crop=true);
+2 -2
View File
@@ -223,9 +223,9 @@ with tf.Session() as sess:
# By default, float16 weights are stored in repeated tensor's field called
# `half_val`. It has type int32 with leading zeros for unused bytes.
# This type is encoded by Varint that means only 7 bits are used for value
# This type is encoded by Variant that means only 7 bits are used for value
# representation but the last one is indicated the end of encoding. This way
# float16 might takes 1 or 2 or 3 bytes depends on value. To impove compression,
# float16 might takes 1 or 2 or 3 bytes depends on value. To improve compression,
# we replace all `half_val` values to `tensor_content` using only 2 bytes for everyone.
for node in graph_def.node:
if 'value' in node.attr:
+51 -17
View File
@@ -13,7 +13,7 @@
namespace opencv_test {
CV_ENUM(DNNBackend, DNN_BACKEND_DEFAULT, DNN_BACKEND_HALIDE, DNN_BACKEND_INFERENCE_ENGINE)
CV_ENUM(DNNTarget, DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16)
CV_ENUM(DNNTarget, DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16, DNN_TARGET_MYRIAD)
class DNNTestNetwork : public ::perf::TestBaseWithParam< tuple<DNNBackend, DNNTarget> >
{
@@ -29,6 +29,28 @@ public:
target = (dnn::Target)(int)get<1>(GetParam());
}
static bool checkMyriadTarget()
{
#ifndef HAVE_INF_ENGINE
return false;
#endif
cv::dnn::Net net;
cv::dnn::LayerParams lp;
net.addLayerToPrev("testLayer", "Identity", lp);
net.setPreferableBackend(cv::dnn::DNN_BACKEND_INFERENCE_ENGINE);
net.setPreferableTarget(cv::dnn::DNN_TARGET_MYRIAD);
net.setInput(cv::Mat::zeros(1, 1, CV_32FC1));
try
{
net.forward();
}
catch(...)
{
return false;
}
return true;
}
void processNet(std::string weights, std::string proto, std::string halide_scheduler,
const Mat& input, const std::string& outputLayer = "")
{
@@ -41,6 +63,13 @@ public:
throw cvtest::SkipTestException("OpenCL is not available/disabled in OpenCV");
}
}
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
{
if (!checkMyriadTarget())
{
throw SkipTestException("Myriad is not available/disabled in OpenCV");
}
}
randu(input, 0.0f, 1.0f);
@@ -87,8 +116,6 @@ public:
PERF_TEST_P_(DNNTestNetwork, AlexNet)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
throw SkipTestException("");
processNet("dnn/bvlc_alexnet.caffemodel", "dnn/bvlc_alexnet.prototxt",
"alexnet.yml", Mat(cv::Size(227, 227), CV_32FC3));
}
@@ -130,7 +157,6 @@ PERF_TEST_P_(DNNTestNetwork, ENet)
PERF_TEST_P_(DNNTestNetwork, SSD)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE) throw SkipTestException("");
processNet("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel", "dnn/ssd_vgg16.prototxt", "disabled",
Mat(cv::Size(300, 300), CV_32FC3));
}
@@ -146,18 +172,17 @@ PERF_TEST_P_(DNNTestNetwork, OpenFace)
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_Caffe)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
processNet("dnn/MobileNetSSD_deploy.caffemodel", "dnn/MobileNetSSD_deploy.prototxt", "",
Mat(cv::Size(300, 300), CV_32FC3));
}
// TODO: update MobileNet model.
PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_TensorFlow)
{
if (backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL ||
backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE)
throw SkipTestException("");
processNet("dnn/ssd_mobilenet_v1_coco.pb", "ssd_mobilenet_v1_coco.pbtxt", "",
Mat(cv::Size(300, 300), CV_32FC3));
@@ -166,7 +191,8 @@ PERF_TEST_P_(DNNTestNetwork, MobileNet_SSD_TensorFlow)
PERF_TEST_P_(DNNTestNetwork, DenseNet_121)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16)
backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL_FP16 ||
target == DNN_TARGET_MYRIAD))
throw SkipTestException("");
processNet("dnn/DenseNet_121.caffemodel", "dnn/DenseNet_121.prototxt", "",
Mat(cv::Size(224, 224), CV_32FC3));
@@ -174,21 +200,27 @@ PERF_TEST_P_(DNNTestNetwork, DenseNet_121)
PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_coco)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
processNet("dnn/openpose_pose_coco.caffemodel", "dnn/openpose_pose_coco.prototxt", "",
Mat(cv::Size(368, 368), CV_32FC3));
}
PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi.prototxt", "",
Mat(cv::Size(368, 368), CV_32FC3));
}
PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && 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
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi_faster_4_stages.prototxt", "",
@@ -197,8 +229,7 @@ PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
PERF_TEST_P_(DNNTestNetwork, opencv_face_detector)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
processNet("dnn/opencv_face_detector.caffemodel", "dnn/opencv_face_detector.prototxt", "",
Mat(cv::Size(300, 300), CV_32FC3));
@@ -207,7 +238,8 @@ PERF_TEST_P_(DNNTestNetwork, opencv_face_detector)
PERF_TEST_P_(DNNTestNetwork, Inception_v2_SSD_TensorFlow)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL) ||
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16))
throw SkipTestException("");
processNet("dnn/ssd_inception_v2_coco_2017_11_17.pb", "ssd_inception_v2_coco_2017_11_17.pbtxt", "",
Mat(cv::Size(300, 300), CV_32FC3));
@@ -215,7 +247,8 @@ PERF_TEST_P_(DNNTestNetwork, Inception_v2_SSD_TensorFlow)
PERF_TEST_P_(DNNTestNetwork, YOLOv3)
{
if (backend != DNN_BACKEND_DEFAULT)
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/dog416.png", false));
Mat inp;
@@ -232,6 +265,7 @@ const tuple<DNNBackend, DNNTarget> testCases[] = {
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD),
#endif
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL),
+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;
+8 -6
View File
@@ -541,7 +541,7 @@ public:
{
// if dst already has been allocated with total(shape) elements,
// it won't be recrreated and pointer of dst.data remains the same.
// it won't be recreated and pointer of dst.data remains the same.
dst.create(shape, use_half ? CV_16S : CV_32F);
addHost(lp, dst);
}
@@ -1132,7 +1132,7 @@ struct Net::Impl
if (layerNet != ieInpNode->net)
{
// layerNet is empty or nodes are from different graphs.
ieInpNode->net->addOutput(inpLd.name);
ieInpNode->net->addOutput(ieInpNode->layer->name);
}
}
}
@@ -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);
@@ -1518,7 +1520,7 @@ struct Net::Impl
}
}
// fuse convlution layer followed by eltwise + relu
// fuse convolution layer followed by eltwise + relu
if ( IS_DNN_OPENCL_TARGET(preferableTarget) )
{
Ptr<EltwiseLayer> nextEltwiseLayer;
@@ -1647,7 +1649,7 @@ struct Net::Impl
// the optimization #3. if there is concat layer that concatenates channels
// from the inputs together (i.e. axis == 1) then we make the inputs of
// the concat layer to write to the concatetion output buffer
// the concat layer to write to the concatenation output buffer
// (and so we eliminate the concatenation layer, because the channels
// are concatenated implicitly).
Ptr<ConcatLayer> concatLayer = ld.layerInstance.dynamicCast<ConcatLayer>();
+1 -1
View File
@@ -242,7 +242,7 @@ bool HalideScheduler::process(Ptr<BackendNode>& node)
std::map<std::string, Halide::Func> funcsMap; // Scheduled functions.
// For every function, from top to bottom, we try to find a scheduling node.
// Scheduling is successful (return true) if for the first function (top)
// node is respresented.
// node is represented.
CV_Assert(!node.empty());
std::vector<Halide::Func>& funcs = node.dynamicCast<HalideBackendNode>()->funcs;
for (int i = funcs.size() - 1; i >= 0; --i)
+1
View File
@@ -84,6 +84,7 @@ void initializeLayerFactory()
CV_DNN_REGISTER_LAYER_CLASS(Reshape, ReshapeLayer);
CV_DNN_REGISTER_LAYER_CLASS(Flatten, FlattenLayer);
CV_DNN_REGISTER_LAYER_CLASS(ResizeNearestNeighbor, ResizeNearestNeighborLayer);
CV_DNN_REGISTER_LAYER_CLASS(CropAndResize, CropAndResizeLayer);
CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
CV_DNN_REGISTER_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
+2 -3
View File
@@ -676,7 +676,7 @@ public:
int j0 = std::max(0, (-in_j + dilation_w-1)/dilation_w);
int j1 = std::min(kernel_w, (width - in_j + dilation_w-1)/dilation_w);
// here some non-continous sub-row of the row will not be
// here some non-continuous sub-row of the row will not be
// filled from the tensor; we need to make sure that the uncovered
// elements are explicitly set to 0's. the easiest way is to
// set all the elements to 0's before the loop.
@@ -966,8 +966,7 @@ public:
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget) &&
OCL_PERFORMANCE_CHECK(ocl::Device::getDefault().isIntel()),
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
forward_ocl(inputs_arr, outputs_arr, internals_arr))
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
@@ -0,0 +1,108 @@
#include "../precomp.hpp"
#include "layers_common.hpp"
namespace cv { namespace dnn {
class CropAndResizeLayerImpl CV_FINAL : public CropAndResizeLayer
{
public:
CropAndResizeLayerImpl(const LayerParams& params)
{
CV_Assert(params.has("width"), params.has("height"));
outWidth = params.get<float>("width");
outHeight = params.get<float>("height");
}
bool getMemoryShapes(const std::vector<MatShape> &inputs,
const int requiredOutputs,
std::vector<MatShape> &outputs,
std::vector<MatShape> &internals) const CV_OVERRIDE
{
CV_Assert(inputs.size() == 2, inputs[0].size() == 4);
if (inputs[0][0] != 1)
CV_Error(Error::StsNotImplemented, "");
outputs.resize(1, MatShape(4));
outputs[0][0] = inputs[1][2]; // Number of bounding boxes.
outputs[0][1] = inputs[0][1]; // Number of channels.
outputs[0][2] = outHeight;
outputs[0][3] = outWidth;
return false;
}
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
{
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
}
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals) CV_OVERRIDE
{
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
Mat& inp = *inputs[0];
Mat& out = outputs[0];
Mat boxes = inputs[1]->reshape(1, inputs[1]->total() / 7);
const int numChannels = inp.size[1];
const int inpHeight = inp.size[2];
const int inpWidth = inp.size[3];
const int inpSpatialSize = inpHeight * inpWidth;
const int outSpatialSize = outHeight * outWidth;
CV_Assert(inp.isContinuous(), out.isContinuous());
for (int b = 0; b < boxes.rows; ++b)
{
float* outDataBox = out.ptr<float>(b);
float left = boxes.at<float>(b, 3);
float top = boxes.at<float>(b, 4);
float right = boxes.at<float>(b, 5);
float bottom = boxes.at<float>(b, 6);
float boxWidth = right - left;
float boxHeight = bottom - top;
float heightScale = boxHeight * static_cast<float>(inpHeight - 1) / (outHeight - 1);
float widthScale = boxWidth * static_cast<float>(inpWidth - 1) / (outWidth - 1);
for (int y = 0; y < outHeight; ++y)
{
float input_y = top * (inpHeight - 1) + y * heightScale;
int y0 = static_cast<int>(input_y);
const float* inpData_row0 = (float*)inp.data + y0 * inpWidth;
const float* inpData_row1 = (y0 + 1 < inpHeight) ? (inpData_row0 + inpWidth) : inpData_row0;
for (int x = 0; x < outWidth; ++x)
{
float input_x = left * (inpWidth - 1) + x * widthScale;
int x0 = static_cast<int>(input_x);
int x1 = std::min(x0 + 1, inpWidth - 1);
float* outData = outDataBox + y * outWidth + x;
const float* inpData_row0_c = inpData_row0;
const float* inpData_row1_c = inpData_row1;
for (int c = 0; c < numChannels; ++c)
{
*outData = inpData_row0_c[x0] +
(input_y - y0) * (inpData_row1_c[x0] - inpData_row0_c[x0]) +
(input_x - x0) * (inpData_row0_c[x1] - inpData_row0_c[x0] +
(input_y - y0) * (inpData_row1_c[x1] - inpData_row0_c[x1] - inpData_row1_c[x0] + inpData_row0_c[x0]));
inpData_row0_c += inpSpatialSize;
inpData_row1_c += inpSpatialSize;
outData += outSpatialSize;
}
}
}
}
}
private:
int outWidth, outHeight;
};
Ptr<Layer> CropAndResizeLayer::create(const LayerParams& params)
{
return Ptr<CropAndResizeLayer>(new CropAndResizeLayerImpl(params));
}
} // namespace dnn
} // namespace cv
@@ -110,7 +110,7 @@ public:
float _nmsThreshold;
int _topK;
// Whenever predicted bounding boxes are respresented in YXHW instead of XYWH layout.
// Whenever predicted bounding boxes are represented in YXHW instead of XYWH layout.
bool _locPredTransposed;
// It's true whenever predicted bounding boxes and proposals are normalized to [0, 1].
bool _bboxesNormalized;
@@ -208,8 +208,9 @@ public:
CV_Assert(inputs[0][0] == inputs[1][0]);
int numPriors = inputs[2][2] / 4;
CV_Assert((numPriors * _numLocClasses * 4) == inputs[0][1]);
CV_Assert(int(numPriors * _numClasses) == inputs[1][1]);
CV_Assert((numPriors * _numLocClasses * 4) == total(inputs[0], 1));
CV_Assert(int(numPriors * _numClasses) == total(inputs[1], 1));
CV_Assert(inputs[2][1] == 1 + (int)(!_varianceEncodedInTarget));
// num() and channels() are 1.
// Since the number of bboxes to be kept is unknown before nms, we manually
@@ -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
@@ -176,8 +176,7 @@ public:
{
CV_TRACE_FUNCTION();
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(this->preferableTarget) &&
OCL_PERFORMANCE_CHECK(ocl::Device::getDefault().isIntel()),
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(this->preferableTarget),
func.applyOCL(inputs_arr, outputs_arr, internals_arr))
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
@@ -335,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
@@ -432,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
@@ -557,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
+1 -1
View File
@@ -79,7 +79,7 @@ public:
else if (operation == "max")
op = MAX;
else
CV_Error(cv::Error::StsBadArg, "Unknown operaticon type \"" + operation + "\"");
CV_Error(cv::Error::StsBadArg, "Unknown operation type \"" + operation + "\"");
}
if (params.has("coeff"))
+39 -12
View File
@@ -73,7 +73,7 @@ public:
virtual bool tryFuse(Ptr<Layer>& top) CV_OVERRIDE
{
if (preferableTarget == DNN_TARGET_OPENCL && !fuse_batch_norm)
if (!fuse_batch_norm)
{
top->getScaleShift(scale, shift);
fuse_batch_norm = !scale.empty() || !shift.empty();
@@ -252,8 +252,7 @@ public:
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget) &&
OCL_PERFORMANCE_CHECK(ocl::Device::getDefault().isIntel()),
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
forward_ocl(inputs_arr, outputs_arr, internals_arr))
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
@@ -274,25 +273,53 @@ public:
for( i = 0; i < splitDim; i++ )
newRows *= inpBlob.size[i];
if (inpBlob.total() == newRows)
{
// MVN is applied to single values at an every row.
outBlob.setTo(0);
return;
}
Mat inpMat = inpBlob.reshape(1, newRows);
Mat outMat = outBlob.reshape(1, newRows);
if ( inpBlob.total() == newRows )
{
// MVN is applied to single values at an every row.
if (shift.empty())
{
outBlob.setTo(0);
}
else
{
for ( i = 0; i < newRows; i++ )
{
outMat.row(i).setTo(((float*)shift.data)[i]);
}
}
return;
}
Scalar mean, dev;
for ( i = 0; i < newRows; i++)
{
Mat inpRow = inpMat.row(i);
Mat outRow = outMat.row(i);
float weight = 1.f;
float bias = 0.f;
if (fuse_batch_norm)
{
weight = i < scale.cols ? ((float*)scale.data)[i] : weight;
bias = i < shift.cols ? ((float*)shift.data)[i] : bias;
}
cv::meanStdDev(inpRow, mean, (normVariance) ? dev : noArray());
double alpha = (normVariance) ? 1/(eps + dev[0]) : 1;
inpRow.convertTo(outRow, outRow.type(), alpha, -mean[0] * alpha);
double normalizationScale = 1.0;
double normalizationShift = 0.0;
if (fuse_batch_norm)
{
normalizationScale = alpha * weight;
normalizationShift = -mean[0] * normalizationScale + bias;
}
else
{
normalizationScale = alpha;
normalizationShift = -mean[0] * alpha;
}
inpRow.convertTo(outRow, outRow.type(), normalizationScale, normalizationShift);
}
}
}
+1 -2
View File
@@ -191,8 +191,7 @@ public:
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget) &&
OCL_PERFORMANCE_CHECK(ocl::Device::getDefault().isIntel()),
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
forward_ocl(inputs_arr, outputs_arr, internals_arr))
Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
+27 -12
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,
@@ -366,7 +366,7 @@ public:
kernel.set(13, (int)_imageWidth);
kernel.run(1, &nthreads, NULL, false);
// clip the prior's coordidate such that it is within [0, 1]
// clip the prior's coordinate such that it is within [0, 1]
if (_clip)
{
Mat mat = outputs[0].getMat(ACCESS_READ);
@@ -442,7 +442,7 @@ public:
}
}
}
// clip the prior's coordidate such that it is within [0, 1]
// clip the prior's coordinate such that it is within [0, 1]
if (_clip)
{
int _outChannelSize = _layerHeight * _layerWidth * _numPriors * 4;
@@ -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.
@@ -550,7 +565,7 @@ private:
std::vector<float> _variance;
std::vector<float> _offsetsX;
std::vector<float> _offsetsY;
// Precomputed final widhts and heights based on aspect ratios or explicit sizes.
// Precomputed final widths and heights based on aspect ratios or explicit sizes.
std::vector<float> _boxWidths;
std::vector<float> _boxHeights;
-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;
@@ -709,7 +709,7 @@ bool OCL4DNNConvSpatial<Dtype>::swizzleWeight(const UMat &weight,
return false;
}
} else {
// assumption: kernel dimesion is 2
// assumption: kernel dimension is 2
Mat weightMat = weight.getMat(ACCESS_READ);
Dtype* cpu_weight = (Dtype *)weightMat.ptr<float>();
Mat swizzledWeightMat;
+44 -41
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;
}
@@ -296,7 +288,7 @@ void InfEngineBackendNet::init(int targetId)
}
for (const InferenceEngine::DataPtr& out : l->outData)
{
// TODO: Replace to uniquness assertion.
// TODO: Replace to uniqueness assertion.
if (internalOutputs.find(out->name) == internalOutputs.end())
internalOutputs[out->name] = out;
}
@@ -313,7 +305,7 @@ void InfEngineBackendNet::init(int targetId)
// Add all outputs.
for (const InferenceEngine::DataPtr& out : l->outData)
{
// TODO: Replace to uniquness assertion.
// TODO: Replace to uniqueness assertion.
if (unconnectedOuts.find(out->name) == unconnectedOuts.end())
unconnectedOuts[out->name] = out;
}
@@ -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));
}
@@ -364,11 +361,21 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
{
CV_Assert(!isInitialized());
InferenceEngine::StatusCode status;
InferenceEngine::ResponseDesc resp;
static std::map<std::string, InferenceEngine::InferenceEnginePluginPtr> sharedPlugins;
std::string deviceName = InferenceEngine::getDeviceName(targetDevice);
auto pluginIt = sharedPlugins.find(deviceName);
if (pluginIt != sharedPlugins.end())
{
enginePtr = pluginIt->second;
}
else
{
enginePtr = InferenceEngine::PluginDispatcher({""}).getSuitablePlugin(targetDevice);
sharedPlugins[deviceName] = enginePtr;
}
plugin = InferenceEngine::InferencePlugin(enginePtr);
plugin = InferenceEngine::PluginDispatcher({""}).getSuitablePlugin(targetDevice);
if (infEngineVersion() > 5855 && targetDevice == InferenceEngine::TargetDevice::eCPU)
if (targetDevice == InferenceEngine::TargetDevice::eCPU)
{
#ifdef _WIN32
InferenceEngine::IExtensionPtr extension =
@@ -377,18 +384,17 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
InferenceEngine::IExtensionPtr extension =
InferenceEngine::make_so_pointer<InferenceEngine::IExtension>("libcpu_extension.so");
#endif // _WIN32
status = plugin->AddExtension(extension, &resp);
if (status != InferenceEngine::StatusCode::OK)
CV_Error(Error::StsAssert, resp.msg);
plugin.AddExtension(extension);
}
status = plugin->LoadNetwork(net, &resp);
if (status != InferenceEngine::StatusCode::OK)
CV_Error(Error::StsAssert, resp.msg);
netExec = plugin.LoadNetwork(net, {});
infRequest = netExec.CreateInferRequest();
infRequest.SetInput(inpBlobs);
infRequest.SetOutput(outBlobs);
}
bool InfEngineBackendNet::isInitialized()
{
return (bool)plugin;
return (bool)enginePtr;
}
void InfEngineBackendNet::addBlobs(const std::vector<Ptr<BackendWrapper> >& ptrs)
@@ -402,10 +408,7 @@ void InfEngineBackendNet::addBlobs(const std::vector<Ptr<BackendWrapper> >& ptrs
void InfEngineBackendNet::forward()
{
InferenceEngine::ResponseDesc resp;
InferenceEngine::StatusCode status = plugin->Infer(inpBlobs, outBlobs, &resp);
if (status != InferenceEngine::StatusCode::OK)
CV_Error(Error::StsAssert, resp.msg);
infRequest.Infer();
}
Mat infEngineBlobToMat(const InferenceEngine::Blob::Ptr& blob)
+4 -1
View File
@@ -89,7 +89,10 @@ private:
InferenceEngine::BlobMap allBlobs;
InferenceEngine::TargetDevice targetDevice;
InferenceEngine::Precision precision;
InferenceEngine::InferenceEnginePluginPtr plugin;
InferenceEngine::InferenceEnginePluginPtr enginePtr;
InferenceEngine::InferencePlugin plugin;
InferenceEngine::ExecutableNetwork netExec;
InferenceEngine::InferRequest infRequest;
void initPlugin(InferenceEngine::ICNNNetwork& net);
};
+10 -5
View File
@@ -89,7 +89,8 @@ __kernel void CALC_MEAN(__global const Dtype* src,
Dtype mean_val = mean[x];
vec_type src_vec = load(src, index);
vec_type dst_vec = native_powr(src_vec - (vec_type)mean_val, 2);
vec_type dst_vec = src_vec - (vec_type)mean_val;
dst_vec = dst_vec * dst_vec;
store(dst_vec, dst, index);
}
@@ -197,10 +198,14 @@ __kernel void MEAN_FUSE(__global const T * A,
const T4 a2 = vload4(i, src0_read + 2 * A_col_size);
const T4 a3 = vload4(i, src0_read + 3 * A_col_size);
dot0 = native_powr(convert_float4(a0) - (Dtype4)sum.x, 2);
dot1 = native_powr(convert_float4(a1) - (Dtype4)sum.y, 2);
dot2 = native_powr(convert_float4(a2) - (Dtype4)sum.z, 2);
dot3 = native_powr(convert_float4(a3) - (Dtype4)sum.w, 2);
dot0 = convert_float4(a0) - (Dtype4)sum.x;
dot1 = convert_float4(a1) - (Dtype4)sum.y;
dot2 = convert_float4(a2) - (Dtype4)sum.z;
dot3 = convert_float4(a3) - (Dtype4)sum.w;
dot0 = dot0 * dot0;
dot1 = dot1 * dot1;
dot2 = dot2 * dot2;
dot3 = dot3 * dot3;
vstore4(dot0, i, dst0_read);
vstore4(dot1, i, dst0_read + A_col_size);
+1 -1
View File
@@ -86,7 +86,7 @@ message NodeDef {
// | ( ("gpu" | "cpu") ":" ([1-9][0-9]* | "*") )
//
// Valid values for this string include:
// * "@other/node" (colocate with "other/node")
// * "@other/node" (collocate with "other/node")
// * "/job:worker/replica:0/task:1/gpu:3" (full specification)
// * "/job:worker/gpu:3" (partial specification)
// * "" (no specification)
@@ -5,6 +5,8 @@
// Copyright (C) 2018, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "../precomp.hpp"
#ifdef HAVE_PROTOBUF
#include "tf_graph_simplifier.hpp"
+36 -4
View File
@@ -644,8 +644,9 @@ void TFImporter::populateNet(Net dstNet)
CV_Assert(layer.input_size() == 3);
DictValue dilation = parseDims(getConstBlob(layer, value_id, 1));
CV_Assert(dilation.size() == 2 && dilation.get<int>(0) == dilation.get<int>(1));
layerParams.set("dilation", dilation.get<int>(0));
CV_Assert(dilation.size() == 2);
layerParams.set("dilation_h", dilation.get<int>(0));
layerParams.set("dilation_w", dilation.get<int>(1));
Mat paddings;
parseTensor<int>(getConstBlob(layer, value_id, 2), paddings);
@@ -655,6 +656,10 @@ void TFImporter::populateNet(Net dstNet)
layerParams.set("pad_w", paddings.at<float>(2));
StrIntVector next_layers = getNextLayers(net, name, "Conv2D");
if (next_layers.empty())
{
next_layers = getNextLayers(net, name, "DepthwiseConv2dNative");
}
CV_Assert(next_layers.size() == 1);
layer = net.node(next_layers[0].second);
layers_to_ignore.insert(next_layers[0].first);
@@ -1089,9 +1094,9 @@ void TFImporter::populateNet(Net dstNet)
CV_Assert(!begins.empty(), !sizes.empty(), begins.type() == CV_32SC1,
sizes.type() == CV_32SC1);
if (begins.total() == 4)
if (begins.total() == 4 && data_layouts[name] == DATA_LAYOUT_NHWC)
{
// Perhabs, we have an NHWC order. Swap it to NCHW.
// Swap NHWC parameters' order to NCHW.
std::swap(*begins.ptr<int32_t>(0, 2), *begins.ptr<int32_t>(0, 3));
std::swap(*begins.ptr<int32_t>(0, 1), *begins.ptr<int32_t>(0, 2));
std::swap(*sizes.ptr<int32_t>(0, 2), *sizes.ptr<int32_t>(0, 3));
@@ -1171,6 +1176,9 @@ void TFImporter::populateNet(Net dstNet)
layers_to_ignore.insert(next_layers[0].first);
}
if (hasLayerAttr(layer, "axis"))
layerParams.set("axis", getLayerAttr(layer, "axis").i());
id = dstNet.addLayer(name, "Scale", layerParams);
}
layer_id[name] = id;
@@ -1542,6 +1550,10 @@ void TFImporter::populateNet(Net dstNet)
layerParams.set("confidence_threshold", getLayerAttr(layer, "confidence_threshold").f());
if (hasLayerAttr(layer, "loc_pred_transposed"))
layerParams.set("loc_pred_transposed", getLayerAttr(layer, "loc_pred_transposed").b());
if (hasLayerAttr(layer, "clip"))
layerParams.set("clip", getLayerAttr(layer, "clip").b());
if (hasLayerAttr(layer, "variance_encoded_in_target"))
layerParams.set("variance_encoded_in_target", getLayerAttr(layer, "variance_encoded_in_target").b());
int id = dstNet.addLayer(name, "DetectionOutput", layerParams);
layer_id[name] = id;
@@ -1558,6 +1570,26 @@ void TFImporter::populateNet(Net dstNet)
layer_id[name] = id;
connectToAllBlobs(layer_id, dstNet, parsePin(layer.input(0)), id, layer.input_size());
}
else if (type == "CropAndResize")
{
// op: "CropAndResize"
// input: "input"
// input: "boxes"
// input: "sizes"
CV_Assert(layer.input_size() == 3);
Mat cropSize = getTensorContent(getConstBlob(layer, value_id, 2));
CV_Assert(cropSize.type() == CV_32SC1, cropSize.total() == 2);
layerParams.set("height", cropSize.at<int>(0));
layerParams.set("width", cropSize.at<int>(1));
int id = dstNet.addLayer(name, "CropAndResize", layerParams);
layer_id[name] = id;
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
connect(layer_id, dstNet, parsePin(layer.input(1)), id, 1);
}
else if (type == "Mean")
{
Mat indices = getTensorContent(getConstBlob(layer, value_id, 1));
+3 -3
View File
@@ -311,11 +311,11 @@ struct TorchImporter
int numModules = curModule->modules.size();
readTorchObject(index);
if (tensors.count(index)) //tensor was readed
if (tensors.count(index)) //tensor was read
{
tensorParams.insert(std::make_pair(key, std::make_pair(index, tensors[index])));
}
else if (storages.count(index)) //storage was readed
else if (storages.count(index)) //storage was read
{
Mat &matStorage = storages[index];
Mat matCasted;
@@ -399,7 +399,7 @@ struct TorchImporter
size_t requireElems = (size_t)offset + (size_t)steps[0] * (size_t)sizes[0];
size_t storageElems = storages[indexStorage].total();
if (requireElems > storageElems)
CV_Error(Error::StsBadSize, "Storage has insufficent number of elemements for requested Tensor");
CV_Error(Error::StsBadSize, "Storage has insufficient number of elements for requested Tensor");
//convert sizes
AutoBuffer<int, 4> isizes(ndims);
+57 -26
View File
@@ -49,7 +49,14 @@ public:
throw SkipTestException("OpenCL is not available/disabled in OpenCV");
}
}
if (target == DNN_TARGET_OPENCL_FP16)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
{
if (!checkMyriadTarget())
{
throw SkipTestException("Myriad is not available/disabled in OpenCV");
}
}
if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)
{
l1 = l1 == 0.0 ? 4e-3 : l1;
lInf = lInf == 0.0 ? 2e-2 : lInf;
@@ -80,10 +87,7 @@ public:
}
Mat out = net.forward(outputLayer).clone();
if (outputLayer == "detection_out")
normAssertDetections(outDefault, out, "First run", 0.2, l1, lInf);
else
normAssert(outDefault, out, "First run", l1, lInf);
check(outDefault, out, outputLayer, l1, lInf, "First run");
// Test 2: change input.
float* inpData = (float*)inp.data;
@@ -97,18 +101,33 @@ public:
net.setInput(inp);
outDefault = netDefault.forward(outputLayer).clone();
out = net.forward(outputLayer).clone();
check(outDefault, out, outputLayer, l1, lInf, "Second run");
}
void check(Mat& ref, Mat& out, const std::string& outputLayer, double l1, double lInf, const char* msg)
{
if (outputLayer == "detection_out")
normAssertDetections(outDefault, out, "Second run", 0.2, l1, lInf);
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE)
{
// Inference Engine produces detections terminated by a row which starts from -1.
out = out.reshape(1, out.total() / 7);
int numDetections = 0;
while (numDetections < out.rows && out.at<float>(numDetections, 0) != -1)
{
numDetections += 1;
}
out = out.rowRange(0, numDetections);
}
normAssertDetections(ref, out, msg, 0.2, l1, lInf);
}
else
normAssert(outDefault, out, "Second run", l1, lInf);
normAssert(ref, out, msg, l1, lInf);
}
};
TEST_P(DNNTestNetwork, AlexNet)
{
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
throw SkipTestException("");
processNet("dnn/bvlc_alexnet.caffemodel", "dnn/bvlc_alexnet.prototxt",
Size(227, 227), "prob",
target == DNN_TARGET_OPENCL ? "dnn/halide_scheduler_opencl_alexnet.yml" :
@@ -158,8 +177,7 @@ TEST_P(DNNTestNetwork, ENet)
TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
@@ -170,10 +188,11 @@ TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe)
inp, "detection_out", "", l1, lInf);
}
// TODO: update MobileNet model.
TEST_P(DNNTestNetwork, MobileNet_SSD_TensorFlow)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
backend == DNN_BACKEND_INFERENCE_ENGINE)
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
@@ -185,31 +204,38 @@ TEST_P(DNNTestNetwork, MobileNet_SSD_TensorFlow)
TEST_P(DNNTestNetwork, SSD_VGG16)
{
if ((backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL_FP16) ||
(backend == DNN_BACKEND_HALIDE && target == DNN_TARGET_CPU) ||
(backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU))
if (backend == DNN_BACKEND_HALIDE && target == DNN_TARGET_CPU)
throw SkipTestException("");
double scoreThreshold = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.0252 : 0.0;
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f, Size(300, 300), Scalar(), false);
processNet("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel",
"dnn/ssd_vgg16.prototxt", Size(300, 300), "detection_out");
"dnn/ssd_vgg16.prototxt", inp, "detection_out", "", scoreThreshold);
}
TEST_P(DNNTestNetwork, OpenPose_pose_coco)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
processNet("dnn/openpose_pose_coco.caffemodel", "dnn/openpose_pose_coco.prototxt",
Size(368, 368));
}
TEST_P(DNNTestNetwork, OpenPose_pose_mpi)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
throw SkipTestException("");
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi.prototxt",
Size(368, 368));
}
TEST_P(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
{
if (backend == DNN_BACKEND_HALIDE) throw SkipTestException("");
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && 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
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi_faster_4_stages.prototxt",
@@ -226,11 +252,13 @@ TEST_P(DNNTestNetwork, OpenFace)
TEST_P(DNNTestNetwork, opencv_face_detector)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
Size inpSize;
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
inpSize = Size(300, 300);
Mat img = imread(findDataFile("gpu/lbpcascade/er.png", false));
Mat inp = blobFromImage(img, 1.0, Size(), Scalar(104.0, 177.0, 123.0), false, false);
Mat inp = blobFromImage(img, 1.0, inpSize, Scalar(104.0, 177.0, 123.0), false, false);
processNet("dnn/opencv_face_detector.caffemodel", "dnn/opencv_face_detector.prototxt",
inp, "detection_out");
}
@@ -238,12 +266,13 @@ TEST_P(DNNTestNetwork, opencv_face_detector)
TEST_P(DNNTestNetwork, Inception_v2_SSD_TensorFlow)
{
if (backend == DNN_BACKEND_HALIDE ||
backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL) ||
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16))
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
float l1 = (backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL_FP16) ? 0.008 : 0.0;
float lInf = (backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL_FP16) ? 0.07 : 0.0;
float l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.008 : 0.0;
float lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.07 : 0.0;
processNet("dnn/ssd_inception_v2_coco_2017_11_17.pb", "dnn/ssd_inception_v2_coco_2017_11_17.pbtxt",
inp, "detection_out", "", l1, lInf);
}
@@ -252,7 +281,8 @@ TEST_P(DNNTestNetwork, DenseNet_121)
{
if ((backend == DNN_BACKEND_HALIDE) ||
(backend == DNN_BACKEND_DEFAULT && target == DNN_TARGET_OPENCL_FP16) ||
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16))
(backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL_FP16 ||
target == DNN_TARGET_MYRIAD)))
throw SkipTestException("");
processNet("dnn/DenseNet_121.caffemodel", "dnn/DenseNet_121.prototxt", Size(224, 224), "", "caffe");
}
@@ -266,6 +296,7 @@ const tuple<DNNBackend, DNNTarget> testCases[] = {
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD),
#endif
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL_FP16)
+22
View File
@@ -147,6 +147,28 @@ inline void normAssertDetections(cv::Mat ref, cv::Mat out, const char *comment =
testBoxes, comment, confThreshold, scores_diff, boxes_iou_diff);
}
inline bool checkMyriadTarget()
{
#ifndef HAVE_INF_ENGINE
return false;
#endif
cv::dnn::Net net;
cv::dnn::LayerParams lp;
net.addLayerToPrev("testLayer", "Identity", lp);
net.setPreferableBackend(cv::dnn::DNN_BACKEND_INFERENCE_ENGINE);
net.setPreferableTarget(cv::dnn::DNN_TARGET_MYRIAD);
net.setInput(cv::Mat::zeros(1, 1, CV_32FC1));
try
{
net.forward();
}
catch(...)
{
return false;
}
return true;
}
inline bool readFileInMemory(const std::string& filename, std::string& content)
{
std::ios::openmode mode = std::ios::in | std::ios::binary;
+55 -12
View File
@@ -71,13 +71,31 @@ static void testDarknetModel(const std::string& cfg, const std::string& weights,
const std::vector<int>& refClassIds,
const std::vector<float>& refConfidences,
const std::vector<Rect2d>& refBoxes,
int targetId, float confThreshold = 0.24)
int backendId, int targetId, float scoreDiff = 0.0,
float iouDiff = 0.0, float confThreshold = 0.24)
{
if (backendId == DNN_BACKEND_DEFAULT && targetId == DNN_TARGET_OPENCL)
{
#ifdef HAVE_OPENCL
if (!cv::ocl::useOpenCL())
#endif
{
throw SkipTestException("OpenCL is not available/disabled in OpenCV");
}
}
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD)
{
if (!checkMyriadTarget())
{
throw SkipTestException("Myriad is not available/disabled in OpenCV");
}
}
Mat sample = imread(_tf("dog416.png"));
Mat inp = blobFromImage(sample, 1.0/255, Size(416, 416), Scalar(), true, false);
Net net = readNet(findDataFile("dnn/" + cfg, false),
findDataFile("dnn/" + weights, false));
net.setPreferableBackend(backendId);
net.setPreferableTarget(targetId);
net.setInput(inp);
std::vector<Mat> outs;
@@ -108,42 +126,53 @@ static void testDarknetModel(const std::string& cfg, const std::string& weights,
}
}
normAssertDetections(refClassIds, refConfidences, refBoxes, classIds,
confidences, boxes, "", confThreshold, 8e-5, 3e-5);
confidences, boxes, "", confThreshold, scoreDiff, iouDiff);
}
typedef testing::TestWithParam<DNNTarget> Test_Darknet_nets;
typedef testing::TestWithParam<tuple<DNNBackend, DNNTarget> > Test_Darknet_nets;
TEST_P(Test_Darknet_nets, YoloVoc)
{
int targetId = GetParam();
int backendId = get<0>(GetParam());
int targetId = get<1>(GetParam());
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD)
throw SkipTestException("");
std::vector<cv::String> outNames(1, "detection_out");
std::vector<int> classIds(3);
std::vector<float> confidences(3);
std::vector<Rect2d> boxes(3);
classIds[0] = 6; confidences[0] = 0.750469f; boxes[0] = Rect2d(0.577374, 0.127391, 0.325575, 0.173418); // a car
classIds[1] = 1; confidences[1] = 0.780879f; boxes[1] = Rect2d(0.270762, 0.264102, 0.461713, 0.48131); // a bycicle
classIds[1] = 1; confidences[1] = 0.780879f; boxes[1] = Rect2d(0.270762, 0.264102, 0.461713, 0.48131); // a bicycle
classIds[2] = 11; confidences[2] = 0.901615f; boxes[2] = Rect2d(0.1386, 0.338509, 0.282737, 0.60028); // a dog
double scoreDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 7e-3 : 8e-5;
double iouDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 0.013 : 3e-5;
testDarknetModel("yolo-voc.cfg", "yolo-voc.weights", outNames,
classIds, confidences, boxes, targetId);
classIds, confidences, boxes, backendId, targetId, scoreDiff, iouDiff);
}
TEST_P(Test_Darknet_nets, TinyYoloVoc)
{
int targetId = GetParam();
int backendId = get<0>(GetParam());
int targetId = get<1>(GetParam());
std::vector<cv::String> outNames(1, "detection_out");
std::vector<int> classIds(2);
std::vector<float> confidences(2);
std::vector<Rect2d> boxes(2);
classIds[0] = 6; confidences[0] = 0.761967f; boxes[0] = Rect2d(0.579042, 0.159161, 0.31544, 0.160779); // a car
classIds[1] = 11; confidences[1] = 0.780595f; boxes[1] = Rect2d(0.129696, 0.386467, 0.315579, 0.534527); // a dog
double scoreDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 8e-3 : 8e-5;
double iouDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 8e-3 : 3e-5;
testDarknetModel("tiny-yolo-voc.cfg", "tiny-yolo-voc.weights", outNames,
classIds, confidences, boxes, targetId);
classIds, confidences, boxes, backendId, targetId, scoreDiff, iouDiff);
}
TEST_P(Test_Darknet_nets, YOLOv3)
{
int targetId = GetParam();
int backendId = get<0>(GetParam());
int targetId = get<1>(GetParam());
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD)
throw SkipTestException("");
std::vector<cv::String> outNames(3);
outNames[0] = "yolo_82";
outNames[1] = "yolo_94";
@@ -153,13 +182,27 @@ TEST_P(Test_Darknet_nets, YOLOv3)
std::vector<float> confidences(3);
std::vector<Rect2d> boxes(3);
classIds[0] = 7; confidences[0] = 0.952983f; boxes[0] = Rect2d(0.614622, 0.150257, 0.286747, 0.138994); // a truck
classIds[1] = 1; confidences[1] = 0.987908f; boxes[1] = Rect2d(0.150913, 0.221933, 0.591342, 0.524327); // a bycicle
classIds[1] = 1; confidences[1] = 0.987908f; boxes[1] = Rect2d(0.150913, 0.221933, 0.591342, 0.524327); // a bicycle
classIds[2] = 16; confidences[2] = 0.998836f; boxes[2] = Rect2d(0.160024, 0.389964, 0.257861, 0.553752); // a dog (COCO)
double scoreDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 4e-3 : 8e-5;
double iouDiff = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 0.011 : 3e-5;
testDarknetModel("yolov3.cfg", "yolov3.weights", outNames,
classIds, confidences, boxes, targetId);
classIds, confidences, boxes, backendId, targetId, scoreDiff, iouDiff);
}
INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_nets, availableDnnTargets());
const tuple<DNNBackend, DNNTarget> testCases[] = {
#ifdef HAVE_INF_ENGINE
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_OPENCL_FP16),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_INFERENCE_ENGINE, DNN_TARGET_MYRIAD),
#endif
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_CPU),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL),
tuple<DNNBackend, DNNTarget>(DNN_BACKEND_DEFAULT, DNN_TARGET_OPENCL_FP16)
};
INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_nets, testing::ValuesIn(testCases));
static void testDarknetLayer(const std::string& name, bool hasWeights = false)
{
+78
View File
@@ -834,6 +834,84 @@ TEST(Test_DLDT, two_inputs)
normAssert(out, firstInp + secondInp);
}
class UnsupportedLayer : public Layer
{
public:
UnsupportedLayer(const LayerParams &params) {}
static Ptr<Layer> create(const LayerParams& params)
{
return Ptr<Layer>(new UnsupportedLayer(params));
}
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_DEFAULT;
}
virtual void forward(std::vector<cv::Mat*> &inputs, std::vector<cv::Mat> &outputs, std::vector<cv::Mat> &internals) CV_OVERRIDE {}
virtual void forward(cv::InputArrayOfArrays inputs, cv::OutputArrayOfArrays outputs, cv::OutputArrayOfArrays internals) CV_OVERRIDE {}
};
TEST(Test_DLDT, fused_output)
{
static const int kNumChannels = 3;
CV_DNN_REGISTER_LAYER_CLASS(Unsupported, UnsupportedLayer);
Net net;
{
LayerParams lp;
lp.set("kernel_size", 1);
lp.set("num_output", 3);
lp.set("bias_term", false);
lp.type = "Convolution";
lp.name = "testConv";
lp.blobs.push_back(Mat({kNumChannels, 1, 1, 1}, CV_32F, Scalar(1)));
net.addLayerToPrev(lp.name, lp.type, lp);
}
{
LayerParams lp;
lp.set("bias_term", false);
lp.type = "Scale";
lp.name = "testScale";
lp.blobs.push_back(Mat({kNumChannels}, CV_32F, Scalar(1)));
net.addLayerToPrev(lp.name, lp.type, lp);
}
{
LayerParams lp;
net.addLayerToPrev("unsupported_layer", "Unsupported", lp);
}
net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
net.setInput(Mat({1, 1, 1, 1}, CV_32FC1, Scalar(1)));
ASSERT_NO_THROW(net.forward());
LayerFactory::unregisterLayer("Unsupported");
}
TEST(Test_DLDT, multiple_networks)
{
Net nets[2];
for (int i = 0; i < 2; ++i)
{
nets[i].setInputsNames(std::vector<String>(1, format("input_%d", i)));
LayerParams lp;
lp.set("kernel_size", 1);
lp.set("num_output", 1);
lp.set("bias_term", false);
lp.type = "Convolution";
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].setInput(Mat({1, 1, 1, 1}, CV_32FC1, Scalar(1)));
}
Mat out_1 = nets[0].forward();
Mat out_2 = nets[1].forward();
// After the second model is initialized we try to receive an output from the first network again.
out_1 = nets[0].forward();
normAssert(2 * out_1, out_2);
}
#endif // HAVE_INF_ENGINE
// Test a custom layer.
+3 -3
View File
@@ -49,11 +49,11 @@
#include "opencv2/dnn.hpp"
#include "test_common.hpp"
namespace opencv_test {
namespace opencv_test { namespace {
using namespace cv::dnn;
CV_ENUM(DNNBackend, DNN_BACKEND_DEFAULT, DNN_BACKEND_HALIDE, DNN_BACKEND_INFERENCE_ENGINE)
CV_ENUM(DNNTarget, DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16)
CV_ENUM(DNNTarget, DNN_TARGET_CPU, DNN_TARGET_OPENCL, DNN_TARGET_OPENCL_FP16, DNN_TARGET_MYRIAD)
static testing::internal::ParamGenerator<DNNTarget> availableDnnTargets()
{
@@ -69,6 +69,6 @@ static testing::internal::ParamGenerator<DNNTarget> availableDnnTargets()
return testing::ValuesIn(targets);
}
}
}}
#endif
+20 -1
View File
@@ -124,6 +124,7 @@ TEST_P(Test_TensorFlow_layers, conv)
runTensorFlowNet("atrous_conv2d_valid", targetId);
runTensorFlowNet("atrous_conv2d_same", targetId);
runTensorFlowNet("depthwise_conv2d", targetId);
runTensorFlowNet("keras_atrous_conv2d_same", targetId);
}
TEST_P(Test_TensorFlow_layers, padding)
@@ -160,10 +161,12 @@ TEST_P(Test_TensorFlow_layers, batch_norm)
TEST_P(Test_TensorFlow_layers, pooling)
{
int targetId = GetParam();
cv::ocl::Device d = cv::ocl::Device::getDefault();
bool loosenFlag = targetId == DNN_TARGET_OPENCL && d.isIntel() && d.type() == cv::ocl::Device::TYPE_CPU;
runTensorFlowNet("max_pool_even", targetId);
runTensorFlowNet("max_pool_odd_valid", targetId);
runTensorFlowNet("ave_pool_same", targetId);
runTensorFlowNet("max_pool_odd_same", targetId);
runTensorFlowNet("max_pool_odd_same", targetId, false, loosenFlag ? 3e-5 : 1e-5, loosenFlag ? 3e-4 : 1e-4);
runTensorFlowNet("reduce_mean", targetId); // an average pooling over all spatial dimensions.
}
@@ -267,6 +270,22 @@ TEST_P(Test_TensorFlow_nets, Inception_v2_SSD)
normAssertDetections(ref, out, "", 0.5);
}
TEST_P(Test_TensorFlow_nets, Inception_v2_Faster_RCNN)
{
std::string proto = findDataFile("dnn/faster_rcnn_inception_v2_coco_2018_01_28.pbtxt", false);
std::string model = findDataFile("dnn/faster_rcnn_inception_v2_coco_2018_01_28.pb", false);
Net net = readNetFromTensorflow(model, proto);
Mat img = imread(findDataFile("dnn/dog416.png", false));
Mat blob = blobFromImage(img, 1.0f / 127.5, Size(800, 600), Scalar(127.5, 127.5, 127.5), true, false);
net.setInput(blob);
Mat out = net.forward();
Mat ref = blobFromNPY(findDataFile("dnn/tensorflow/faster_rcnn_inception_v2_coco_2018_01_28.detection_out.npy"));
normAssertDetections(ref, out, "", 0.3);
}
TEST_P(Test_TensorFlow_nets, opencv_face_detector_uint8)
{
std::string proto = findDataFile("dnn/opencv_face_detector.pbtxt", false);
+1 -1
View File
@@ -250,7 +250,7 @@ TEST_P(Test_Torch_nets, ENet_accuracy)
Mat out = net.forward();
Mat ref = blobFromNPY(_tf("torch_enet_prob.npy", false));
// Due to numerical instability in Pooling-Unpooling layers (indexes jittering)
// thresholds for ENet must be changed. Accuracy of resuults was checked on
// thresholds for ENet must be changed. Accuracy of results was checked on
// Cityscapes dataset and difference in mIOU with Torch is 10E-4%
normAssert(ref, out, "", 0.00044, 0.44);