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 commit9ba9358ecb. Revert "documentation: avoid links to 'master' branch from 3.4 maintenance branch (2)" This reverts commitf185802489.
This commit is contained in:
@@ -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.
|
||||
@}
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -834,6 +834,84 @@ TEST(Test_DLDT, two_inputs)
|
||||
|
||||
normAssert(out, firstInp + secondInp);
|
||||
}
|
||||
|
||||
class UnsupportedLayer : public Layer
|
||||
{
|
||||
public:
|
||||
UnsupportedLayer(const LayerParams ¶ms) {}
|
||||
|
||||
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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user