mirror of
https://github.com/opencv/opencv.git
synced 2024-11-24 11:10:21 +08:00
Merge pull request #8989 from alalek:move_dnn_module
This commit is contained in:
commit
48924cd874
84
modules/dnn/CMakeLists.txt
Normal file
84
modules/dnn/CMakeLists.txt
Normal file
@ -0,0 +1,84 @@
|
||||
if(WINRT)
|
||||
ocv_module_disable(dnn)
|
||||
endif()
|
||||
|
||||
include(${OpenCV_SOURCE_DIR}/cmake/OpenCVFindLibProtobuf.cmake)
|
||||
if(NOT Protobuf_FOUND)
|
||||
ocv_module_disable(opencv_dnn)
|
||||
endif()
|
||||
|
||||
set(the_description "Deep neural network module. It allows to load models from different frameworks and to make forward pass")
|
||||
|
||||
ocv_add_module(dnn opencv_core opencv_imgproc WRAP python matlab)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-shadow -Wno-parentheses -Wmaybe-uninitialized -Wsign-promo
|
||||
-Wmissing-declarations -Wmissing-prototypes
|
||||
)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4701 /wd4100)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions( -D_CRT_SECURE_NO_WARNINGS=1 )
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146
|
||||
/wd4305 /wd4127 /wd4100 /wd4512 /wd4125 /wd4389 /wd4510 /wd4610
|
||||
/wd4702 /wd4456 /wd4457 /wd4065 /wd4310 /wd4661 /wd4506
|
||||
)
|
||||
else()
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated -Wmissing-prototypes -Wmissing-declarations -Wshadow
|
||||
-Wunused-parameter -Wunused-local-typedefs -Wsign-compare -Wsign-promo
|
||||
-Wundef -Wtautological-undefined-compare -Wignored-qualifiers -Wextra
|
||||
-Wunused-function -Wunused-const-variable -Wdeprecated-declarations
|
||||
)
|
||||
endif()
|
||||
|
||||
if(APPLE_FRAMEWORK)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshorten-64-to-32)
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
add_definitions(-DDISABLE_POSIX_MEMALIGN -DTH_DISABLE_HEAP_TRACKING)
|
||||
endif()
|
||||
|
||||
#supress warnings in autogenerated caffe.pb.* files
|
||||
add_definitions(-DHAVE_PROTOBUF=1)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS
|
||||
-Wunused-parameter -Wundef -Wignored-qualifiers -Wno-enum-compare
|
||||
-Wdeprecated-declarations
|
||||
/wd4125 /wd4267 /wd4127 /wd4244 /wd4512 /wd4702
|
||||
/wd4456 /wd4510 /wd4610 /wd4800
|
||||
-wd858 -wd2196
|
||||
)
|
||||
|
||||
if(PROTOBUF_UPDATE_FILES)
|
||||
file(GLOB proto_files src/tensorflow/*.proto)
|
||||
list(APPEND proto_files src/caffe/caffe.proto)
|
||||
PROTOBUF_GENERATE_CPP(Protobuf_HDRS Protobuf_SRCS ${proto_files})
|
||||
else()
|
||||
file(GLOB fw_srcs ${CMAKE_CURRENT_SOURCE_DIR}/misc/tensorflow/*.cc)
|
||||
file(GLOB fw_hdrs ${CMAKE_CURRENT_SOURCE_DIR}/misc/tensorflow/*.h)
|
||||
list(APPEND fw_srcs ${CMAKE_CURRENT_SOURCE_DIR}/misc/caffe/caffe.pb.cc)
|
||||
list(APPEND fw_hdrs ${CMAKE_CURRENT_SOURCE_DIR}/misc/caffe/caffe.pb.h)
|
||||
list(APPEND Protobuf_SRCS ${fw_srcs})
|
||||
list(APPEND Protobuf_HDRS ${fw_hdrs})
|
||||
list(APPEND Protobuf_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/misc/caffe)
|
||||
list(APPEND Protobuf_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/misc/tensorflow)
|
||||
endif()
|
||||
|
||||
ocv_source_group("Src\\protobuf" FILES ${Protobuf_SRCS} ${Protobuf_HDRS})
|
||||
ocv_module_include_directories(include ${Protobuf_INCLUDE_DIRS})
|
||||
|
||||
ocv_glob_module_sources(${Protobuf_SRCS} ${Protobuf_HDRS} ${CBLAS_H_PROXY_PATH})
|
||||
ocv_create_module(${Protobuf_LIBRARIES} ${LAPACK_LIBRARIES})
|
||||
ocv_add_samples()
|
||||
ocv_add_accuracy_tests()
|
||||
ocv_add_perf_tests()
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Torch7 importer of blobs and models, produced by Torch.nn module
|
||||
# ----------------------------------------------------------------------------
|
||||
OCV_OPTION(${the_module}_BUILD_TORCH_IMPORTER "Build Torch model importer" ON)
|
||||
if(${the_module}_BUILD_TORCH_IMPORTER)
|
||||
message(STATUS "Torch importer has been enabled. To run the tests you have to install Torch "
|
||||
"('th' executable should be available) "
|
||||
"and generate testdata using opencv_extra/testdata/dnn/generate_torch_models.py script.")
|
||||
add_definitions(-DENABLE_TORCH_IMPORTER=1)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4702 /wd4127 /wd4267) #supress warnings in original torch files
|
||||
endif()
|
64
modules/dnn/include/opencv2/dnn.hpp
Normal file
64
modules/dnn/include/opencv2/dnn.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_DNN_HPP
|
||||
#define OPENCV_DNN_HPP
|
||||
|
||||
// This is an umbrealla header to include into you project.
|
||||
// We are free to change headers layout in dnn subfolder, so please include
|
||||
// this header for future compartibility
|
||||
|
||||
|
||||
/** @defgroup dnn Deep Neural Network module
|
||||
@{
|
||||
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;
|
||||
- functionality for loading serialized networks models from differnet frameworks.
|
||||
|
||||
Functionality of this module is designed only for forward pass computations (i. e. network testing).
|
||||
A network training is in principle not supported.
|
||||
@}
|
||||
*/
|
||||
#include <opencv2/dnn/dnn.hpp>
|
||||
|
||||
#endif /* OPENCV_DNN_HPP */
|
471
modules/dnn/include/opencv2/dnn/all_layers.hpp
Normal file
471
modules/dnn/include/opencv2/dnn/all_layers.hpp
Normal file
@ -0,0 +1,471 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_DNN_DNN_ALL_LAYERS_HPP
|
||||
#define OPENCV_DNN_DNN_ALL_LAYERS_HPP
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
//! @addtogroup dnn
|
||||
//! @{
|
||||
|
||||
/** @defgroup dnnLayerList Partial List of Implemented Layers
|
||||
@{
|
||||
This subsection of dnn module contains information about bult-in layers and their descriptions.
|
||||
|
||||
Classes listed here, in fact, provides C++ API for creating intances of bult-in layers.
|
||||
In addition to this way of layers instantiation, there is a more common factory API (see @ref dnnLayerFactory), it allows to create layers dynamically (by name) and register new ones.
|
||||
You can use both API, but factory API is less convinient for native C++ programming and basically designed for use inside importers (see @ref Importer, @ref createCaffeImporter(), @ref createTorchImporter()).
|
||||
|
||||
Bult-in layers partially reproduce functionality of corresponding Caffe and Torch7 layers.
|
||||
In partuclar, the following layers and Caffe @ref Importer were tested to reproduce <a href="http://caffe.berkeleyvision.org/tutorial/layers.html">Caffe</a> functionality:
|
||||
- Convolution
|
||||
- Deconvolution
|
||||
- Pooling
|
||||
- InnerProduct
|
||||
- TanH, ReLU, Sigmoid, BNLL, Power, AbsVal
|
||||
- Softmax
|
||||
- Reshape, Flatten, Slice, Split
|
||||
- LRN
|
||||
- MVN
|
||||
- Dropout (since it does nothing on forward pass -))
|
||||
*/
|
||||
|
||||
class CV_EXPORTS BlankLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<BlankLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
//! LSTM recurrent layer
|
||||
class CV_EXPORTS LSTMLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/** Creates instance of LSTM layer */
|
||||
static Ptr<LSTMLayer> create(const LayerParams& params);
|
||||
|
||||
/** Set trained weights for LSTM layer.
|
||||
LSTM behavior on each step is defined by current input, previous output, previous cell state and learned weights.
|
||||
|
||||
Let @f$x_t@f$ be current input, @f$h_t@f$ be current output, @f$c_t@f$ be current state.
|
||||
Than current output and current cell state is computed as follows:
|
||||
@f{eqnarray*}{
|
||||
h_t &= o_t \odot tanh(c_t), \\
|
||||
c_t &= f_t \odot c_{t-1} + i_t \odot g_t, \\
|
||||
@f}
|
||||
where @f$\odot@f$ is per-element multiply operation and @f$i_t, f_t, o_t, g_t@f$ is internal gates that are computed using learned wights.
|
||||
|
||||
Gates are computed as follows:
|
||||
@f{eqnarray*}{
|
||||
i_t &= sigmoid&(W_{xi} x_t + W_{hi} h_{t-1} + b_i), \\
|
||||
f_t &= sigmoid&(W_{xf} x_t + W_{hf} h_{t-1} + b_f), \\
|
||||
o_t &= sigmoid&(W_{xo} x_t + W_{ho} h_{t-1} + b_o), \\
|
||||
g_t &= tanh &(W_{xg} x_t + W_{hg} h_{t-1} + b_g), \\
|
||||
@f}
|
||||
where @f$W_{x?}@f$, @f$W_{h?}@f$ and @f$b_{?}@f$ are learned weights represented as matrices:
|
||||
@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$.
|
||||
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$)
|
||||
*/
|
||||
virtual void setWeights(const Mat &Wh, const Mat &Wx, const Mat &b) = 0;
|
||||
|
||||
/** @brief Specifies shape of output blob which will be [[`T`], `N`] + @p outTailShape.
|
||||
* @details If this parameter is empty or unset then @p outTailShape = [`Wh`.size(0)] will be used,
|
||||
* where `Wh` is parameter from setWeights().
|
||||
*/
|
||||
virtual void setOutShape(const MatShape &outTailShape = MatShape()) = 0;
|
||||
|
||||
/** @brief Specifies either interpet first dimension of input blob as timestamp dimenion either as sample.
|
||||
*
|
||||
* If flag is set to true then shape of input blob will be interpeted as [`T`, `N`, `[data dims]`] where `T` specifies number of timpestamps, `N` is number of independent streams.
|
||||
* In this case each forward() call will iterate through `T` timestamps and update layer's state `T` times.
|
||||
*
|
||||
* If flag is set to false then shape of input blob will be interpeted as [`N`, `[data dims]`].
|
||||
* In this case each forward() call will make one iteration and produce one timestamp with shape [`N`, `[out dims]`].
|
||||
*/
|
||||
virtual void setUseTimstampsDim(bool use = true) = 0;
|
||||
|
||||
/** @brief If this flag is set to true then layer will produce @f$ c_t @f$ as second output.
|
||||
* @details Shape of the second output is the same as first output.
|
||||
*/
|
||||
virtual void setProduceCellOutput(bool produce = false) = 0;
|
||||
|
||||
/* In common case it use single input with @f$x_t@f$ values to compute output(s) @f$h_t@f$ (and @f$c_t@f$).
|
||||
* @param input should contain packed values @f$x_t@f$
|
||||
* @param output contains computed outputs: @f$h_t@f$ (and @f$c_t@f$ if setProduceCellOutput() flag was set to true).
|
||||
*
|
||||
* 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 timpestamps, `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.
|
||||
* (i.e. @f$ x_{t}^{stream} @f$ is stored inside @p input[0][stream, ...]).
|
||||
*/
|
||||
|
||||
int inputNameToIndex(String inputName);
|
||||
int outputNameToIndex(String outputName);
|
||||
};
|
||||
|
||||
//! Classical recurrent layer
|
||||
class CV_EXPORTS RNNLayer : public Layer
|
||||
{
|
||||
public:
|
||||
/** Creates instance of RNNLayer */
|
||||
static Ptr<RNNLayer> create(const LayerParams& params);
|
||||
|
||||
/** Setups learned weights.
|
||||
|
||||
Recurrent-layer behavior on each step is defined by current input @f$ x_t @f$, previous state @f$ h_t @f$ and learned weights as follows:
|
||||
@f{eqnarray*}{
|
||||
h_t &= tanh&(W_{hh} h_{t-1} + W_{xh} x_t + b_h), \\
|
||||
o_t &= tanh&(W_{ho} h_t + b_o),
|
||||
@f}
|
||||
|
||||
@param Wxh is @f$ W_{xh} @f$ matrix
|
||||
@param bh is @f$ b_{h} @f$ vector
|
||||
@param Whh is @f$ W_{hh} @f$ matrix
|
||||
@param Who is @f$ W_{xo} @f$ matrix
|
||||
@param bo is @f$ b_{o} @f$ vector
|
||||
*/
|
||||
virtual void setWeights(const Mat &Wxh, const Mat &bh, const Mat &Whh, const Mat &Who, const Mat &bo) = 0;
|
||||
|
||||
/** @brief If this flag is set to true then layer will produce @f$ h_t @f$ as second output.
|
||||
* @details Shape of the second output is the same as first output.
|
||||
*/
|
||||
virtual void setProduceHiddenOutput(bool produce = false) = 0;
|
||||
|
||||
/** Accepts two inputs @f$x_t@f$ and @f$h_{t-1}@f$ and compute two outputs @f$o_t@f$ and @f$h_t@f$.
|
||||
|
||||
@param input should contain packed input @f$x_t@f$.
|
||||
@param output should contain output @f$o_t@f$ (and @f$h_t@f$ if setProduceHiddenOutput() is set to true).
|
||||
|
||||
@p input[0] should have shape [`T`, `N`, `data_dims`] where `T` and `N` is number of timestamps and number of independent samples of @f$x_t@f$ respectively.
|
||||
|
||||
@p output[0] will have shape [`T`, `N`, @f$N_o@f$], where @f$N_o@f$ is number of rows in @f$ W_{xo} @f$ matrix.
|
||||
|
||||
If setProduceHiddenOutput() is set to true then @p output[1] will contain a Mat with shape [`T`, `N`, @f$N_h@f$], where @f$N_h@f$ is number of rows in @f$ W_{hh} @f$ matrix.
|
||||
*/
|
||||
};
|
||||
|
||||
class CV_EXPORTS BaseConvolutionLayer : public Layer
|
||||
{
|
||||
public:
|
||||
Size kernel, stride, pad, dilation, adjustPad;
|
||||
String padMode;
|
||||
};
|
||||
|
||||
class CV_EXPORTS ActivationLayer;
|
||||
class CV_EXPORTS BatchNormLayer;
|
||||
|
||||
class CV_EXPORTS ConvolutionLayer : public BaseConvolutionLayer
|
||||
{
|
||||
public:
|
||||
virtual bool setActivation(const Ptr<ActivationLayer>& layer) = 0;
|
||||
virtual bool setBatchNorm(const Ptr<BatchNormLayer>& layer) = 0;
|
||||
|
||||
static Ptr<BaseConvolutionLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS DeconvolutionLayer : public BaseConvolutionLayer
|
||||
{
|
||||
public:
|
||||
static Ptr<BaseConvolutionLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS LRNLayer : public Layer
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
CHANNEL_NRM,
|
||||
SPATIAL_NRM
|
||||
};
|
||||
int type;
|
||||
|
||||
int size;
|
||||
float alpha, beta, bias;
|
||||
bool normBySize;
|
||||
|
||||
static Ptr<LRNLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS PoolingLayer : public Layer
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
MAX,
|
||||
AVE,
|
||||
STOCHASTIC
|
||||
};
|
||||
|
||||
int type;
|
||||
Size kernel, stride, pad;
|
||||
bool globalPooling;
|
||||
bool computeMaxIdx;
|
||||
String padMode;
|
||||
|
||||
static Ptr<PoolingLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS SoftmaxLayer : public Layer
|
||||
{
|
||||
public:
|
||||
bool logSoftMax;
|
||||
|
||||
static Ptr<SoftmaxLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS InnerProductLayer : public Layer
|
||||
{
|
||||
public:
|
||||
int axis;
|
||||
static Ptr<InnerProductLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS MVNLayer : public Layer
|
||||
{
|
||||
public:
|
||||
float eps;
|
||||
bool normVariance, acrossChannels;
|
||||
|
||||
static Ptr<MVNLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
/* Reshaping */
|
||||
|
||||
class CV_EXPORTS ReshapeLayer : public Layer
|
||||
{
|
||||
public:
|
||||
MatShape newShapeDesc;
|
||||
Range newShapeRange;
|
||||
|
||||
static Ptr<ReshapeLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS FlattenLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<FlattenLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS ConcatLayer : public Layer
|
||||
{
|
||||
public:
|
||||
int axis;
|
||||
|
||||
static Ptr<ConcatLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS SplitLayer : public Layer
|
||||
{
|
||||
public:
|
||||
int outputsCount; //!< Number of copies that will be produced (is ignored when negative).
|
||||
|
||||
static Ptr<SplitLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS SliceLayer : public Layer
|
||||
{
|
||||
public:
|
||||
int axis;
|
||||
std::vector<int> sliceIndices;
|
||||
|
||||
static Ptr<SliceLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS PermuteLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<PermuteLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS PaddingLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<PaddingLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
/* Activations */
|
||||
class CV_EXPORTS ActivationLayer : public Layer
|
||||
{
|
||||
public:
|
||||
virtual void forwardSlice(const float* src, float* dst, int len,
|
||||
size_t outPlaneSize, int cn0, int cn1) const = 0;
|
||||
};
|
||||
|
||||
class CV_EXPORTS ReLULayer : public ActivationLayer
|
||||
{
|
||||
public:
|
||||
float negativeSlope;
|
||||
|
||||
static Ptr<ReLULayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS ChannelsPReLULayer : public ActivationLayer
|
||||
{
|
||||
public:
|
||||
static Ptr<ChannelsPReLULayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS TanHLayer : public ActivationLayer
|
||||
{
|
||||
public:
|
||||
static Ptr<TanHLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS SigmoidLayer : public ActivationLayer
|
||||
{
|
||||
public:
|
||||
static Ptr<SigmoidLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS BNLLLayer : public ActivationLayer
|
||||
{
|
||||
public:
|
||||
static Ptr<BNLLLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS AbsLayer : public ActivationLayer
|
||||
{
|
||||
public:
|
||||
static Ptr<AbsLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS PowerLayer : public ActivationLayer
|
||||
{
|
||||
public:
|
||||
float power, scale, shift;
|
||||
|
||||
static Ptr<PowerLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
/* Layers used in semantic segmentation */
|
||||
|
||||
class CV_EXPORTS CropLayer : public Layer
|
||||
{
|
||||
public:
|
||||
int startAxis;
|
||||
std::vector<int> offset;
|
||||
|
||||
static Ptr<CropLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS EltwiseLayer : public Layer
|
||||
{
|
||||
public:
|
||||
enum EltwiseOp
|
||||
{
|
||||
PROD = 0,
|
||||
SUM = 1,
|
||||
MAX = 2,
|
||||
};
|
||||
|
||||
static Ptr<EltwiseLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS BatchNormLayer : public Layer
|
||||
{
|
||||
public:
|
||||
bool hasWeights, hasBias;
|
||||
float epsilon;
|
||||
|
||||
virtual void getScaleShift(Mat& scale, Mat& shift) const = 0;
|
||||
static Ptr<BatchNormLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS MaxUnpoolLayer : public Layer
|
||||
{
|
||||
public:
|
||||
Size poolKernel;
|
||||
Size poolPad;
|
||||
Size poolStride;
|
||||
|
||||
static Ptr<MaxUnpoolLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS ScaleLayer : public Layer
|
||||
{
|
||||
public:
|
||||
bool hasBias;
|
||||
|
||||
static Ptr<ScaleLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS ShiftLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<ShiftLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS PriorBoxLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<PriorBoxLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class CV_EXPORTS DetectionOutputLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<DetectionOutputLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
class NormalizeBBoxLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<NormalizeBBoxLayer> create(const LayerParams& params);
|
||||
};
|
||||
|
||||
//! @}
|
||||
//! @}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
146
modules/dnn/include/opencv2/dnn/dict.hpp
Normal file
146
modules/dnn/include/opencv2/dnn/dict.hpp
Normal file
@ -0,0 +1,146 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_DNN_DNN_DICT_HPP
|
||||
#define OPENCV_DNN_DNN_DICT_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
//! @addtogroup dnn
|
||||
//! @{
|
||||
|
||||
/** @brief This struct stores the scalar value (or array) of one of the following type: double, cv::String or int64.
|
||||
* @todo Maybe int64 is useless because double type exactly stores at least 2^52 integers.
|
||||
*/
|
||||
struct DictValue
|
||||
{
|
||||
DictValue(const DictValue &r);
|
||||
DictValue(int64 i = 0) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = i; } //!< Constructs integer scalar
|
||||
DictValue(int i) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = i; } //!< Constructs integer scalar
|
||||
DictValue(unsigned p) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = p; } //!< Constructs integer scalar
|
||||
DictValue(double p) : type(Param::REAL), pd(new AutoBuffer<double,1>) { (*pd)[0] = p; } //!< Constructs floating point scalar
|
||||
DictValue(const String &s) : type(Param::STRING), ps(new AutoBuffer<String,1>) { (*ps)[0] = s; } //!< Constructs string scalar
|
||||
DictValue(const char *s) : type(Param::STRING), ps(new AutoBuffer<String,1>) { (*ps)[0] = s; } //!< @overload
|
||||
|
||||
template<typename TypeIter>
|
||||
static DictValue arrayInt(TypeIter begin, int size); //!< Constructs integer array
|
||||
template<typename TypeIter>
|
||||
static DictValue arrayReal(TypeIter begin, int size); //!< Constructs floating point array
|
||||
template<typename TypeIter>
|
||||
static DictValue arrayString(TypeIter begin, int size); //!< Constructs array of strings
|
||||
|
||||
template<typename T>
|
||||
T get(int idx = -1) const; //!< Tries to convert array element with specified index to requested type and returns its.
|
||||
|
||||
int size() const;
|
||||
|
||||
bool isInt() const;
|
||||
bool isString() const;
|
||||
bool isReal() const;
|
||||
|
||||
DictValue &operator=(const DictValue &r);
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const DictValue &dictv);
|
||||
|
||||
~DictValue();
|
||||
|
||||
private:
|
||||
|
||||
int type;
|
||||
|
||||
union
|
||||
{
|
||||
AutoBuffer<int64, 1> *pi;
|
||||
AutoBuffer<double, 1> *pd;
|
||||
AutoBuffer<String, 1> *ps;
|
||||
void *pv;
|
||||
};
|
||||
|
||||
DictValue(int _type, void *_p) : type(_type), pv(_p) {}
|
||||
void release();
|
||||
};
|
||||
|
||||
/** @brief This class implements name-value dictionary, values are instances of DictValue. */
|
||||
class CV_EXPORTS Dict
|
||||
{
|
||||
typedef std::map<String, DictValue> _Dict;
|
||||
_Dict dict;
|
||||
|
||||
public:
|
||||
|
||||
//! Checks a presence of the @p key in the dictionary.
|
||||
bool has(const String &key) const;
|
||||
|
||||
//! If the @p key in the dictionary then returns pointer to its value, else returns NULL.
|
||||
DictValue *ptr(const String &key);
|
||||
|
||||
/** @overload */
|
||||
const DictValue *ptr(const String &key) const;
|
||||
|
||||
//! If the @p key in the dictionary then returns its value, else an error will be generated.
|
||||
const DictValue &get(const String &key) const;
|
||||
|
||||
/** @overload */
|
||||
template <typename T>
|
||||
T get(const String &key) const;
|
||||
|
||||
//! If the @p key in the dictionary then returns its value, else returns @p defaultValue.
|
||||
template <typename T>
|
||||
T get(const String &key, const T &defaultValue) const;
|
||||
|
||||
//! Sets new @p value for the @p key, or adds new key-value pair into the dictionary.
|
||||
template<typename T>
|
||||
const T &set(const String &key, const T &value);
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const Dict &dict);
|
||||
};
|
||||
|
||||
//! @}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
655
modules/dnn/include/opencv2/dnn/dnn.hpp
Normal file
655
modules/dnn/include/opencv2/dnn/dnn.hpp
Normal file
@ -0,0 +1,655 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_DNN_DNN_HPP
|
||||
#define OPENCV_DNN_DNN_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/dnn/dict.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn //! This namespace is used for dnn module functionlaity.
|
||||
{
|
||||
//! @addtogroup dnn
|
||||
//! @{
|
||||
|
||||
typedef std::vector<int> MatShape;
|
||||
|
||||
/**
|
||||
* @brief Enum of computation backends supported by layers.
|
||||
*/
|
||||
enum Backend
|
||||
{
|
||||
DNN_BACKEND_DEFAULT,
|
||||
DNN_BACKEND_HALIDE
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enum of target devices for computations.
|
||||
*/
|
||||
enum Target
|
||||
{
|
||||
DNN_TARGET_CPU,
|
||||
DNN_TARGET_OPENCL
|
||||
};
|
||||
|
||||
/** @brief Initialize dnn module and built-in layers.
|
||||
*
|
||||
* This function automatically called on most of OpenCV builds,
|
||||
* but you need to call it manually on some specific configurations (iOS for example).
|
||||
*/
|
||||
CV_EXPORTS_W void initModule();
|
||||
|
||||
/** @brief This class provides all data needed to initialize layer.
|
||||
*
|
||||
* It includes dictionary with scalar params (which can be readed by using Dict interface),
|
||||
* blob params #blobs and optional meta information: #name and #type of layer instance.
|
||||
*/
|
||||
class CV_EXPORTS LayerParams : public Dict
|
||||
{
|
||||
public:
|
||||
//TODO: Add ability to name blob params
|
||||
std::vector<Mat> blobs; //!< List of learned parameters stored as blobs.
|
||||
|
||||
String name; //!< Name of the layer instance (optional, can be used internal purposes).
|
||||
String type; //!< Type name which was used for creating layer by layer factory (optional).
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Derivatives of this class encapsulates functions of certain backends.
|
||||
*/
|
||||
class BackendNode
|
||||
{
|
||||
public:
|
||||
BackendNode(int backendId);
|
||||
|
||||
virtual ~BackendNode(); //!< Virtual destructor to make polymorphism.
|
||||
|
||||
int backendId; //!< Backend identifier.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Derivatives of this class wraps cv::Mat for different backends and targets.
|
||||
*/
|
||||
class BackendWrapper
|
||||
{
|
||||
public:
|
||||
BackendWrapper(int backendId, int targetId);
|
||||
|
||||
/**
|
||||
* @brief Wrap cv::Mat for specific backend and target.
|
||||
* @param[in] targetId Target identifier.
|
||||
* @param[in] m cv::Mat for wrapping.
|
||||
*
|
||||
* Make CPU->GPU data transfer if it's require for the target.
|
||||
*/
|
||||
BackendWrapper(int targetId, const cv::Mat& m);
|
||||
|
||||
/**
|
||||
* @brief Make wrapper for reused cv::Mat.
|
||||
* @param[in] base Wrapper of cv::Mat that will be reused.
|
||||
* @param[in] shape Specific shape.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
BackendWrapper(const Ptr<BackendWrapper>& base, const MatShape& shape);
|
||||
|
||||
virtual ~BackendWrapper(); //!< Virtual destructor to make polymorphism.
|
||||
|
||||
/**
|
||||
* @brief Transfer data to CPU host memory.
|
||||
*/
|
||||
virtual void copyToHost() = 0;
|
||||
|
||||
int backendId; //!< Backend identifier.
|
||||
int targetId; //!< Target identifier.
|
||||
};
|
||||
|
||||
/** @brief This interface class allows to build new Layers - are building blocks of networks.
|
||||
*
|
||||
* Each class, derived from Layer, must implement allocate() methods to declare own outputs and forward() to compute outputs.
|
||||
* Also before using the new layer into networks you must register your layer by using one of @ref dnnLayerFactory "LayerFactory" macros.
|
||||
*/
|
||||
class CV_EXPORTS_W Layer
|
||||
{
|
||||
public:
|
||||
|
||||
//! List of learned parameters must be stored here to allow read them by using Net::getParam().
|
||||
CV_PROP_RW std::vector<Mat> blobs;
|
||||
|
||||
/** @brief Computes and sets internal parameters according to inputs, outputs and blobs.
|
||||
* @param[in] input vector of already allocated input blobs
|
||||
* @param[out] output vector of already allocated output blobs
|
||||
*
|
||||
* If this method is called after network has allocated all memory for input and output blobs
|
||||
* and before inferencing.
|
||||
*/
|
||||
virtual void finalize(const std::vector<Mat*> &input, std::vector<Mat> &output);
|
||||
|
||||
/** @brief Given the @p input blobs, computes the output @p blobs.
|
||||
* @param[in] input the input blobs.
|
||||
* @param[out] output allocated output blobs, which will store results of the computation.
|
||||
* @param[out] internals allocated internal blobs
|
||||
*/
|
||||
virtual void forward(std::vector<Mat*> &input, std::vector<Mat> &output, std::vector<Mat> &internals) = 0;
|
||||
|
||||
/** @brief @overload */
|
||||
CV_WRAP void finalize(const std::vector<Mat> &inputs, CV_OUT std::vector<Mat> &outputs);
|
||||
|
||||
/** @brief @overload */
|
||||
CV_WRAP std::vector<Mat> finalize(const std::vector<Mat> &inputs);
|
||||
|
||||
/** @brief @overload */
|
||||
CV_WRAP void forward(const std::vector<Mat> &inputs, CV_IN_OUT std::vector<Mat> &outputs,
|
||||
CV_IN_OUT std::vector<Mat> &internals);
|
||||
|
||||
/** @brief Allocates layer and computes output. */
|
||||
CV_WRAP void run(const std::vector<Mat> &inputs, CV_OUT std::vector<Mat> &outputs,
|
||||
CV_IN_OUT std::vector<Mat> &internals);
|
||||
|
||||
/** @brief Returns index of input blob into the input array.
|
||||
* @param inputName label of input blob
|
||||
*
|
||||
* Each layer input and output can be labeled to easily identify them using "%<layer_name%>[.output_name]" notation.
|
||||
* This method maps label of input blob to its index into input vector.
|
||||
*/
|
||||
virtual int inputNameToIndex(String inputName);
|
||||
/** @brief Returns index of output blob in output array.
|
||||
* @see inputNameToIndex()
|
||||
*/
|
||||
virtual int outputNameToIndex(String outputName);
|
||||
|
||||
/**
|
||||
* @brief Ask layer if it support specific backend for doing computations.
|
||||
* @param[in] backendId computation backend identifier.
|
||||
* @see Backend
|
||||
*/
|
||||
virtual bool supportBackend(int backendId);
|
||||
|
||||
/**
|
||||
* @brief Returns Halide backend node.
|
||||
* @param[in] inputs Input Halide buffers.
|
||||
* @see BackendNode, BackendWrapper
|
||||
*
|
||||
* Input buffers should be exactly the same that will be used in forward invocations.
|
||||
* Despite we can use Halide::ImageParam based on input shape only,
|
||||
* it helps prevent some memory management issues (if something wrong,
|
||||
* Halide tests will be failed).
|
||||
*/
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs);
|
||||
|
||||
/**
|
||||
* @brief Automatic Halide scheduling based on layer hyper-parameters.
|
||||
* @param[in] node Backend node with Halide functions.
|
||||
* @param[in] inputs Blobs that will be used in forward invocations.
|
||||
* @param[in] outputs Blobs that will be used in forward invocations.
|
||||
* @param[in] targetId Target identifier
|
||||
* @see BackendNode, Target
|
||||
*
|
||||
* Layer don't use own Halide::Func members because we can have applied
|
||||
* layers fusing. In this way the fused function should be scheduled.
|
||||
*/
|
||||
virtual void applyHalideScheduler(Ptr<BackendNode>& node,
|
||||
const std::vector<Mat*> &inputs,
|
||||
const std::vector<Mat> &outputs,
|
||||
int targetId) const;
|
||||
|
||||
/**
|
||||
* @brief Implement layers fusing.
|
||||
* @param[in] node Backend node of bottom layer.
|
||||
* @see BackendNode
|
||||
*
|
||||
* Actual for graph-based backends. If layer attached successfully,
|
||||
* returns non-empty cv::Ptr to node of the same backend.
|
||||
* Fuse only over the last function.
|
||||
*/
|
||||
virtual Ptr<BackendNode> tryAttach(const Ptr<BackendNode>& node);
|
||||
|
||||
virtual bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const;
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const {(void)inputs; (void)outputs; return 0;}
|
||||
|
||||
CV_PROP String name; //!< Name of the layer instance, can be used for logging or other internal purposes.
|
||||
CV_PROP String type; //!< Type name which was used for creating layer by layer factory.
|
||||
|
||||
Layer();
|
||||
explicit Layer(const LayerParams ¶ms); //!< Initializes only #name, #type and #blobs fields.
|
||||
void setParamsFrom(const LayerParams ¶ms); //!< Initializes only #name, #type and #blobs fields.
|
||||
virtual ~Layer();
|
||||
};
|
||||
|
||||
/** @brief This class allows to create and manipulate comprehensive artificial neural networks.
|
||||
*
|
||||
* Neural network is presented as directed acyclic graph (DAG), where vertices are Layer instances,
|
||||
* and edges specify relationships between layers inputs and outputs.
|
||||
*
|
||||
* Each network layer has unique integer id and unique string name inside its network.
|
||||
* LayerId can store either layer name or layer id.
|
||||
*
|
||||
* This class supports reference counting of its instances, i. e. copies point to the same instance.
|
||||
*/
|
||||
class CV_EXPORTS_W_SIMPLE Net
|
||||
{
|
||||
public:
|
||||
|
||||
CV_WRAP Net(); //!< Default constructor.
|
||||
CV_WRAP ~Net(); //!< Destructor frees the net only if there aren't references to the net anymore.
|
||||
|
||||
/** Returns true if there are no layers in the network. */
|
||||
CV_WRAP bool empty() const;
|
||||
|
||||
/** @brief Adds new layer to the net.
|
||||
* @param name unique name of the adding layer.
|
||||
* @param type typename of the adding layer (type must be registered in LayerRegister).
|
||||
* @param params parameters which will be used to initialize the creating layer.
|
||||
* @returns unique identifier of created layer, or -1 if a failure will happen.
|
||||
*/
|
||||
int addLayer(const String &name, const String &type, LayerParams ¶ms);
|
||||
/** @brief Adds new layer and connects its first input to the first output of previously added layer.
|
||||
* @see addLayer()
|
||||
*/
|
||||
int addLayerToPrev(const String &name, const String &type, LayerParams ¶ms);
|
||||
|
||||
/** @brief Converts string name of the layer to the integer identifier.
|
||||
* @returns id of the layer, or -1 if the layer wasn't found.
|
||||
*/
|
||||
CV_WRAP int getLayerId(const String &layer);
|
||||
|
||||
CV_WRAP std::vector<String> getLayerNames() const;
|
||||
|
||||
/** @brief Container for strings and integers. */
|
||||
typedef DictValue LayerId;
|
||||
|
||||
/** @brief Returns pointer to layer with specified name which the network use. */
|
||||
CV_WRAP Ptr<Layer> getLayer(LayerId layerId);
|
||||
|
||||
/** @brief Returns pointers to input layers of specific layer. */
|
||||
CV_WRAP std::vector<Ptr<Layer> > getLayerInputs(LayerId layerId);
|
||||
|
||||
/** @brief Delete layer for the network (not implemented yet) */
|
||||
CV_WRAP void deleteLayer(LayerId layer);
|
||||
|
||||
/** @brief Connects output of the first layer to input of the second layer.
|
||||
* @param outPin descriptor of the first layer output.
|
||||
* @param inpPin descriptor of the second layer input.
|
||||
*
|
||||
* Descriptors have the following template <DFN><layer_name>[.input_number]</DFN>:
|
||||
* - the first part of the template <DFN>layer_name</DFN> is sting name of the added layer.
|
||||
* If this part is empty then the network input pseudo layer will be used;
|
||||
* - the second optional part of the template <DFN>input_number</DFN>
|
||||
* is either number of the layer input, either label one.
|
||||
* If this part is omitted then the first layer input will be used.
|
||||
*
|
||||
* @see setNetInputs(), Layer::inputNameToIndex(), Layer::outputNameToIndex()
|
||||
*/
|
||||
CV_WRAP void connect(String outPin, String inpPin);
|
||||
|
||||
/** @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 inpNum number of the second layer input
|
||||
*/
|
||||
void connect(int outLayerId, int outNum, int inpLayerId, int inpNum);
|
||||
|
||||
/** @brief Sets outputs names of the network input pseudo layer.
|
||||
*
|
||||
* Each net always has special own the network input pseudo layer with id=0.
|
||||
* This layer stores the user blobs only and don't make any computations.
|
||||
* In fact, this layer provides the only way to pass user data into the network.
|
||||
* As any other layer, this layer can label its outputs and this function provides an easy way to do this.
|
||||
*/
|
||||
CV_WRAP void setInputsNames(const std::vector<String> &inputBlobNames);
|
||||
|
||||
/** @brief Runs forward pass to compute output of layer with name @p outputName.
|
||||
* @param outputName name for layer which output is needed to get
|
||||
* @return blob for first output of specified layer.
|
||||
* @details By default runs forward pass for the whole network.
|
||||
*/
|
||||
CV_WRAP Mat forward(const String& outputName = String());
|
||||
|
||||
/** @brief Runs forward pass to compute output of layer with name @p outputName.
|
||||
* @param outputBlobs contains all output blobs for specified layer.
|
||||
* @param outputName name for layer which output is needed to get
|
||||
* @details If @p outputName is empty, runs forward pass for the whole network.
|
||||
*/
|
||||
CV_WRAP void forward(std::vector<Mat>& outputBlobs, const String& outputName = String());
|
||||
|
||||
/** @brief Runs forward pass to compute outputs of layers listed in @p outBlobNames.
|
||||
* @param outputBlobs contains blobs for first outputs of specified layers.
|
||||
* @param outBlobNames names for layers which outputs are needed to get
|
||||
*/
|
||||
CV_WRAP void forward(std::vector<Mat>& outputBlobs,
|
||||
const std::vector<String>& outBlobNames);
|
||||
|
||||
/** @brief Runs forward pass to compute outputs of layers listed in @p outBlobNames.
|
||||
* @param outputBlobs contains all output blobs for each layer specified in @p outBlobNames.
|
||||
* @param outBlobNames names for layers which outputs are needed to get
|
||||
*/
|
||||
CV_WRAP void forward(std::vector<std::vector<Mat> >& outputBlobs,
|
||||
const std::vector<String>& outBlobNames);
|
||||
|
||||
//TODO:
|
||||
/** @brief Optimized forward.
|
||||
* @warning Not implemented yet.
|
||||
* @details Makes forward only those layers which weren't changed after previous forward().
|
||||
*/
|
||||
void forwardOpt(LayerId toLayer);
|
||||
/** @overload */
|
||||
void forwardOpt(const std::vector<LayerId> &toLayers);
|
||||
|
||||
/**
|
||||
* @brief Compile Halide layers.
|
||||
* @param[in] scheduler Path to YAML file with scheduling directives.
|
||||
* @see setPreferableBackend
|
||||
*
|
||||
* Schedule layers that support Halide backend. Then compile them for
|
||||
* specific target. For layers that not represented in scheduling file
|
||||
* or if no manual scheduling used at all, automatic scheduling will be applied.
|
||||
*/
|
||||
void setHalideScheduler(const String& scheduler);
|
||||
|
||||
/**
|
||||
* @brief Ask network to use specific computation backend where it supported.
|
||||
* @param[in] backendId backend identifier.
|
||||
* @see Backend
|
||||
*/
|
||||
void setPreferableBackend(int backendId);
|
||||
|
||||
/**
|
||||
* @brief Ask network to make computations on specific target device.
|
||||
* @param[in] targetId target identifier.
|
||||
* @see Target
|
||||
*/
|
||||
void setPreferableTarget(int targetId);
|
||||
|
||||
/** @brief Sets the new value for the layer output blob
|
||||
* @param name descriptor of the updating layer output blob.
|
||||
* @param blob new blob.
|
||||
* @see connect(String, String) to know format of the descriptor.
|
||||
* @note If updating blob is not empty then @p blob must have the same shape,
|
||||
* because network reshaping is not implemented yet.
|
||||
*/
|
||||
CV_WRAP void setInput(const Mat &blob, const String& name = "");
|
||||
|
||||
/** @brief Sets the new value for the learned param of the layer.
|
||||
* @param layer name or id of the layer.
|
||||
* @param numParam index of the layer parameter in the Layer::blobs array.
|
||||
* @param blob the new value.
|
||||
* @see Layer::blobs
|
||||
* @note If shape of the new blob differs from the previous shape,
|
||||
* then the following forward pass may fail.
|
||||
*/
|
||||
CV_WRAP void setParam(LayerId layer, int numParam, const Mat &blob);
|
||||
|
||||
/** @brief Returns parameter blob of the layer.
|
||||
* @param layer name or id of the layer.
|
||||
* @param numParam index of the layer parameter in the Layer::blobs array.
|
||||
* @see Layer::blobs
|
||||
*/
|
||||
CV_WRAP Mat getParam(LayerId layer, int numParam = 0);
|
||||
|
||||
/** @brief Returns indexes of layers with unconnected outputs.
|
||||
*/
|
||||
CV_WRAP std::vector<int> getUnconnectedOutLayers() const;
|
||||
/** @brief Returns input and output shapes for all layers in loaded model;
|
||||
* preliminary inferencing isn't necessary.
|
||||
* @param netInputShapes shapes for all input blobs in net input layer.
|
||||
* @param layersIds output parameter for layer IDs.
|
||||
* @param inLayersShapes output parameter for input layers shapes;
|
||||
* order is the same as in layersIds
|
||||
* @param outLayersShapes output parameter for output layers shapes;
|
||||
* order is the same as in layersIds
|
||||
*/
|
||||
CV_WRAP void getLayersShapes(const std::vector<MatShape>& netInputShapes,
|
||||
std::vector<int>* layersIds,
|
||||
std::vector<std::vector<MatShape> >* inLayersShapes,
|
||||
std::vector<std::vector<MatShape> >* outLayersShapes) const;
|
||||
|
||||
/** @overload */
|
||||
CV_WRAP void getLayersShapes(const MatShape& netInputShape,
|
||||
std::vector<int>* layersIds,
|
||||
std::vector<std::vector<MatShape> >* inLayersShapes,
|
||||
std::vector<std::vector<MatShape> >* outLayersShapes) const;
|
||||
|
||||
/** @brief Returns input and output shapes for layer with specified
|
||||
* id in loaded model; preliminary inferencing isn't necessary.
|
||||
* @param netInputShape shape input blob in net input layer.
|
||||
* @param layerId id for layer.
|
||||
* @param inLayerShapes output parameter for input layers shapes;
|
||||
* order is the same as in layersIds
|
||||
* @param outLayerShapes output parameter for output layers shapes;
|
||||
* order is the same as in layersIds
|
||||
*/
|
||||
CV_WRAP void getLayerShapes(const MatShape& netInputShape,
|
||||
const int layerId,
|
||||
std::vector<MatShape>* inLayerShapes,
|
||||
std::vector<MatShape>* outLayerShapes) const;
|
||||
|
||||
/** @overload */
|
||||
CV_WRAP void getLayerShapes(const std::vector<MatShape>& netInputShapes,
|
||||
const int layerId,
|
||||
std::vector<MatShape>* inLayerShapes,
|
||||
std::vector<MatShape>* outLayerShapes) const;
|
||||
/** @brief Computes FLOP for whole loaded model with specified input shapes.
|
||||
* @param netInputShapes vector of shapes for all net inputs.
|
||||
* @returns computed FLOP.
|
||||
*/
|
||||
CV_WRAP int64 getFLOPS(const std::vector<MatShape>& netInputShapes) const;
|
||||
/** @overload */
|
||||
CV_WRAP int64 getFLOPS(const MatShape& netInputShape) const;
|
||||
/** @overload */
|
||||
CV_WRAP int64 getFLOPS(const int layerId,
|
||||
const std::vector<MatShape>& netInputShapes) const;
|
||||
/** @overload */
|
||||
CV_WRAP int64 getFLOPS(const int layerId,
|
||||
const MatShape& netInputShape) const;
|
||||
|
||||
/** @brief Returns list of types for layer used in model.
|
||||
* @param layersTypes output parameter for returning types.
|
||||
*/
|
||||
CV_WRAP void getLayerTypes(std::vector<String>& layersTypes) const;
|
||||
|
||||
/** @brief Returns count of layers of specified type.
|
||||
* @param layerType type.
|
||||
* @returns count of layers
|
||||
*/
|
||||
CV_WRAP int getLayersCount(const String& layerType) const;
|
||||
|
||||
/** @brief Computes bytes number which are requered 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.
|
||||
* @param blobs output parameter to store resulting bytes for intermediate blobs.
|
||||
*/
|
||||
CV_WRAP void getMemoryConsumption(const std::vector<MatShape>& netInputShapes,
|
||||
size_t& weights, size_t& blobs) const;
|
||||
/** @overload */
|
||||
CV_WRAP void getMemoryConsumption(const MatShape& netInputShape,
|
||||
size_t& weights, size_t& blobs) const;
|
||||
/** @overload */
|
||||
CV_WRAP void getMemoryConsumption(const int layerId,
|
||||
const std::vector<MatShape>& netInputShapes,
|
||||
size_t& weights, size_t& blobs) const;
|
||||
/** @overload */
|
||||
CV_WRAP void getMemoryConsumption(const int layerId,
|
||||
const MatShape& netInputShape,
|
||||
size_t& weights, size_t& blobs) const;
|
||||
|
||||
/** @brief Computes bytes number which are requered 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.
|
||||
* @param weights output parameter to store resulting bytes for weights.
|
||||
* @param blobs output parameter to store resulting bytes for intermediate blobs.
|
||||
*/
|
||||
CV_WRAP void getMemoryConsumption(const std::vector<MatShape>& netInputShapes,
|
||||
std::vector<int>& layerIds, std::vector<size_t>& weights,
|
||||
std::vector<size_t>& blobs) const;
|
||||
/** @overload */
|
||||
CV_WRAP void getMemoryConsumption(const MatShape& netInputShape,
|
||||
std::vector<int>& layerIds, std::vector<size_t>& weights,
|
||||
std::vector<size_t>& blobs) const;
|
||||
private:
|
||||
|
||||
struct Impl;
|
||||
Ptr<Impl> impl;
|
||||
};
|
||||
|
||||
/** @brief Small interface class for loading trained serialized models of different dnn-frameworks. */
|
||||
class CV_EXPORTS_W Importer
|
||||
{
|
||||
public:
|
||||
|
||||
/** @brief Adds loaded layers into the @p net and sets connections between them. */
|
||||
CV_WRAP virtual void populateNet(Net net) = 0;
|
||||
|
||||
virtual ~Importer();
|
||||
};
|
||||
|
||||
/** @brief Creates the importer of <a href="http://caffe.berkeleyvision.org">Caffe</a> framework network.
|
||||
* @param prototxt path to the .prototxt file with text description of the network architecture.
|
||||
* @param caffeModel path to the .caffemodel file with learned network.
|
||||
* @returns Pointer to the created importer, NULL in failure cases.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<Importer> createCaffeImporter(const String &prototxt, const String &caffeModel = String());
|
||||
|
||||
/** @brief Reads a network model stored in Caffe model files.
|
||||
* @details This is shortcut consisting from createCaffeImporter and Net::populateNet calls.
|
||||
*/
|
||||
CV_EXPORTS_W Net readNetFromCaffe(const String &prototxt, const String &caffeModel = String());
|
||||
|
||||
/** @brief Reads a network model stored in Tensorflow model file.
|
||||
* @details This is shortcut consisting from createTensorflowImporter and Net::populateNet calls.
|
||||
*/
|
||||
CV_EXPORTS_W Net readNetFromTensorflow(const String &model);
|
||||
|
||||
/** @brief Reads a network model stored in Torch model file.
|
||||
* @details This is shortcut consisting from createTorchImporter and Net::populateNet calls.
|
||||
*/
|
||||
CV_EXPORTS_W Net readNetFromTorch(const String &model, bool isBinary = true);
|
||||
|
||||
/** @brief Creates the importer of <a href="http://www.tensorflow.org">TensorFlow</a> framework network.
|
||||
* @param model path to the .pb file with binary protobuf description of the network architecture.
|
||||
* @returns Pointer to the created importer, NULL in failure cases.
|
||||
*/
|
||||
CV_EXPORTS Ptr<Importer> createTensorflowImporter(const String &model);
|
||||
|
||||
/** @brief Creates the importer of <a href="http://torch.ch">Torch7</a> framework network.
|
||||
* @param filename path to the file, dumped from Torch by using torch.save() function.
|
||||
* @param isBinary specifies whether the network was serialized in ascii mode or binary.
|
||||
* @returns Pointer to the created importer, NULL in failure cases.
|
||||
*
|
||||
* @warning Torch7 importer is experimental now, you need explicitly set CMake `opencv_dnn_BUILD_TORCH_IMPORTER` flag to compile its.
|
||||
*
|
||||
* @note Ascii mode of Torch serializer is more preferable, because binary mode extensively use `long` type of C language,
|
||||
* which has various bit-length on different systems.
|
||||
*
|
||||
* The loading file must contain serialized <a href="https://github.com/torch/nn/blob/master/doc/module.md">nn.Module</a> object
|
||||
* with importing network. Try to eliminate a custom objects from serialazing data to avoid importing errors.
|
||||
*
|
||||
* List of supported layers (i.e. object instances derived from Torch nn.Module class):
|
||||
* - nn.Sequential
|
||||
* - nn.Parallel
|
||||
* - nn.Concat
|
||||
* - nn.Linear
|
||||
* - nn.SpatialConvolution
|
||||
* - nn.SpatialMaxPooling, nn.SpatialAveragePooling
|
||||
* - nn.ReLU, nn.TanH, nn.Sigmoid
|
||||
* - nn.Reshape
|
||||
* - nn.SoftMax, nn.LogSoftMax
|
||||
*
|
||||
* Also some equivalents of these classes from cunn, cudnn, and fbcunn may be successfully imported.
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<Importer> createTorchImporter(const String &filename, bool isBinary = true);
|
||||
|
||||
/** @brief Loads blob which was serialized as torch.Tensor object of Torch7 framework.
|
||||
* @warning This function has the same limitations as createTorchImporter().
|
||||
*/
|
||||
CV_EXPORTS_W Mat readTorchBlob(const String &filename, bool isBinary = true);
|
||||
/** @brief Creates 4-dimensional blob from image. Optionally resizes and crops @p image from center,
|
||||
* subtract @p mean values, scales values by @p scalefactor, swap Blue and Red channels.
|
||||
* @param image input image (with 1- or 3-channels).
|
||||
* @param size spatial size for output image
|
||||
* @param mean scalar with mean values which are subtracted from channels. Values are intended
|
||||
* to be in (mean-R, mean-G, mean-B) order if @p image has BGR ordering and @p swapRB is true.
|
||||
* @param scalefactor multiplier for @p image values.
|
||||
* @param swapRB flag which indicates that swap first and last channels
|
||||
* in 3-channel image is necessary.
|
||||
* @details input image is resized so one side after resize is equal to corresponing
|
||||
* dimension in @p size and another one is equal or larger. Then, crop from the center is performed.
|
||||
* @returns 4-dimansional Mat with NCHW dimensions order.
|
||||
*/
|
||||
CV_EXPORTS_W Mat blobFromImage(const Mat& image, double scalefactor=1.0, const Size& size = Size(),
|
||||
const Scalar& mean = Scalar(), bool swapRB=true);
|
||||
/** @brief Creates 4-dimensional blob from series of images. Optionally resizes and
|
||||
* crops @p images from center, subtract @p mean values, scales values by @p scalefactor,
|
||||
* swap Blue and Red channels.
|
||||
* @param images input images (all with 1- or 3-channels).
|
||||
* @param size spatial size for output image
|
||||
* @param mean scalar with mean values which are subtracted from channels. Values are intended
|
||||
* to be in (mean-R, mean-G, mean-B) order if @p image has BGR ordering and @p swapRB is true.
|
||||
* @param scalefactor multiplier for @p images values.
|
||||
* @param swapRB flag which indicates that swap first and last channels
|
||||
* in 3-channel image is necessary.
|
||||
* @details input image is resized so one side after resize is equal to corresponing
|
||||
* dimension in @p size and another one is equal or larger. Then, crop from the center is performed.
|
||||
* @returns 4-dimansional Mat with NCHW dimensions order.
|
||||
*/
|
||||
CV_EXPORTS_W Mat blobFromImages(const std::vector<Mat>& images, double scalefactor=1.0,
|
||||
Size size = Size(), const Scalar& mean = Scalar(), bool swapRB=true);
|
||||
|
||||
//! @}
|
||||
}
|
||||
}
|
||||
|
||||
#include <opencv2/dnn/layer.hpp>
|
||||
#include <opencv2/dnn/dnn.inl.hpp>
|
||||
|
||||
#endif /* __OPENCV_DNN_DNN_HPP__ */
|
357
modules/dnn/include/opencv2/dnn/dnn.inl.hpp
Normal file
357
modules/dnn/include/opencv2/dnn/dnn.inl.hpp
Normal file
@ -0,0 +1,357 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_DNN_DNN_INL_HPP
|
||||
#define OPENCV_DNN_DNN_INL_HPP
|
||||
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
template<typename TypeIter>
|
||||
DictValue DictValue::arrayInt(TypeIter begin, int size)
|
||||
{
|
||||
DictValue res(Param::INT, new AutoBuffer<int64, 1>(size));
|
||||
for (int j = 0; j < size; begin++, j++)
|
||||
(*res.pi)[j] = *begin;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename TypeIter>
|
||||
DictValue DictValue::arrayReal(TypeIter begin, int size)
|
||||
{
|
||||
DictValue res(Param::REAL, new AutoBuffer<double, 1>(size));
|
||||
for (int j = 0; j < size; begin++, j++)
|
||||
(*res.pd)[j] = *begin;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename TypeIter>
|
||||
DictValue DictValue::arrayString(TypeIter begin, int size)
|
||||
{
|
||||
DictValue res(Param::STRING, new AutoBuffer<String, 1>(size));
|
||||
for (int j = 0; j < size; begin++, j++)
|
||||
(*res.ps)[j] = *begin;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline DictValue DictValue::get<DictValue>(int idx) const
|
||||
{
|
||||
CV_Assert(idx == -1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int64 DictValue::get<int64>(int idx) const
|
||||
{
|
||||
CV_Assert((idx == -1 && size() == 1) || (idx >= 0 && idx < size()));
|
||||
idx = (idx == -1) ? 0 : idx;
|
||||
|
||||
if (type == Param::INT)
|
||||
{
|
||||
return (*pi)[idx];
|
||||
}
|
||||
else if (type == Param::REAL)
|
||||
{
|
||||
double doubleValue = (*pd)[idx];
|
||||
|
||||
double fracpart, intpart;
|
||||
fracpart = std::modf(doubleValue, &intpart);
|
||||
CV_Assert(fracpart == 0.0);
|
||||
|
||||
return (int64)doubleValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(isInt() || isReal());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int DictValue::get<int>(int idx) const
|
||||
{
|
||||
return (int)get<int64>(idx);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline unsigned DictValue::get<unsigned>(int idx) const
|
||||
{
|
||||
return (unsigned)get<int64>(idx);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool DictValue::get<bool>(int idx) const
|
||||
{
|
||||
return (get<int64>(idx) != 0);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline double DictValue::get<double>(int idx) const
|
||||
{
|
||||
CV_Assert((idx == -1 && size() == 1) || (idx >= 0 && idx < size()));
|
||||
idx = (idx == -1) ? 0 : idx;
|
||||
|
||||
if (type == Param::REAL)
|
||||
{
|
||||
return (*pd)[idx];
|
||||
}
|
||||
else if (type == Param::INT)
|
||||
{
|
||||
return (double)(*pi)[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(isReal() || isInt());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float DictValue::get<float>(int idx) const
|
||||
{
|
||||
return (float)get<double>(idx);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline String DictValue::get<String>(int idx) const
|
||||
{
|
||||
CV_Assert(isString());
|
||||
CV_Assert((idx == -1 && ps->size() == 1) || (idx >= 0 && idx < (int)ps->size()));
|
||||
return (*ps)[(idx == -1) ? 0 : idx];
|
||||
}
|
||||
|
||||
inline void DictValue::release()
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Param::INT:
|
||||
delete pi;
|
||||
break;
|
||||
case Param::STRING:
|
||||
delete ps;
|
||||
break;
|
||||
case Param::REAL:
|
||||
delete pd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline DictValue::~DictValue()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
inline DictValue & DictValue::operator=(const DictValue &r)
|
||||
{
|
||||
if (&r == this)
|
||||
return *this;
|
||||
|
||||
if (r.type == Param::INT)
|
||||
{
|
||||
AutoBuffer<int64, 1> *tmp = new AutoBuffer<int64, 1>(*r.pi);
|
||||
release();
|
||||
pi = tmp;
|
||||
}
|
||||
else if (r.type == Param::STRING)
|
||||
{
|
||||
AutoBuffer<String, 1> *tmp = new AutoBuffer<String, 1>(*r.ps);
|
||||
release();
|
||||
ps = tmp;
|
||||
}
|
||||
else if (r.type == Param::REAL)
|
||||
{
|
||||
AutoBuffer<double, 1> *tmp = new AutoBuffer<double, 1>(*r.pd);
|
||||
release();
|
||||
pd = tmp;
|
||||
}
|
||||
|
||||
type = r.type;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline DictValue::DictValue(const DictValue &r)
|
||||
{
|
||||
type = r.type;
|
||||
|
||||
if (r.type == Param::INT)
|
||||
pi = new AutoBuffer<int64, 1>(*r.pi);
|
||||
else if (r.type == Param::STRING)
|
||||
ps = new AutoBuffer<String, 1>(*r.ps);
|
||||
else if (r.type == Param::REAL)
|
||||
pd = new AutoBuffer<double, 1>(*r.pd);
|
||||
}
|
||||
|
||||
inline bool DictValue::isString() const
|
||||
{
|
||||
return (type == Param::STRING);
|
||||
}
|
||||
|
||||
inline bool DictValue::isInt() const
|
||||
{
|
||||
return (type == Param::INT);
|
||||
}
|
||||
|
||||
inline bool DictValue::isReal() const
|
||||
{
|
||||
return (type == Param::REAL || type == Param::INT);
|
||||
}
|
||||
|
||||
inline int DictValue::size() const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Param::INT:
|
||||
return (int)pi->size();
|
||||
break;
|
||||
case Param::STRING:
|
||||
return (int)ps->size();
|
||||
break;
|
||||
case Param::REAL:
|
||||
return (int)pd->size();
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsInternal, "");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream, const DictValue &dictv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dictv.isInt())
|
||||
{
|
||||
for (i = 0; i < dictv.size() - 1; i++)
|
||||
stream << dictv.get<int64>(i) << ", ";
|
||||
stream << dictv.get<int64>(i);
|
||||
}
|
||||
else if (dictv.isReal())
|
||||
{
|
||||
for (i = 0; i < dictv.size() - 1; i++)
|
||||
stream << dictv.get<double>(i) << ", ";
|
||||
stream << dictv.get<double>(i);
|
||||
}
|
||||
else if (dictv.isString())
|
||||
{
|
||||
for (i = 0; i < dictv.size() - 1; i++)
|
||||
stream << "\"" << dictv.get<String>(i) << "\", ";
|
||||
stream << dictv.get<String>(i);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool Dict::has(const String &key) const
|
||||
{
|
||||
return dict.count(key) != 0;
|
||||
}
|
||||
|
||||
inline DictValue *Dict::ptr(const String &key)
|
||||
{
|
||||
_Dict::iterator i = dict.find(key);
|
||||
return (i == dict.end()) ? NULL : &i->second;
|
||||
}
|
||||
|
||||
inline const DictValue *Dict::ptr(const String &key) const
|
||||
{
|
||||
_Dict::const_iterator i = dict.find(key);
|
||||
return (i == dict.end()) ? NULL : &i->second;
|
||||
}
|
||||
|
||||
inline const DictValue &Dict::get(const String &key) const
|
||||
{
|
||||
_Dict::const_iterator i = dict.find(key);
|
||||
if (i == dict.end())
|
||||
CV_Error(Error::StsObjectNotFound, "Required argument \"" + key + "\" not found into dictionary");
|
||||
return i->second;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T Dict::get(const String &key) const
|
||||
{
|
||||
return this->get(key).get<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T Dict::get(const String &key, const T &defaultValue) const
|
||||
{
|
||||
_Dict::const_iterator i = dict.find(key);
|
||||
|
||||
if (i != dict.end())
|
||||
return i->second.get<T>();
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const T &Dict::set(const String &key, const T &value)
|
||||
{
|
||||
_Dict::iterator i = dict.find(key);
|
||||
|
||||
if (i != dict.end())
|
||||
i->second = DictValue(value);
|
||||
else
|
||||
dict.insert(std::make_pair(key, DictValue(value)));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream, const Dict &dict)
|
||||
{
|
||||
Dict::_Dict::const_iterator it;
|
||||
for (it = dict.dict.begin(); it != dict.dict.end(); it++)
|
||||
stream << it->first << " : " << it->second << "\n";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
148
modules/dnn/include/opencv2/dnn/layer.hpp
Normal file
148
modules/dnn/include/opencv2/dnn/layer.hpp
Normal file
@ -0,0 +1,148 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_DNN_LAYER_HPP
|
||||
#define OPENCV_DNN_LAYER_HPP
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
//! @addtogroup dnn
|
||||
//! @{
|
||||
//!
|
||||
//! @defgroup dnnLayerFactory Utilities for New Layers Registration
|
||||
//! @{
|
||||
|
||||
/** @brief %Layer factory allows to create instances of registered layers. */
|
||||
class CV_EXPORTS LayerFactory
|
||||
{
|
||||
public:
|
||||
|
||||
//! Each Layer class must provide this function to the factory
|
||||
typedef Ptr<Layer>(*Constuctor)(LayerParams ¶ms);
|
||||
|
||||
//! Registers the layer class with typename @p type and specified @p constructor.
|
||||
static void registerLayer(const String &type, Constuctor constructor);
|
||||
|
||||
//! Unregisters registered layer with specified type name.
|
||||
static void unregisterLayer(const String &type);
|
||||
|
||||
/** @brief Creates instance of registered layer.
|
||||
* @param type type name of creating layer.
|
||||
* @param params parameters which will be used for layer initialization.
|
||||
*/
|
||||
static Ptr<Layer> createLayerInstance(const String &type, LayerParams& params);
|
||||
|
||||
private:
|
||||
LayerFactory();
|
||||
|
||||
struct Impl;
|
||||
static Ptr<Impl> impl();
|
||||
};
|
||||
|
||||
/** @brief Registers layer constructor in runtime.
|
||||
* @param type string, containing type name of the layer.
|
||||
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
|
||||
* @details This macros must be placed inside the function code.
|
||||
*/
|
||||
#define REG_RUNTIME_LAYER_FUNC(type, constuctorFunc) \
|
||||
cv::dnn::LayerFactory::registerLayer(#type, constuctorFunc);
|
||||
|
||||
/** @brief Registers layer class in runtime.
|
||||
* @param type string, containing type name of the layer.
|
||||
* @param class C++ class, derived from Layer.
|
||||
* @details This macros must be placed inside the function code.
|
||||
*/
|
||||
#define REG_RUNTIME_LAYER_CLASS(type, class) \
|
||||
cv::dnn::LayerFactory::registerLayer(#type, _layerDynamicRegisterer<class>);
|
||||
|
||||
/** @brief Registers layer constructor on module load time.
|
||||
* @param type string, containing type name of the layer.
|
||||
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
|
||||
* @details This macros must be placed outside the function code.
|
||||
*/
|
||||
#define REG_STATIC_LAYER_FUNC(type, constuctorFunc) \
|
||||
static cv::dnn::_LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, constuctorFunc);
|
||||
|
||||
/** @brief Registers layer class on module load time.
|
||||
* @param type string, containing type name of the layer.
|
||||
* @param class C++ class, derived from Layer.
|
||||
* @details This macros must be placed outside the function code.
|
||||
*/
|
||||
#define REG_STATIC_LAYER_CLASS(type, class) \
|
||||
Ptr<Layer> __LayerStaticRegisterer_func_##type(LayerParams ¶ms) \
|
||||
{ return Ptr<Layer>(new class(params)); } \
|
||||
static _LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, __LayerStaticRegisterer_func_##type);
|
||||
|
||||
|
||||
//! @}
|
||||
//! @}
|
||||
|
||||
|
||||
template<typename LayerClass>
|
||||
Ptr<Layer> _layerDynamicRegisterer(LayerParams ¶ms)
|
||||
{
|
||||
return Ptr<Layer>(LayerClass::create(params));
|
||||
}
|
||||
|
||||
//allows automatically register created layer on module load time
|
||||
class _LayerStaticRegisterer
|
||||
{
|
||||
String type;
|
||||
public:
|
||||
|
||||
_LayerStaticRegisterer(const String &layerType, LayerFactory::Constuctor layerConstuctor)
|
||||
{
|
||||
this->type = layerType;
|
||||
LayerFactory::registerLayer(layerType, layerConstuctor);
|
||||
}
|
||||
|
||||
~_LayerStaticRegisterer()
|
||||
{
|
||||
LayerFactory::unregisterLayer(type);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
195
modules/dnn/include/opencv2/dnn/shape_utils.hpp
Normal file
195
modules/dnn/include/opencv2/dnn/shape_utils.hpp
Normal file
@ -0,0 +1,195 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_DNN_DNN_SHAPE_UTILS_HPP
|
||||
#define OPENCV_DNN_DNN_SHAPE_UTILS_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/core/types_c.h>
|
||||
#include <ostream>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
|
||||
//Useful shortcut
|
||||
inline std::ostream &operator<< (std::ostream &s, cv::Range &r)
|
||||
{
|
||||
return s << "[" << r.start << ", " << r.end << ")";
|
||||
}
|
||||
|
||||
//Slicing
|
||||
|
||||
struct _Range : public cv::Range
|
||||
{
|
||||
_Range(const Range &r) : cv::Range(r) {}
|
||||
_Range(int start_, int size_ = 1) : cv::Range(start_, start_ + size_) {}
|
||||
};
|
||||
|
||||
static inline Mat slice(const Mat &m, const _Range &r0)
|
||||
{
|
||||
Range ranges[CV_MAX_DIM];
|
||||
for (int i = 1; i < m.dims; i++)
|
||||
ranges[i] = Range::all();
|
||||
ranges[0] = r0;
|
||||
return m(&ranges[0]);
|
||||
}
|
||||
|
||||
static inline Mat slice(const Mat &m, const _Range &r0, const _Range &r1)
|
||||
{
|
||||
CV_Assert(m.dims >= 2);
|
||||
Range ranges[CV_MAX_DIM];
|
||||
for (int i = 2; i < m.dims; i++)
|
||||
ranges[i] = Range::all();
|
||||
ranges[0] = r0;
|
||||
ranges[1] = r1;
|
||||
return m(&ranges[0]);
|
||||
}
|
||||
|
||||
static inline Mat slice(const Mat &m, const _Range &r0, const _Range &r1, const _Range &r2)
|
||||
{
|
||||
CV_Assert(m.dims >= 3);
|
||||
Range ranges[CV_MAX_DIM];
|
||||
for (int i = 3; i < m.dims; i++)
|
||||
ranges[i] = Range::all();
|
||||
ranges[0] = r0;
|
||||
ranges[1] = r1;
|
||||
ranges[2] = r2;
|
||||
return m(&ranges[0]);
|
||||
}
|
||||
|
||||
static inline Mat slice(const Mat &m, const _Range &r0, const _Range &r1, const _Range &r2, const _Range &r3)
|
||||
{
|
||||
CV_Assert(m.dims >= 4);
|
||||
Range ranges[CV_MAX_DIM];
|
||||
for (int i = 4; i < m.dims; i++)
|
||||
ranges[i] = Range::all();
|
||||
ranges[0] = r0;
|
||||
ranges[1] = r1;
|
||||
ranges[2] = r2;
|
||||
ranges[3] = r3;
|
||||
return m(&ranges[0]);
|
||||
}
|
||||
|
||||
static inline Mat getPlane(const Mat &m, int n, int cn)
|
||||
{
|
||||
CV_Assert(m.dims > 2);
|
||||
Range range[CV_MAX_DIM];
|
||||
int sz[CV_MAX_DIM];
|
||||
for(int i = 2; i < m.dims; i++)
|
||||
{
|
||||
sz[i-2] = m.size.p[i];
|
||||
range[i] = Range::all();
|
||||
}
|
||||
range[0] = Range(n, n+1);
|
||||
range[1] = Range(cn, cn+1);
|
||||
return m(range).reshape(1, m.dims-2, sz);
|
||||
}
|
||||
|
||||
static inline MatShape shape(const int* dims, const int n = 4)
|
||||
{
|
||||
MatShape shape;
|
||||
shape.assign(dims, dims + n);
|
||||
return shape;
|
||||
}
|
||||
|
||||
static inline MatShape shape(const Mat& mat)
|
||||
{
|
||||
return shape(mat.size.p, mat.dims);
|
||||
}
|
||||
|
||||
namespace {inline bool is_neg(int i) { return i < 0; }}
|
||||
|
||||
static inline MatShape shape(int a0, int a1=-1, int a2=-1, int a3=-1)
|
||||
{
|
||||
int dims[] = {a0, a1, a2, a3};
|
||||
MatShape s = shape(dims);
|
||||
s.erase(std::remove_if(s.begin(), s.end(), is_neg), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline int total(const MatShape& shape, int start = -1, int end = -1)
|
||||
{
|
||||
if (start == -1) start = 0;
|
||||
if (end == -1) end = (int)shape.size();
|
||||
|
||||
if (shape.empty())
|
||||
return 0;
|
||||
|
||||
int elems = 1;
|
||||
CV_Assert(start < (int)shape.size() && end <= (int)shape.size() &&
|
||||
start <= end);
|
||||
for(int i = start; i < end; i++)
|
||||
{
|
||||
elems *= shape[i];
|
||||
}
|
||||
return elems;
|
||||
}
|
||||
|
||||
static inline MatShape concat(const MatShape& a, const MatShape& b)
|
||||
{
|
||||
MatShape c = a;
|
||||
c.insert(c.end(), b.begin(), b.end());
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
inline void print(const MatShape& shape, const String& name = "")
|
||||
{
|
||||
printf("%s: [", name.c_str());
|
||||
size_t i, n = shape.size();
|
||||
for( i = 0; i < n; i++ )
|
||||
printf(" %d", shape[i]);
|
||||
printf(" ]\n");
|
||||
}
|
||||
|
||||
inline int clamp(int ax, int dims)
|
||||
{
|
||||
return ax < 0 ? ax + dims : ax;
|
||||
}
|
||||
|
||||
inline int clamp(int ax, const MatShape& shape)
|
||||
{
|
||||
return clamp(ax, (int)shape.size());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
53676
modules/dnn/misc/caffe/caffe.pb.cc
Normal file
53676
modules/dnn/misc/caffe/caffe.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
28612
modules/dnn/misc/caffe/caffe.pb.h
Normal file
28612
modules/dnn/misc/caffe/caffe.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
39
modules/dnn/misc/python/pyopencv_dnn.hpp
Normal file
39
modules/dnn/misc/python/pyopencv_dnn.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
typedef dnn::DictValue LayerId;
|
||||
typedef std::vector<dnn::MatShape> vector_MatShape;
|
||||
typedef std::vector<std::vector<dnn::MatShape> > vector_vector_MatShape;
|
||||
typedef std::vector<size_t> vector_size_t;
|
||||
typedef std::vector<std::vector<Mat> > vector_vector_Mat;
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject *o, dnn::DictValue &dv, const char *name)
|
||||
{
|
||||
(void)name;
|
||||
if (!o || o == Py_None)
|
||||
return true; //Current state will be used
|
||||
else if (PyLong_Check(o))
|
||||
{
|
||||
dv = dnn::DictValue((int64)PyLong_AsLongLong(o));
|
||||
return true;
|
||||
}
|
||||
else if (PyFloat_Check(o))
|
||||
{
|
||||
dv = dnn::DictValue(PyFloat_AS_DOUBLE(o));
|
||||
return true;
|
||||
}
|
||||
else if (PyString_Check(o))
|
||||
{
|
||||
dv = dnn::DictValue(String(PyString_AsString(o)));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject *o, std::vector<Mat> &blobs, const char *name) //required for Layer::blobs RW
|
||||
{
|
||||
return pyopencvVecConverter<Mat>::to(o, blobs, ArgInfo(name, false));
|
||||
}
|
||||
|
||||
#endif
|
3014
modules/dnn/misc/tensorflow/attr_value.pb.cc
Normal file
3014
modules/dnn/misc/tensorflow/attr_value.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
1697
modules/dnn/misc/tensorflow/attr_value.pb.h
Normal file
1697
modules/dnn/misc/tensorflow/attr_value.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
2348
modules/dnn/misc/tensorflow/function.pb.cc
Normal file
2348
modules/dnn/misc/tensorflow/function.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
1160
modules/dnn/misc/tensorflow/function.pb.h
Normal file
1160
modules/dnn/misc/tensorflow/function.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
1687
modules/dnn/misc/tensorflow/graph.pb.cc
Normal file
1687
modules/dnn/misc/tensorflow/graph.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
814
modules/dnn/misc/tensorflow/graph.pb.h
Normal file
814
modules/dnn/misc/tensorflow/graph.pb.h
Normal file
@ -0,0 +1,814 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: graph.proto
|
||||
|
||||
#ifndef PROTOBUF_graph_2eproto__INCLUDED
|
||||
#define PROTOBUF_graph_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3001000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3001000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_field_inl.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include "attr_value.pb.h"
|
||||
#include "function.pb.h"
|
||||
#include "versions.pb.h"
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
// Internal implementation detail -- do not call these.
|
||||
void protobuf_AddDesc_graph_2eproto();
|
||||
void protobuf_InitDefaults_graph_2eproto();
|
||||
void protobuf_AssignDesc_graph_2eproto();
|
||||
void protobuf_ShutdownFile_graph_2eproto();
|
||||
|
||||
class GraphDef;
|
||||
class NodeDef;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class GraphDef : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:tensorflow.GraphDef) */ {
|
||||
public:
|
||||
GraphDef();
|
||||
virtual ~GraphDef();
|
||||
|
||||
GraphDef(const GraphDef& from);
|
||||
|
||||
inline GraphDef& operator=(const GraphDef& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
|
||||
inline void* GetMaybeArenaPointer() const {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const GraphDef& default_instance();
|
||||
|
||||
static const GraphDef* internal_default_instance();
|
||||
|
||||
void UnsafeArenaSwap(GraphDef* other);
|
||||
void Swap(GraphDef* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline GraphDef* New() const { return New(NULL); }
|
||||
|
||||
GraphDef* New(::google::protobuf::Arena* arena) const;
|
||||
void CopyFrom(const ::google::protobuf::Message& from);
|
||||
void MergeFrom(const ::google::protobuf::Message& from);
|
||||
void CopyFrom(const GraphDef& from);
|
||||
void MergeFrom(const GraphDef& from);
|
||||
void Clear();
|
||||
bool IsInitialized() const;
|
||||
|
||||
size_t ByteSizeLong() const;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input);
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* output) const;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
|
||||
return InternalSerializeWithCachedSizesToArray(false, output);
|
||||
}
|
||||
int GetCachedSize() const { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(GraphDef* other);
|
||||
void UnsafeMergeFrom(const GraphDef& from);
|
||||
protected:
|
||||
explicit GraphDef(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return _internal_metadata_.raw_arena_ptr();
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// repeated .tensorflow.NodeDef node = 1;
|
||||
int node_size() const;
|
||||
void clear_node();
|
||||
static const int kNodeFieldNumber = 1;
|
||||
const ::tensorflow::NodeDef& node(int index) const;
|
||||
::tensorflow::NodeDef* mutable_node(int index);
|
||||
::tensorflow::NodeDef* add_node();
|
||||
::google::protobuf::RepeatedPtrField< ::tensorflow::NodeDef >*
|
||||
mutable_node();
|
||||
const ::google::protobuf::RepeatedPtrField< ::tensorflow::NodeDef >&
|
||||
node() const;
|
||||
|
||||
// optional .tensorflow.VersionDef versions = 4;
|
||||
bool has_versions() const;
|
||||
void clear_versions();
|
||||
static const int kVersionsFieldNumber = 4;
|
||||
private:
|
||||
void _slow_mutable_versions();
|
||||
void _slow_set_allocated_versions(
|
||||
::google::protobuf::Arena* message_arena, ::tensorflow::VersionDef** versions);
|
||||
::tensorflow::VersionDef* _slow_release_versions();
|
||||
public:
|
||||
const ::tensorflow::VersionDef& versions() const;
|
||||
::tensorflow::VersionDef* mutable_versions();
|
||||
::tensorflow::VersionDef* release_versions();
|
||||
void set_allocated_versions(::tensorflow::VersionDef* versions);
|
||||
::tensorflow::VersionDef* unsafe_arena_release_versions();
|
||||
void unsafe_arena_set_allocated_versions(
|
||||
::tensorflow::VersionDef* versions);
|
||||
|
||||
// optional int32 version = 3 [deprecated = true];
|
||||
GOOGLE_PROTOBUF_DEPRECATED_ATTR void clear_version();
|
||||
GOOGLE_PROTOBUF_DEPRECATED_ATTR static const int kVersionFieldNumber = 3;
|
||||
GOOGLE_PROTOBUF_DEPRECATED_ATTR ::google::protobuf::int32 version() const;
|
||||
GOOGLE_PROTOBUF_DEPRECATED_ATTR void set_version(::google::protobuf::int32 value);
|
||||
|
||||
// optional .tensorflow.FunctionDefLibrary library = 2;
|
||||
bool has_library() const;
|
||||
void clear_library();
|
||||
static const int kLibraryFieldNumber = 2;
|
||||
private:
|
||||
void _slow_mutable_library();
|
||||
void _slow_set_allocated_library(
|
||||
::google::protobuf::Arena* message_arena, ::tensorflow::FunctionDefLibrary** library);
|
||||
::tensorflow::FunctionDefLibrary* _slow_release_library();
|
||||
public:
|
||||
const ::tensorflow::FunctionDefLibrary& library() const;
|
||||
::tensorflow::FunctionDefLibrary* mutable_library();
|
||||
::tensorflow::FunctionDefLibrary* release_library();
|
||||
void set_allocated_library(::tensorflow::FunctionDefLibrary* library);
|
||||
::tensorflow::FunctionDefLibrary* unsafe_arena_release_library();
|
||||
void unsafe_arena_set_allocated_library(
|
||||
::tensorflow::FunctionDefLibrary* library);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:tensorflow.GraphDef)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::RepeatedPtrField< ::tensorflow::NodeDef > node_;
|
||||
::tensorflow::VersionDef* versions_;
|
||||
::tensorflow::FunctionDefLibrary* library_;
|
||||
::google::protobuf::int32 version_;
|
||||
mutable int _cached_size_;
|
||||
friend void protobuf_InitDefaults_graph_2eproto_impl();
|
||||
friend void protobuf_AddDesc_graph_2eproto_impl();
|
||||
friend void protobuf_AssignDesc_graph_2eproto();
|
||||
friend void protobuf_ShutdownFile_graph_2eproto();
|
||||
|
||||
void InitAsDefaultInstance();
|
||||
};
|
||||
extern ::google::protobuf::internal::ExplicitlyConstructed<GraphDef> GraphDef_default_instance_;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
class NodeDef : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:tensorflow.NodeDef) */ {
|
||||
public:
|
||||
NodeDef();
|
||||
virtual ~NodeDef();
|
||||
|
||||
NodeDef(const NodeDef& from);
|
||||
|
||||
inline NodeDef& operator=(const NodeDef& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
|
||||
inline void* GetMaybeArenaPointer() const {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const NodeDef& default_instance();
|
||||
|
||||
static const NodeDef* internal_default_instance();
|
||||
|
||||
void UnsafeArenaSwap(NodeDef* other);
|
||||
void Swap(NodeDef* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline NodeDef* New() const { return New(NULL); }
|
||||
|
||||
NodeDef* New(::google::protobuf::Arena* arena) const;
|
||||
void CopyFrom(const ::google::protobuf::Message& from);
|
||||
void MergeFrom(const ::google::protobuf::Message& from);
|
||||
void CopyFrom(const NodeDef& from);
|
||||
void MergeFrom(const NodeDef& from);
|
||||
void Clear();
|
||||
bool IsInitialized() const;
|
||||
|
||||
size_t ByteSizeLong() const;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input);
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* output) const;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
|
||||
return InternalSerializeWithCachedSizesToArray(false, output);
|
||||
}
|
||||
int GetCachedSize() const { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(NodeDef* other);
|
||||
void UnsafeMergeFrom(const NodeDef& from);
|
||||
protected:
|
||||
explicit NodeDef(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return _internal_metadata_.raw_arena_ptr();
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// optional string name = 1;
|
||||
void clear_name();
|
||||
static const int kNameFieldNumber = 1;
|
||||
const ::std::string& name() const;
|
||||
void set_name(const ::std::string& value);
|
||||
void set_name(const char* value);
|
||||
void set_name(const char* value, size_t size);
|
||||
::std::string* mutable_name();
|
||||
::std::string* release_name();
|
||||
void set_allocated_name(::std::string* name);
|
||||
::std::string* unsafe_arena_release_name();
|
||||
void unsafe_arena_set_allocated_name(
|
||||
::std::string* name);
|
||||
|
||||
// optional string op = 2;
|
||||
void clear_op();
|
||||
static const int kOpFieldNumber = 2;
|
||||
const ::std::string& op() const;
|
||||
void set_op(const ::std::string& value);
|
||||
void set_op(const char* value);
|
||||
void set_op(const char* value, size_t size);
|
||||
::std::string* mutable_op();
|
||||
::std::string* release_op();
|
||||
void set_allocated_op(::std::string* op);
|
||||
::std::string* unsafe_arena_release_op();
|
||||
void unsafe_arena_set_allocated_op(
|
||||
::std::string* op);
|
||||
|
||||
// repeated string input = 3;
|
||||
int input_size() const;
|
||||
void clear_input();
|
||||
static const int kInputFieldNumber = 3;
|
||||
const ::std::string& input(int index) const;
|
||||
::std::string* mutable_input(int index);
|
||||
void set_input(int index, const ::std::string& value);
|
||||
void set_input(int index, const char* value);
|
||||
void set_input(int index, const char* value, size_t size);
|
||||
::std::string* add_input();
|
||||
void add_input(const ::std::string& value);
|
||||
void add_input(const char* value);
|
||||
void add_input(const char* value, size_t size);
|
||||
const ::google::protobuf::RepeatedPtrField< ::std::string>& input() const;
|
||||
::google::protobuf::RepeatedPtrField< ::std::string>* mutable_input();
|
||||
|
||||
// optional string device = 4;
|
||||
void clear_device();
|
||||
static const int kDeviceFieldNumber = 4;
|
||||
const ::std::string& device() const;
|
||||
void set_device(const ::std::string& value);
|
||||
void set_device(const char* value);
|
||||
void set_device(const char* value, size_t size);
|
||||
::std::string* mutable_device();
|
||||
::std::string* release_device();
|
||||
void set_allocated_device(::std::string* device);
|
||||
::std::string* unsafe_arena_release_device();
|
||||
void unsafe_arena_set_allocated_device(
|
||||
::std::string* device);
|
||||
|
||||
// map<string, .tensorflow.AttrValue> attr = 5;
|
||||
int attr_size() const;
|
||||
void clear_attr();
|
||||
static const int kAttrFieldNumber = 5;
|
||||
const ::google::protobuf::Map< ::std::string, ::tensorflow::AttrValue >&
|
||||
attr() const;
|
||||
::google::protobuf::Map< ::std::string, ::tensorflow::AttrValue >*
|
||||
mutable_attr();
|
||||
|
||||
// @@protoc_insertion_point(class_scope:tensorflow.NodeDef)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::RepeatedPtrField< ::std::string> input_;
|
||||
typedef ::google::protobuf::internal::MapEntryLite<
|
||||
::std::string, ::tensorflow::AttrValue,
|
||||
::google::protobuf::internal::WireFormatLite::TYPE_STRING,
|
||||
::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
|
||||
0 >
|
||||
NodeDef_AttrEntry;
|
||||
::google::protobuf::internal::MapField<
|
||||
::std::string, ::tensorflow::AttrValue,
|
||||
::google::protobuf::internal::WireFormatLite::TYPE_STRING,
|
||||
::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE,
|
||||
0 > attr_;
|
||||
::google::protobuf::internal::ArenaStringPtr name_;
|
||||
::google::protobuf::internal::ArenaStringPtr op_;
|
||||
::google::protobuf::internal::ArenaStringPtr device_;
|
||||
mutable int _cached_size_;
|
||||
friend void protobuf_InitDefaults_graph_2eproto_impl();
|
||||
friend void protobuf_AddDesc_graph_2eproto_impl();
|
||||
friend void protobuf_AssignDesc_graph_2eproto();
|
||||
friend void protobuf_ShutdownFile_graph_2eproto();
|
||||
|
||||
void InitAsDefaultInstance();
|
||||
};
|
||||
extern ::google::protobuf::internal::ExplicitlyConstructed<NodeDef> NodeDef_default_instance_;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// GraphDef
|
||||
|
||||
// repeated .tensorflow.NodeDef node = 1;
|
||||
inline int GraphDef::node_size() const {
|
||||
return node_.size();
|
||||
}
|
||||
inline void GraphDef::clear_node() {
|
||||
node_.Clear();
|
||||
}
|
||||
inline const ::tensorflow::NodeDef& GraphDef::node(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.GraphDef.node)
|
||||
return node_.Get(index);
|
||||
}
|
||||
inline ::tensorflow::NodeDef* GraphDef::mutable_node(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.GraphDef.node)
|
||||
return node_.Mutable(index);
|
||||
}
|
||||
inline ::tensorflow::NodeDef* GraphDef::add_node() {
|
||||
// @@protoc_insertion_point(field_add:tensorflow.GraphDef.node)
|
||||
return node_.Add();
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::tensorflow::NodeDef >*
|
||||
GraphDef::mutable_node() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.GraphDef.node)
|
||||
return &node_;
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::tensorflow::NodeDef >&
|
||||
GraphDef::node() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.GraphDef.node)
|
||||
return node_;
|
||||
}
|
||||
|
||||
// optional .tensorflow.VersionDef versions = 4;
|
||||
inline bool GraphDef::has_versions() const {
|
||||
return this != internal_default_instance() && versions_ != NULL;
|
||||
}
|
||||
inline void GraphDef::clear_versions() {
|
||||
if (GetArenaNoVirtual() == NULL && versions_ != NULL) delete versions_;
|
||||
versions_ = NULL;
|
||||
}
|
||||
inline const ::tensorflow::VersionDef& GraphDef::versions() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.GraphDef.versions)
|
||||
return versions_ != NULL ? *versions_
|
||||
: *::tensorflow::VersionDef::internal_default_instance();
|
||||
}
|
||||
inline ::tensorflow::VersionDef* GraphDef::mutable_versions() {
|
||||
|
||||
if (versions_ == NULL) {
|
||||
_slow_mutable_versions();
|
||||
}
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.GraphDef.versions)
|
||||
return versions_;
|
||||
}
|
||||
inline ::tensorflow::VersionDef* GraphDef::release_versions() {
|
||||
// @@protoc_insertion_point(field_release:tensorflow.GraphDef.versions)
|
||||
|
||||
if (GetArenaNoVirtual() != NULL) {
|
||||
return _slow_release_versions();
|
||||
} else {
|
||||
::tensorflow::VersionDef* temp = versions_;
|
||||
versions_ = NULL;
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
inline void GraphDef::set_allocated_versions(::tensorflow::VersionDef* versions) {
|
||||
::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
|
||||
if (message_arena == NULL) {
|
||||
delete versions_;
|
||||
}
|
||||
if (versions != NULL) {
|
||||
_slow_set_allocated_versions(message_arena, &versions);
|
||||
}
|
||||
versions_ = versions;
|
||||
if (versions) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
// @@protoc_insertion_point(field_set_allocated:tensorflow.GraphDef.versions)
|
||||
}
|
||||
|
||||
// optional int32 version = 3 [deprecated = true];
|
||||
inline void GraphDef::clear_version() {
|
||||
version_ = 0;
|
||||
}
|
||||
inline ::google::protobuf::int32 GraphDef::version() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.GraphDef.version)
|
||||
return version_;
|
||||
}
|
||||
inline void GraphDef::set_version(::google::protobuf::int32 value) {
|
||||
|
||||
version_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.GraphDef.version)
|
||||
}
|
||||
|
||||
// optional .tensorflow.FunctionDefLibrary library = 2;
|
||||
inline bool GraphDef::has_library() const {
|
||||
return this != internal_default_instance() && library_ != NULL;
|
||||
}
|
||||
inline void GraphDef::clear_library() {
|
||||
if (GetArenaNoVirtual() == NULL && library_ != NULL) delete library_;
|
||||
library_ = NULL;
|
||||
}
|
||||
inline const ::tensorflow::FunctionDefLibrary& GraphDef::library() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.GraphDef.library)
|
||||
return library_ != NULL ? *library_
|
||||
: *::tensorflow::FunctionDefLibrary::internal_default_instance();
|
||||
}
|
||||
inline ::tensorflow::FunctionDefLibrary* GraphDef::mutable_library() {
|
||||
|
||||
if (library_ == NULL) {
|
||||
_slow_mutable_library();
|
||||
}
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.GraphDef.library)
|
||||
return library_;
|
||||
}
|
||||
inline ::tensorflow::FunctionDefLibrary* GraphDef::release_library() {
|
||||
// @@protoc_insertion_point(field_release:tensorflow.GraphDef.library)
|
||||
|
||||
if (GetArenaNoVirtual() != NULL) {
|
||||
return _slow_release_library();
|
||||
} else {
|
||||
::tensorflow::FunctionDefLibrary* temp = library_;
|
||||
library_ = NULL;
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
inline void GraphDef::set_allocated_library(::tensorflow::FunctionDefLibrary* library) {
|
||||
::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
|
||||
if (message_arena == NULL) {
|
||||
delete library_;
|
||||
}
|
||||
if (library != NULL) {
|
||||
_slow_set_allocated_library(message_arena, &library);
|
||||
}
|
||||
library_ = library;
|
||||
if (library) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
// @@protoc_insertion_point(field_set_allocated:tensorflow.GraphDef.library)
|
||||
}
|
||||
|
||||
inline const GraphDef* GraphDef::internal_default_instance() {
|
||||
return &GraphDef_default_instance_.get();
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// NodeDef
|
||||
|
||||
// optional string name = 1;
|
||||
inline void NodeDef::clear_name() {
|
||||
name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline const ::std::string& NodeDef::name() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.NodeDef.name)
|
||||
return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void NodeDef::set_name(const ::std::string& value) {
|
||||
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set:tensorflow.NodeDef.name)
|
||||
}
|
||||
inline void NodeDef::set_name(const char* value) {
|
||||
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_char:tensorflow.NodeDef.name)
|
||||
}
|
||||
inline void NodeDef::set_name(const char* value,
|
||||
size_t size) {
|
||||
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_pointer:tensorflow.NodeDef.name)
|
||||
}
|
||||
inline ::std::string* NodeDef::mutable_name() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.NodeDef.name)
|
||||
return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* NodeDef::release_name() {
|
||||
// @@protoc_insertion_point(field_release:tensorflow.NodeDef.name)
|
||||
|
||||
return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* NodeDef::unsafe_arena_release_name() {
|
||||
// @@protoc_insertion_point(field_unsafe_arena_release:tensorflow.NodeDef.name)
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
|
||||
return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
}
|
||||
inline void NodeDef::set_allocated_name(::std::string* name) {
|
||||
if (name != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:tensorflow.NodeDef.name)
|
||||
}
|
||||
inline void NodeDef::unsafe_arena_set_allocated_name(
|
||||
::std::string* name) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (name != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
name, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_unsafe_arena_set_allocated:tensorflow.NodeDef.name)
|
||||
}
|
||||
|
||||
// optional string op = 2;
|
||||
inline void NodeDef::clear_op() {
|
||||
op_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline const ::std::string& NodeDef::op() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.NodeDef.op)
|
||||
return op_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void NodeDef::set_op(const ::std::string& value) {
|
||||
|
||||
op_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set:tensorflow.NodeDef.op)
|
||||
}
|
||||
inline void NodeDef::set_op(const char* value) {
|
||||
|
||||
op_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_char:tensorflow.NodeDef.op)
|
||||
}
|
||||
inline void NodeDef::set_op(const char* value,
|
||||
size_t size) {
|
||||
|
||||
op_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_pointer:tensorflow.NodeDef.op)
|
||||
}
|
||||
inline ::std::string* NodeDef::mutable_op() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.NodeDef.op)
|
||||
return op_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* NodeDef::release_op() {
|
||||
// @@protoc_insertion_point(field_release:tensorflow.NodeDef.op)
|
||||
|
||||
return op_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* NodeDef::unsafe_arena_release_op() {
|
||||
// @@protoc_insertion_point(field_unsafe_arena_release:tensorflow.NodeDef.op)
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
|
||||
return op_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
}
|
||||
inline void NodeDef::set_allocated_op(::std::string* op) {
|
||||
if (op != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
op_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), op,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:tensorflow.NodeDef.op)
|
||||
}
|
||||
inline void NodeDef::unsafe_arena_set_allocated_op(
|
||||
::std::string* op) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (op != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
op_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
op, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_unsafe_arena_set_allocated:tensorflow.NodeDef.op)
|
||||
}
|
||||
|
||||
// repeated string input = 3;
|
||||
inline int NodeDef::input_size() const {
|
||||
return input_.size();
|
||||
}
|
||||
inline void NodeDef::clear_input() {
|
||||
input_.Clear();
|
||||
}
|
||||
inline const ::std::string& NodeDef::input(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.NodeDef.input)
|
||||
return input_.Get(index);
|
||||
}
|
||||
inline ::std::string* NodeDef::mutable_input(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.NodeDef.input)
|
||||
return input_.Mutable(index);
|
||||
}
|
||||
inline void NodeDef::set_input(int index, const ::std::string& value) {
|
||||
// @@protoc_insertion_point(field_set:tensorflow.NodeDef.input)
|
||||
input_.Mutable(index)->assign(value);
|
||||
}
|
||||
inline void NodeDef::set_input(int index, const char* value) {
|
||||
input_.Mutable(index)->assign(value);
|
||||
// @@protoc_insertion_point(field_set_char:tensorflow.NodeDef.input)
|
||||
}
|
||||
inline void NodeDef::set_input(int index, const char* value, size_t size) {
|
||||
input_.Mutable(index)->assign(
|
||||
reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_set_pointer:tensorflow.NodeDef.input)
|
||||
}
|
||||
inline ::std::string* NodeDef::add_input() {
|
||||
// @@protoc_insertion_point(field_add_mutable:tensorflow.NodeDef.input)
|
||||
return input_.Add();
|
||||
}
|
||||
inline void NodeDef::add_input(const ::std::string& value) {
|
||||
input_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.NodeDef.input)
|
||||
}
|
||||
inline void NodeDef::add_input(const char* value) {
|
||||
input_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add_char:tensorflow.NodeDef.input)
|
||||
}
|
||||
inline void NodeDef::add_input(const char* value, size_t size) {
|
||||
input_.Add()->assign(reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_add_pointer:tensorflow.NodeDef.input)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
|
||||
NodeDef::input() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.NodeDef.input)
|
||||
return input_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::std::string>*
|
||||
NodeDef::mutable_input() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.NodeDef.input)
|
||||
return &input_;
|
||||
}
|
||||
|
||||
// optional string device = 4;
|
||||
inline void NodeDef::clear_device() {
|
||||
device_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline const ::std::string& NodeDef::device() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.NodeDef.device)
|
||||
return device_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void NodeDef::set_device(const ::std::string& value) {
|
||||
|
||||
device_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set:tensorflow.NodeDef.device)
|
||||
}
|
||||
inline void NodeDef::set_device(const char* value) {
|
||||
|
||||
device_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_char:tensorflow.NodeDef.device)
|
||||
}
|
||||
inline void NodeDef::set_device(const char* value,
|
||||
size_t size) {
|
||||
|
||||
device_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_pointer:tensorflow.NodeDef.device)
|
||||
}
|
||||
inline ::std::string* NodeDef::mutable_device() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.NodeDef.device)
|
||||
return device_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* NodeDef::release_device() {
|
||||
// @@protoc_insertion_point(field_release:tensorflow.NodeDef.device)
|
||||
|
||||
return device_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* NodeDef::unsafe_arena_release_device() {
|
||||
// @@protoc_insertion_point(field_unsafe_arena_release:tensorflow.NodeDef.device)
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
|
||||
return device_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
}
|
||||
inline void NodeDef::set_allocated_device(::std::string* device) {
|
||||
if (device != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
device_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), device,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:tensorflow.NodeDef.device)
|
||||
}
|
||||
inline void NodeDef::unsafe_arena_set_allocated_device(
|
||||
::std::string* device) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (device != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
device_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
device, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_unsafe_arena_set_allocated:tensorflow.NodeDef.device)
|
||||
}
|
||||
|
||||
// map<string, .tensorflow.AttrValue> attr = 5;
|
||||
inline int NodeDef::attr_size() const {
|
||||
return attr_.size();
|
||||
}
|
||||
inline void NodeDef::clear_attr() {
|
||||
attr_.Clear();
|
||||
}
|
||||
inline const ::google::protobuf::Map< ::std::string, ::tensorflow::AttrValue >&
|
||||
NodeDef::attr() const {
|
||||
// @@protoc_insertion_point(field_map:tensorflow.NodeDef.attr)
|
||||
return attr_.GetMap();
|
||||
}
|
||||
inline ::google::protobuf::Map< ::std::string, ::tensorflow::AttrValue >*
|
||||
NodeDef::mutable_attr() {
|
||||
// @@protoc_insertion_point(field_mutable_map:tensorflow.NodeDef.attr)
|
||||
return attr_.MutableMap();
|
||||
}
|
||||
|
||||
inline const NodeDef* NodeDef::internal_default_instance() {
|
||||
return &NodeDef_default_instance_.get();
|
||||
}
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace tensorflow
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_graph_2eproto__INCLUDED
|
4045
modules/dnn/misc/tensorflow/op_def.pb.cc
Normal file
4045
modules/dnn/misc/tensorflow/op_def.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
2103
modules/dnn/misc/tensorflow/op_def.pb.h
Normal file
2103
modules/dnn/misc/tensorflow/op_def.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
1596
modules/dnn/misc/tensorflow/tensor.pb.cc
Normal file
1596
modules/dnn/misc/tensorflow/tensor.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
770
modules/dnn/misc/tensorflow/tensor.pb.h
Normal file
770
modules/dnn/misc/tensorflow/tensor.pb.h
Normal file
@ -0,0 +1,770 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: tensor.proto
|
||||
|
||||
#ifndef PROTOBUF_tensor_2eproto__INCLUDED
|
||||
#define PROTOBUF_tensor_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3001000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3001000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include "tensor_shape.pb.h"
|
||||
#include "types.pb.h"
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
// Internal implementation detail -- do not call these.
|
||||
void protobuf_AddDesc_tensor_2eproto();
|
||||
void protobuf_InitDefaults_tensor_2eproto();
|
||||
void protobuf_AssignDesc_tensor_2eproto();
|
||||
void protobuf_ShutdownFile_tensor_2eproto();
|
||||
|
||||
class TensorProto;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class TensorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:tensorflow.TensorProto) */ {
|
||||
public:
|
||||
TensorProto();
|
||||
virtual ~TensorProto();
|
||||
|
||||
TensorProto(const TensorProto& from);
|
||||
|
||||
inline TensorProto& operator=(const TensorProto& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
|
||||
inline void* GetMaybeArenaPointer() const {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const TensorProto& default_instance();
|
||||
|
||||
static const TensorProto* internal_default_instance();
|
||||
|
||||
void UnsafeArenaSwap(TensorProto* other);
|
||||
void Swap(TensorProto* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline TensorProto* New() const { return New(NULL); }
|
||||
|
||||
TensorProto* New(::google::protobuf::Arena* arena) const;
|
||||
void CopyFrom(const ::google::protobuf::Message& from);
|
||||
void MergeFrom(const ::google::protobuf::Message& from);
|
||||
void CopyFrom(const TensorProto& from);
|
||||
void MergeFrom(const TensorProto& from);
|
||||
void Clear();
|
||||
bool IsInitialized() const;
|
||||
|
||||
size_t ByteSizeLong() const;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input);
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* output) const;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
|
||||
return InternalSerializeWithCachedSizesToArray(false, output);
|
||||
}
|
||||
int GetCachedSize() const { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(TensorProto* other);
|
||||
void UnsafeMergeFrom(const TensorProto& from);
|
||||
protected:
|
||||
explicit TensorProto(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return _internal_metadata_.raw_arena_ptr();
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// optional .tensorflow.DataType dtype = 1;
|
||||
void clear_dtype();
|
||||
static const int kDtypeFieldNumber = 1;
|
||||
::tensorflow::DataType dtype() const;
|
||||
void set_dtype(::tensorflow::DataType value);
|
||||
|
||||
// optional .tensorflow.TensorShapeProto tensor_shape = 2;
|
||||
bool has_tensor_shape() const;
|
||||
void clear_tensor_shape();
|
||||
static const int kTensorShapeFieldNumber = 2;
|
||||
private:
|
||||
void _slow_mutable_tensor_shape();
|
||||
void _slow_set_allocated_tensor_shape(
|
||||
::google::protobuf::Arena* message_arena, ::tensorflow::TensorShapeProto** tensor_shape);
|
||||
::tensorflow::TensorShapeProto* _slow_release_tensor_shape();
|
||||
public:
|
||||
const ::tensorflow::TensorShapeProto& tensor_shape() const;
|
||||
::tensorflow::TensorShapeProto* mutable_tensor_shape();
|
||||
::tensorflow::TensorShapeProto* release_tensor_shape();
|
||||
void set_allocated_tensor_shape(::tensorflow::TensorShapeProto* tensor_shape);
|
||||
::tensorflow::TensorShapeProto* unsafe_arena_release_tensor_shape();
|
||||
void unsafe_arena_set_allocated_tensor_shape(
|
||||
::tensorflow::TensorShapeProto* tensor_shape);
|
||||
|
||||
// optional int32 version_number = 3;
|
||||
void clear_version_number();
|
||||
static const int kVersionNumberFieldNumber = 3;
|
||||
::google::protobuf::int32 version_number() const;
|
||||
void set_version_number(::google::protobuf::int32 value);
|
||||
|
||||
// optional bytes tensor_content = 4;
|
||||
void clear_tensor_content();
|
||||
static const int kTensorContentFieldNumber = 4;
|
||||
const ::std::string& tensor_content() const;
|
||||
void set_tensor_content(const ::std::string& value);
|
||||
void set_tensor_content(const char* value);
|
||||
void set_tensor_content(const void* value, size_t size);
|
||||
::std::string* mutable_tensor_content();
|
||||
::std::string* release_tensor_content();
|
||||
void set_allocated_tensor_content(::std::string* tensor_content);
|
||||
::std::string* unsafe_arena_release_tensor_content();
|
||||
void unsafe_arena_set_allocated_tensor_content(
|
||||
::std::string* tensor_content);
|
||||
|
||||
// repeated int32 half_val = 13 [packed = true];
|
||||
int half_val_size() const;
|
||||
void clear_half_val();
|
||||
static const int kHalfValFieldNumber = 13;
|
||||
::google::protobuf::int32 half_val(int index) const;
|
||||
void set_half_val(int index, ::google::protobuf::int32 value);
|
||||
void add_half_val(::google::protobuf::int32 value);
|
||||
const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
|
||||
half_val() const;
|
||||
::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
|
||||
mutable_half_val();
|
||||
|
||||
// repeated float float_val = 5 [packed = true];
|
||||
int float_val_size() const;
|
||||
void clear_float_val();
|
||||
static const int kFloatValFieldNumber = 5;
|
||||
float float_val(int index) const;
|
||||
void set_float_val(int index, float value);
|
||||
void add_float_val(float value);
|
||||
const ::google::protobuf::RepeatedField< float >&
|
||||
float_val() const;
|
||||
::google::protobuf::RepeatedField< float >*
|
||||
mutable_float_val();
|
||||
|
||||
// repeated double double_val = 6 [packed = true];
|
||||
int double_val_size() const;
|
||||
void clear_double_val();
|
||||
static const int kDoubleValFieldNumber = 6;
|
||||
double double_val(int index) const;
|
||||
void set_double_val(int index, double value);
|
||||
void add_double_val(double value);
|
||||
const ::google::protobuf::RepeatedField< double >&
|
||||
double_val() const;
|
||||
::google::protobuf::RepeatedField< double >*
|
||||
mutable_double_val();
|
||||
|
||||
// repeated int32 int_val = 7 [packed = true];
|
||||
int int_val_size() const;
|
||||
void clear_int_val();
|
||||
static const int kIntValFieldNumber = 7;
|
||||
::google::protobuf::int32 int_val(int index) const;
|
||||
void set_int_val(int index, ::google::protobuf::int32 value);
|
||||
void add_int_val(::google::protobuf::int32 value);
|
||||
const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
|
||||
int_val() const;
|
||||
::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
|
||||
mutable_int_val();
|
||||
|
||||
// repeated bytes string_val = 8;
|
||||
int string_val_size() const;
|
||||
void clear_string_val();
|
||||
static const int kStringValFieldNumber = 8;
|
||||
const ::std::string& string_val(int index) const;
|
||||
::std::string* mutable_string_val(int index);
|
||||
void set_string_val(int index, const ::std::string& value);
|
||||
void set_string_val(int index, const char* value);
|
||||
void set_string_val(int index, const void* value, size_t size);
|
||||
::std::string* add_string_val();
|
||||
void add_string_val(const ::std::string& value);
|
||||
void add_string_val(const char* value);
|
||||
void add_string_val(const void* value, size_t size);
|
||||
const ::google::protobuf::RepeatedPtrField< ::std::string>& string_val() const;
|
||||
::google::protobuf::RepeatedPtrField< ::std::string>* mutable_string_val();
|
||||
|
||||
// repeated float scomplex_val = 9 [packed = true];
|
||||
int scomplex_val_size() const;
|
||||
void clear_scomplex_val();
|
||||
static const int kScomplexValFieldNumber = 9;
|
||||
float scomplex_val(int index) const;
|
||||
void set_scomplex_val(int index, float value);
|
||||
void add_scomplex_val(float value);
|
||||
const ::google::protobuf::RepeatedField< float >&
|
||||
scomplex_val() const;
|
||||
::google::protobuf::RepeatedField< float >*
|
||||
mutable_scomplex_val();
|
||||
|
||||
// repeated int64 int64_val = 10 [packed = true];
|
||||
int int64_val_size() const;
|
||||
void clear_int64_val();
|
||||
static const int kInt64ValFieldNumber = 10;
|
||||
::google::protobuf::int64 int64_val(int index) const;
|
||||
void set_int64_val(int index, ::google::protobuf::int64 value);
|
||||
void add_int64_val(::google::protobuf::int64 value);
|
||||
const ::google::protobuf::RepeatedField< ::google::protobuf::int64 >&
|
||||
int64_val() const;
|
||||
::google::protobuf::RepeatedField< ::google::protobuf::int64 >*
|
||||
mutable_int64_val();
|
||||
|
||||
// repeated bool bool_val = 11 [packed = true];
|
||||
int bool_val_size() const;
|
||||
void clear_bool_val();
|
||||
static const int kBoolValFieldNumber = 11;
|
||||
bool bool_val(int index) const;
|
||||
void set_bool_val(int index, bool value);
|
||||
void add_bool_val(bool value);
|
||||
const ::google::protobuf::RepeatedField< bool >&
|
||||
bool_val() const;
|
||||
::google::protobuf::RepeatedField< bool >*
|
||||
mutable_bool_val();
|
||||
|
||||
// repeated double dcomplex_val = 12 [packed = true];
|
||||
int dcomplex_val_size() const;
|
||||
void clear_dcomplex_val();
|
||||
static const int kDcomplexValFieldNumber = 12;
|
||||
double dcomplex_val(int index) const;
|
||||
void set_dcomplex_val(int index, double value);
|
||||
void add_dcomplex_val(double value);
|
||||
const ::google::protobuf::RepeatedField< double >&
|
||||
dcomplex_val() const;
|
||||
::google::protobuf::RepeatedField< double >*
|
||||
mutable_dcomplex_val();
|
||||
|
||||
// @@protoc_insertion_point(class_scope:tensorflow.TensorProto)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::RepeatedField< ::google::protobuf::int32 > half_val_;
|
||||
mutable int _half_val_cached_byte_size_;
|
||||
::google::protobuf::RepeatedField< float > float_val_;
|
||||
mutable int _float_val_cached_byte_size_;
|
||||
::google::protobuf::RepeatedField< double > double_val_;
|
||||
mutable int _double_val_cached_byte_size_;
|
||||
::google::protobuf::RepeatedField< ::google::protobuf::int32 > int_val_;
|
||||
mutable int _int_val_cached_byte_size_;
|
||||
::google::protobuf::RepeatedPtrField< ::std::string> string_val_;
|
||||
::google::protobuf::RepeatedField< float > scomplex_val_;
|
||||
mutable int _scomplex_val_cached_byte_size_;
|
||||
::google::protobuf::RepeatedField< ::google::protobuf::int64 > int64_val_;
|
||||
mutable int _int64_val_cached_byte_size_;
|
||||
::google::protobuf::RepeatedField< bool > bool_val_;
|
||||
mutable int _bool_val_cached_byte_size_;
|
||||
::google::protobuf::RepeatedField< double > dcomplex_val_;
|
||||
mutable int _dcomplex_val_cached_byte_size_;
|
||||
::google::protobuf::internal::ArenaStringPtr tensor_content_;
|
||||
::tensorflow::TensorShapeProto* tensor_shape_;
|
||||
int dtype_;
|
||||
::google::protobuf::int32 version_number_;
|
||||
mutable int _cached_size_;
|
||||
friend void protobuf_InitDefaults_tensor_2eproto_impl();
|
||||
friend void protobuf_AddDesc_tensor_2eproto_impl();
|
||||
friend void protobuf_AssignDesc_tensor_2eproto();
|
||||
friend void protobuf_ShutdownFile_tensor_2eproto();
|
||||
|
||||
void InitAsDefaultInstance();
|
||||
};
|
||||
extern ::google::protobuf::internal::ExplicitlyConstructed<TensorProto> TensorProto_default_instance_;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// TensorProto
|
||||
|
||||
// optional .tensorflow.DataType dtype = 1;
|
||||
inline void TensorProto::clear_dtype() {
|
||||
dtype_ = 0;
|
||||
}
|
||||
inline ::tensorflow::DataType TensorProto::dtype() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.dtype)
|
||||
return static_cast< ::tensorflow::DataType >(dtype_);
|
||||
}
|
||||
inline void TensorProto::set_dtype(::tensorflow::DataType value) {
|
||||
|
||||
dtype_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.dtype)
|
||||
}
|
||||
|
||||
// optional .tensorflow.TensorShapeProto tensor_shape = 2;
|
||||
inline bool TensorProto::has_tensor_shape() const {
|
||||
return this != internal_default_instance() && tensor_shape_ != NULL;
|
||||
}
|
||||
inline void TensorProto::clear_tensor_shape() {
|
||||
if (GetArenaNoVirtual() == NULL && tensor_shape_ != NULL) delete tensor_shape_;
|
||||
tensor_shape_ = NULL;
|
||||
}
|
||||
inline const ::tensorflow::TensorShapeProto& TensorProto::tensor_shape() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.tensor_shape)
|
||||
return tensor_shape_ != NULL ? *tensor_shape_
|
||||
: *::tensorflow::TensorShapeProto::internal_default_instance();
|
||||
}
|
||||
inline ::tensorflow::TensorShapeProto* TensorProto::mutable_tensor_shape() {
|
||||
|
||||
if (tensor_shape_ == NULL) {
|
||||
_slow_mutable_tensor_shape();
|
||||
}
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.TensorProto.tensor_shape)
|
||||
return tensor_shape_;
|
||||
}
|
||||
inline ::tensorflow::TensorShapeProto* TensorProto::release_tensor_shape() {
|
||||
// @@protoc_insertion_point(field_release:tensorflow.TensorProto.tensor_shape)
|
||||
|
||||
if (GetArenaNoVirtual() != NULL) {
|
||||
return _slow_release_tensor_shape();
|
||||
} else {
|
||||
::tensorflow::TensorShapeProto* temp = tensor_shape_;
|
||||
tensor_shape_ = NULL;
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
inline void TensorProto::set_allocated_tensor_shape(::tensorflow::TensorShapeProto* tensor_shape) {
|
||||
::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
|
||||
if (message_arena == NULL) {
|
||||
delete tensor_shape_;
|
||||
}
|
||||
if (tensor_shape != NULL) {
|
||||
_slow_set_allocated_tensor_shape(message_arena, &tensor_shape);
|
||||
}
|
||||
tensor_shape_ = tensor_shape;
|
||||
if (tensor_shape) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
// @@protoc_insertion_point(field_set_allocated:tensorflow.TensorProto.tensor_shape)
|
||||
}
|
||||
|
||||
// optional int32 version_number = 3;
|
||||
inline void TensorProto::clear_version_number() {
|
||||
version_number_ = 0;
|
||||
}
|
||||
inline ::google::protobuf::int32 TensorProto::version_number() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.version_number)
|
||||
return version_number_;
|
||||
}
|
||||
inline void TensorProto::set_version_number(::google::protobuf::int32 value) {
|
||||
|
||||
version_number_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.version_number)
|
||||
}
|
||||
|
||||
// optional bytes tensor_content = 4;
|
||||
inline void TensorProto::clear_tensor_content() {
|
||||
tensor_content_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline const ::std::string& TensorProto::tensor_content() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.tensor_content)
|
||||
return tensor_content_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void TensorProto::set_tensor_content(const ::std::string& value) {
|
||||
|
||||
tensor_content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.tensor_content)
|
||||
}
|
||||
inline void TensorProto::set_tensor_content(const char* value) {
|
||||
|
||||
tensor_content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_char:tensorflow.TensorProto.tensor_content)
|
||||
}
|
||||
inline void TensorProto::set_tensor_content(const void* value,
|
||||
size_t size) {
|
||||
|
||||
tensor_content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_pointer:tensorflow.TensorProto.tensor_content)
|
||||
}
|
||||
inline ::std::string* TensorProto::mutable_tensor_content() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.TensorProto.tensor_content)
|
||||
return tensor_content_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* TensorProto::release_tensor_content() {
|
||||
// @@protoc_insertion_point(field_release:tensorflow.TensorProto.tensor_content)
|
||||
|
||||
return tensor_content_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* TensorProto::unsafe_arena_release_tensor_content() {
|
||||
// @@protoc_insertion_point(field_unsafe_arena_release:tensorflow.TensorProto.tensor_content)
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
|
||||
return tensor_content_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
}
|
||||
inline void TensorProto::set_allocated_tensor_content(::std::string* tensor_content) {
|
||||
if (tensor_content != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
tensor_content_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), tensor_content,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:tensorflow.TensorProto.tensor_content)
|
||||
}
|
||||
inline void TensorProto::unsafe_arena_set_allocated_tensor_content(
|
||||
::std::string* tensor_content) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (tensor_content != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
tensor_content_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
tensor_content, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_unsafe_arena_set_allocated:tensorflow.TensorProto.tensor_content)
|
||||
}
|
||||
|
||||
// repeated int32 half_val = 13 [packed = true];
|
||||
inline int TensorProto::half_val_size() const {
|
||||
return half_val_.size();
|
||||
}
|
||||
inline void TensorProto::clear_half_val() {
|
||||
half_val_.Clear();
|
||||
}
|
||||
inline ::google::protobuf::int32 TensorProto::half_val(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.half_val)
|
||||
return half_val_.Get(index);
|
||||
}
|
||||
inline void TensorProto::set_half_val(int index, ::google::protobuf::int32 value) {
|
||||
half_val_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.half_val)
|
||||
}
|
||||
inline void TensorProto::add_half_val(::google::protobuf::int32 value) {
|
||||
half_val_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorProto.half_val)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
|
||||
TensorProto::half_val() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorProto.half_val)
|
||||
return half_val_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
|
||||
TensorProto::mutable_half_val() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorProto.half_val)
|
||||
return &half_val_;
|
||||
}
|
||||
|
||||
// repeated float float_val = 5 [packed = true];
|
||||
inline int TensorProto::float_val_size() const {
|
||||
return float_val_.size();
|
||||
}
|
||||
inline void TensorProto::clear_float_val() {
|
||||
float_val_.Clear();
|
||||
}
|
||||
inline float TensorProto::float_val(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.float_val)
|
||||
return float_val_.Get(index);
|
||||
}
|
||||
inline void TensorProto::set_float_val(int index, float value) {
|
||||
float_val_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.float_val)
|
||||
}
|
||||
inline void TensorProto::add_float_val(float value) {
|
||||
float_val_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorProto.float_val)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedField< float >&
|
||||
TensorProto::float_val() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorProto.float_val)
|
||||
return float_val_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedField< float >*
|
||||
TensorProto::mutable_float_val() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorProto.float_val)
|
||||
return &float_val_;
|
||||
}
|
||||
|
||||
// repeated double double_val = 6 [packed = true];
|
||||
inline int TensorProto::double_val_size() const {
|
||||
return double_val_.size();
|
||||
}
|
||||
inline void TensorProto::clear_double_val() {
|
||||
double_val_.Clear();
|
||||
}
|
||||
inline double TensorProto::double_val(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.double_val)
|
||||
return double_val_.Get(index);
|
||||
}
|
||||
inline void TensorProto::set_double_val(int index, double value) {
|
||||
double_val_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.double_val)
|
||||
}
|
||||
inline void TensorProto::add_double_val(double value) {
|
||||
double_val_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorProto.double_val)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedField< double >&
|
||||
TensorProto::double_val() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorProto.double_val)
|
||||
return double_val_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedField< double >*
|
||||
TensorProto::mutable_double_val() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorProto.double_val)
|
||||
return &double_val_;
|
||||
}
|
||||
|
||||
// repeated int32 int_val = 7 [packed = true];
|
||||
inline int TensorProto::int_val_size() const {
|
||||
return int_val_.size();
|
||||
}
|
||||
inline void TensorProto::clear_int_val() {
|
||||
int_val_.Clear();
|
||||
}
|
||||
inline ::google::protobuf::int32 TensorProto::int_val(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.int_val)
|
||||
return int_val_.Get(index);
|
||||
}
|
||||
inline void TensorProto::set_int_val(int index, ::google::protobuf::int32 value) {
|
||||
int_val_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.int_val)
|
||||
}
|
||||
inline void TensorProto::add_int_val(::google::protobuf::int32 value) {
|
||||
int_val_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorProto.int_val)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
|
||||
TensorProto::int_val() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorProto.int_val)
|
||||
return int_val_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
|
||||
TensorProto::mutable_int_val() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorProto.int_val)
|
||||
return &int_val_;
|
||||
}
|
||||
|
||||
// repeated bytes string_val = 8;
|
||||
inline int TensorProto::string_val_size() const {
|
||||
return string_val_.size();
|
||||
}
|
||||
inline void TensorProto::clear_string_val() {
|
||||
string_val_.Clear();
|
||||
}
|
||||
inline const ::std::string& TensorProto::string_val(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.string_val)
|
||||
return string_val_.Get(index);
|
||||
}
|
||||
inline ::std::string* TensorProto::mutable_string_val(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.TensorProto.string_val)
|
||||
return string_val_.Mutable(index);
|
||||
}
|
||||
inline void TensorProto::set_string_val(int index, const ::std::string& value) {
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.string_val)
|
||||
string_val_.Mutable(index)->assign(value);
|
||||
}
|
||||
inline void TensorProto::set_string_val(int index, const char* value) {
|
||||
string_val_.Mutable(index)->assign(value);
|
||||
// @@protoc_insertion_point(field_set_char:tensorflow.TensorProto.string_val)
|
||||
}
|
||||
inline void TensorProto::set_string_val(int index, const void* value, size_t size) {
|
||||
string_val_.Mutable(index)->assign(
|
||||
reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_set_pointer:tensorflow.TensorProto.string_val)
|
||||
}
|
||||
inline ::std::string* TensorProto::add_string_val() {
|
||||
// @@protoc_insertion_point(field_add_mutable:tensorflow.TensorProto.string_val)
|
||||
return string_val_.Add();
|
||||
}
|
||||
inline void TensorProto::add_string_val(const ::std::string& value) {
|
||||
string_val_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorProto.string_val)
|
||||
}
|
||||
inline void TensorProto::add_string_val(const char* value) {
|
||||
string_val_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add_char:tensorflow.TensorProto.string_val)
|
||||
}
|
||||
inline void TensorProto::add_string_val(const void* value, size_t size) {
|
||||
string_val_.Add()->assign(reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_add_pointer:tensorflow.TensorProto.string_val)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
|
||||
TensorProto::string_val() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorProto.string_val)
|
||||
return string_val_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::std::string>*
|
||||
TensorProto::mutable_string_val() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorProto.string_val)
|
||||
return &string_val_;
|
||||
}
|
||||
|
||||
// repeated float scomplex_val = 9 [packed = true];
|
||||
inline int TensorProto::scomplex_val_size() const {
|
||||
return scomplex_val_.size();
|
||||
}
|
||||
inline void TensorProto::clear_scomplex_val() {
|
||||
scomplex_val_.Clear();
|
||||
}
|
||||
inline float TensorProto::scomplex_val(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.scomplex_val)
|
||||
return scomplex_val_.Get(index);
|
||||
}
|
||||
inline void TensorProto::set_scomplex_val(int index, float value) {
|
||||
scomplex_val_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.scomplex_val)
|
||||
}
|
||||
inline void TensorProto::add_scomplex_val(float value) {
|
||||
scomplex_val_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorProto.scomplex_val)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedField< float >&
|
||||
TensorProto::scomplex_val() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorProto.scomplex_val)
|
||||
return scomplex_val_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedField< float >*
|
||||
TensorProto::mutable_scomplex_val() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorProto.scomplex_val)
|
||||
return &scomplex_val_;
|
||||
}
|
||||
|
||||
// repeated int64 int64_val = 10 [packed = true];
|
||||
inline int TensorProto::int64_val_size() const {
|
||||
return int64_val_.size();
|
||||
}
|
||||
inline void TensorProto::clear_int64_val() {
|
||||
int64_val_.Clear();
|
||||
}
|
||||
inline ::google::protobuf::int64 TensorProto::int64_val(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.int64_val)
|
||||
return int64_val_.Get(index);
|
||||
}
|
||||
inline void TensorProto::set_int64_val(int index, ::google::protobuf::int64 value) {
|
||||
int64_val_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.int64_val)
|
||||
}
|
||||
inline void TensorProto::add_int64_val(::google::protobuf::int64 value) {
|
||||
int64_val_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorProto.int64_val)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedField< ::google::protobuf::int64 >&
|
||||
TensorProto::int64_val() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorProto.int64_val)
|
||||
return int64_val_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedField< ::google::protobuf::int64 >*
|
||||
TensorProto::mutable_int64_val() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorProto.int64_val)
|
||||
return &int64_val_;
|
||||
}
|
||||
|
||||
// repeated bool bool_val = 11 [packed = true];
|
||||
inline int TensorProto::bool_val_size() const {
|
||||
return bool_val_.size();
|
||||
}
|
||||
inline void TensorProto::clear_bool_val() {
|
||||
bool_val_.Clear();
|
||||
}
|
||||
inline bool TensorProto::bool_val(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.bool_val)
|
||||
return bool_val_.Get(index);
|
||||
}
|
||||
inline void TensorProto::set_bool_val(int index, bool value) {
|
||||
bool_val_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.bool_val)
|
||||
}
|
||||
inline void TensorProto::add_bool_val(bool value) {
|
||||
bool_val_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorProto.bool_val)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedField< bool >&
|
||||
TensorProto::bool_val() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorProto.bool_val)
|
||||
return bool_val_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedField< bool >*
|
||||
TensorProto::mutable_bool_val() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorProto.bool_val)
|
||||
return &bool_val_;
|
||||
}
|
||||
|
||||
// repeated double dcomplex_val = 12 [packed = true];
|
||||
inline int TensorProto::dcomplex_val_size() const {
|
||||
return dcomplex_val_.size();
|
||||
}
|
||||
inline void TensorProto::clear_dcomplex_val() {
|
||||
dcomplex_val_.Clear();
|
||||
}
|
||||
inline double TensorProto::dcomplex_val(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorProto.dcomplex_val)
|
||||
return dcomplex_val_.Get(index);
|
||||
}
|
||||
inline void TensorProto::set_dcomplex_val(int index, double value) {
|
||||
dcomplex_val_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorProto.dcomplex_val)
|
||||
}
|
||||
inline void TensorProto::add_dcomplex_val(double value) {
|
||||
dcomplex_val_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorProto.dcomplex_val)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedField< double >&
|
||||
TensorProto::dcomplex_val() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorProto.dcomplex_val)
|
||||
return dcomplex_val_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedField< double >*
|
||||
TensorProto::mutable_dcomplex_val() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorProto.dcomplex_val)
|
||||
return &dcomplex_val_;
|
||||
}
|
||||
|
||||
inline const TensorProto* TensorProto::internal_default_instance() {
|
||||
return &TensorProto_default_instance_.get();
|
||||
}
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace tensorflow
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_tensor_2eproto__INCLUDED
|
895
modules/dnn/misc/tensorflow/tensor_shape.pb.cc
Normal file
895
modules/dnn/misc/tensorflow/tensor_shape.pb.cc
Normal file
@ -0,0 +1,895 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: tensor_shape.proto
|
||||
|
||||
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
||||
#include "tensor_shape.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
namespace {
|
||||
|
||||
const ::google::protobuf::Descriptor* TensorShapeProto_descriptor_ = NULL;
|
||||
const ::google::protobuf::internal::GeneratedMessageReflection*
|
||||
TensorShapeProto_reflection_ = NULL;
|
||||
const ::google::protobuf::Descriptor* TensorShapeProto_Dim_descriptor_ = NULL;
|
||||
const ::google::protobuf::internal::GeneratedMessageReflection*
|
||||
TensorShapeProto_Dim_reflection_ = NULL;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void protobuf_AssignDesc_tensor_5fshape_2eproto() GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_AssignDesc_tensor_5fshape_2eproto() {
|
||||
protobuf_AddDesc_tensor_5fshape_2eproto();
|
||||
const ::google::protobuf::FileDescriptor* file =
|
||||
::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
|
||||
"tensor_shape.proto");
|
||||
GOOGLE_CHECK(file != NULL);
|
||||
TensorShapeProto_descriptor_ = file->message_type(0);
|
||||
static const int TensorShapeProto_offsets_[2] = {
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TensorShapeProto, dim_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TensorShapeProto, unknown_rank_),
|
||||
};
|
||||
TensorShapeProto_reflection_ =
|
||||
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
|
||||
TensorShapeProto_descriptor_,
|
||||
TensorShapeProto::internal_default_instance(),
|
||||
TensorShapeProto_offsets_,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
sizeof(TensorShapeProto),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TensorShapeProto, _internal_metadata_));
|
||||
TensorShapeProto_Dim_descriptor_ = TensorShapeProto_descriptor_->nested_type(0);
|
||||
static const int TensorShapeProto_Dim_offsets_[2] = {
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TensorShapeProto_Dim, size_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TensorShapeProto_Dim, name_),
|
||||
};
|
||||
TensorShapeProto_Dim_reflection_ =
|
||||
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
|
||||
TensorShapeProto_Dim_descriptor_,
|
||||
TensorShapeProto_Dim::internal_default_instance(),
|
||||
TensorShapeProto_Dim_offsets_,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
sizeof(TensorShapeProto_Dim),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TensorShapeProto_Dim, _internal_metadata_));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
|
||||
&protobuf_AssignDesc_tensor_5fshape_2eproto);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
|
||||
TensorShapeProto_descriptor_, TensorShapeProto::internal_default_instance());
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
|
||||
TensorShapeProto_Dim_descriptor_, TensorShapeProto_Dim::internal_default_instance());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void protobuf_ShutdownFile_tensor_5fshape_2eproto() {
|
||||
TensorShapeProto_default_instance_.Shutdown();
|
||||
delete TensorShapeProto_reflection_;
|
||||
TensorShapeProto_Dim_default_instance_.Shutdown();
|
||||
delete TensorShapeProto_Dim_reflection_;
|
||||
}
|
||||
|
||||
void protobuf_InitDefaults_tensor_5fshape_2eproto_impl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
TensorShapeProto_default_instance_.DefaultConstruct();
|
||||
::google::protobuf::internal::GetEmptyString();
|
||||
TensorShapeProto_Dim_default_instance_.DefaultConstruct();
|
||||
TensorShapeProto_default_instance_.get_mutable()->InitAsDefaultInstance();
|
||||
TensorShapeProto_Dim_default_instance_.get_mutable()->InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_InitDefaults_tensor_5fshape_2eproto_once_);
|
||||
void protobuf_InitDefaults_tensor_5fshape_2eproto() {
|
||||
::google::protobuf::GoogleOnceInit(&protobuf_InitDefaults_tensor_5fshape_2eproto_once_,
|
||||
&protobuf_InitDefaults_tensor_5fshape_2eproto_impl);
|
||||
}
|
||||
void protobuf_AddDesc_tensor_5fshape_2eproto_impl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
protobuf_InitDefaults_tensor_5fshape_2eproto();
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
"\n\022tensor_shape.proto\022\ntensorflow\"z\n\020Tens"
|
||||
"orShapeProto\022-\n\003dim\030\002 \003(\0132 .tensorflow.T"
|
||||
"ensorShapeProto.Dim\022\024\n\014unknown_rank\030\003 \001("
|
||||
"\010\032!\n\003Dim\022\014\n\004size\030\001 \001(\003\022\014\n\004name\030\002 \001(\tB2\n\030"
|
||||
"org.tensorflow.frameworkB\021TensorShapePro"
|
||||
"tosP\001\370\001\001b\006proto3", 216);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"tensor_shape.proto", &protobuf_RegisterTypes);
|
||||
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_tensor_5fshape_2eproto);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AddDesc_tensor_5fshape_2eproto_once_);
|
||||
void protobuf_AddDesc_tensor_5fshape_2eproto() {
|
||||
::google::protobuf::GoogleOnceInit(&protobuf_AddDesc_tensor_5fshape_2eproto_once_,
|
||||
&protobuf_AddDesc_tensor_5fshape_2eproto_impl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at static initialization time.
|
||||
struct StaticDescriptorInitializer_tensor_5fshape_2eproto {
|
||||
StaticDescriptorInitializer_tensor_5fshape_2eproto() {
|
||||
protobuf_AddDesc_tensor_5fshape_2eproto();
|
||||
}
|
||||
} static_descriptor_initializer_tensor_5fshape_2eproto_;
|
||||
|
||||
namespace {
|
||||
|
||||
static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD GOOGLE_ATTRIBUTE_NORETURN;
|
||||
static void MergeFromFail(int line) {
|
||||
::google::protobuf::internal::MergeFromFail(__FILE__, line);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int TensorShapeProto_Dim::kSizeFieldNumber;
|
||||
const int TensorShapeProto_Dim::kNameFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
TensorShapeProto_Dim::TensorShapeProto_Dim()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
|
||||
if (this != internal_default_instance()) protobuf_InitDefaults_tensor_5fshape_2eproto();
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:tensorflow.TensorShapeProto.Dim)
|
||||
}
|
||||
TensorShapeProto_Dim::TensorShapeProto_Dim(::google::protobuf::Arena* arena)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(arena) {
|
||||
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
|
||||
protobuf_InitDefaults_tensor_5fshape_2eproto();
|
||||
#endif // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
|
||||
SharedCtor();
|
||||
RegisterArenaDtor(arena);
|
||||
// @@protoc_insertion_point(arena_constructor:tensorflow.TensorShapeProto.Dim)
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::InitAsDefaultInstance() {
|
||||
}
|
||||
|
||||
TensorShapeProto_Dim::TensorShapeProto_Dim(const TensorShapeProto_Dim& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL) {
|
||||
SharedCtor();
|
||||
UnsafeMergeFrom(from);
|
||||
// @@protoc_insertion_point(copy_constructor:tensorflow.TensorShapeProto.Dim)
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::SharedCtor() {
|
||||
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
size_ = GOOGLE_LONGLONG(0);
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
TensorShapeProto_Dim::~TensorShapeProto_Dim() {
|
||||
// @@protoc_insertion_point(destructor:tensorflow.TensorShapeProto.Dim)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::SharedDtor() {
|
||||
::google::protobuf::Arena* arena = GetArenaNoVirtual();
|
||||
if (arena != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), arena);
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::ArenaDtor(void* object) {
|
||||
TensorShapeProto_Dim* _this = reinterpret_cast< TensorShapeProto_Dim* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void TensorShapeProto_Dim::RegisterArenaDtor(::google::protobuf::Arena* arena) {
|
||||
}
|
||||
void TensorShapeProto_Dim::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* TensorShapeProto_Dim::descriptor() {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
return TensorShapeProto_Dim_descriptor_;
|
||||
}
|
||||
|
||||
const TensorShapeProto_Dim& TensorShapeProto_Dim::default_instance() {
|
||||
protobuf_InitDefaults_tensor_5fshape_2eproto();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
::google::protobuf::internal::ExplicitlyConstructed<TensorShapeProto_Dim> TensorShapeProto_Dim_default_instance_;
|
||||
|
||||
TensorShapeProto_Dim* TensorShapeProto_Dim::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<TensorShapeProto_Dim>(arena);
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:tensorflow.TensorShapeProto.Dim)
|
||||
size_ = GOOGLE_LONGLONG(0);
|
||||
name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
|
||||
bool TensorShapeProto_Dim::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:tensorflow.TensorShapeProto.Dim)
|
||||
for (;;) {
|
||||
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// optional int64 size = 1;
|
||||
case 1: {
|
||||
if (tag == 8) {
|
||||
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
|
||||
input, &size_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
if (input->ExpectTag(18)) goto parse_name;
|
||||
break;
|
||||
}
|
||||
|
||||
// optional string name = 2;
|
||||
case 2: {
|
||||
if (tag == 18) {
|
||||
parse_name:
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||
input, this->mutable_name()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->name().data(), this->name().length(),
|
||||
::google::protobuf::internal::WireFormatLite::PARSE,
|
||||
"tensorflow.TensorShapeProto.Dim.name"));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
if (input->ExpectAtEnd()) goto success;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0 ||
|
||||
::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:tensorflow.TensorShapeProto.Dim)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:tensorflow.TensorShapeProto.Dim)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:tensorflow.TensorShapeProto.Dim)
|
||||
// optional int64 size = 1;
|
||||
if (this->size() != 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->size(), output);
|
||||
}
|
||||
|
||||
// optional string name = 2;
|
||||
if (this->name().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->name().data(), this->name().length(),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"tensorflow.TensorShapeProto.Dim.name");
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
|
||||
2, this->name(), output);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(serialize_end:tensorflow.TensorShapeProto.Dim)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* TensorShapeProto_Dim::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:tensorflow.TensorShapeProto.Dim)
|
||||
// optional int64 size = 1;
|
||||
if (this->size() != 0) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->size(), target);
|
||||
}
|
||||
|
||||
// optional string name = 2;
|
||||
if (this->name().size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
|
||||
this->name().data(), this->name().length(),
|
||||
::google::protobuf::internal::WireFormatLite::SERIALIZE,
|
||||
"tensorflow.TensorShapeProto.Dim.name");
|
||||
target =
|
||||
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
|
||||
2, this->name(), target);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(serialize_to_array_end:tensorflow.TensorShapeProto.Dim)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t TensorShapeProto_Dim::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:tensorflow.TensorShapeProto.Dim)
|
||||
size_t total_size = 0;
|
||||
|
||||
// optional int64 size = 1;
|
||||
if (this->size() != 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::Int64Size(
|
||||
this->size());
|
||||
}
|
||||
|
||||
// optional string name = 2;
|
||||
if (this->name().size() > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->name());
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:tensorflow.TensorShapeProto.Dim)
|
||||
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
|
||||
const TensorShapeProto_Dim* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const TensorShapeProto_Dim>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:tensorflow.TensorShapeProto.Dim)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:tensorflow.TensorShapeProto.Dim)
|
||||
UnsafeMergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::MergeFrom(const TensorShapeProto_Dim& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:tensorflow.TensorShapeProto.Dim)
|
||||
if (GOOGLE_PREDICT_TRUE(&from != this)) {
|
||||
UnsafeMergeFrom(from);
|
||||
} else {
|
||||
MergeFromFail(__LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::UnsafeMergeFrom(const TensorShapeProto_Dim& from) {
|
||||
GOOGLE_DCHECK(&from != this);
|
||||
if (from.size() != 0) {
|
||||
set_size(from.size());
|
||||
}
|
||||
if (from.name().size() > 0) {
|
||||
set_name(from.name());
|
||||
}
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:tensorflow.TensorShapeProto.Dim)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::CopyFrom(const TensorShapeProto_Dim& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:tensorflow.TensorShapeProto.Dim)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
UnsafeMergeFrom(from);
|
||||
}
|
||||
|
||||
bool TensorShapeProto_Dim::IsInitialized() const {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TensorShapeProto_Dim::Swap(TensorShapeProto_Dim* other) {
|
||||
if (other == this) return;
|
||||
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
TensorShapeProto_Dim temp;
|
||||
temp.UnsafeMergeFrom(*this);
|
||||
CopyFrom(*other);
|
||||
other->CopyFrom(temp);
|
||||
}
|
||||
}
|
||||
void TensorShapeProto_Dim::UnsafeArenaSwap(TensorShapeProto_Dim* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
|
||||
InternalSwap(other);
|
||||
}
|
||||
void TensorShapeProto_Dim::InternalSwap(TensorShapeProto_Dim* other) {
|
||||
std::swap(size_, other->size_);
|
||||
name_.Swap(&other->name_);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
std::swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata TensorShapeProto_Dim::GetMetadata() const {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::Metadata metadata;
|
||||
metadata.descriptor = TensorShapeProto_Dim_descriptor_;
|
||||
metadata.reflection = TensorShapeProto_Dim_reflection_;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int TensorShapeProto::kDimFieldNumber;
|
||||
const int TensorShapeProto::kUnknownRankFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
TensorShapeProto::TensorShapeProto()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
|
||||
if (this != internal_default_instance()) protobuf_InitDefaults_tensor_5fshape_2eproto();
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:tensorflow.TensorShapeProto)
|
||||
}
|
||||
TensorShapeProto::TensorShapeProto(::google::protobuf::Arena* arena)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(arena),
|
||||
dim_(arena) {
|
||||
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
|
||||
protobuf_InitDefaults_tensor_5fshape_2eproto();
|
||||
#endif // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
|
||||
SharedCtor();
|
||||
RegisterArenaDtor(arena);
|
||||
// @@protoc_insertion_point(arena_constructor:tensorflow.TensorShapeProto)
|
||||
}
|
||||
|
||||
void TensorShapeProto::InitAsDefaultInstance() {
|
||||
}
|
||||
|
||||
TensorShapeProto::TensorShapeProto(const TensorShapeProto& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL) {
|
||||
SharedCtor();
|
||||
UnsafeMergeFrom(from);
|
||||
// @@protoc_insertion_point(copy_constructor:tensorflow.TensorShapeProto)
|
||||
}
|
||||
|
||||
void TensorShapeProto::SharedCtor() {
|
||||
unknown_rank_ = false;
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
TensorShapeProto::~TensorShapeProto() {
|
||||
// @@protoc_insertion_point(destructor:tensorflow.TensorShapeProto)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void TensorShapeProto::SharedDtor() {
|
||||
::google::protobuf::Arena* arena = GetArenaNoVirtual();
|
||||
if (arena != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TensorShapeProto::ArenaDtor(void* object) {
|
||||
TensorShapeProto* _this = reinterpret_cast< TensorShapeProto* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void TensorShapeProto::RegisterArenaDtor(::google::protobuf::Arena* arena) {
|
||||
}
|
||||
void TensorShapeProto::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* TensorShapeProto::descriptor() {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
return TensorShapeProto_descriptor_;
|
||||
}
|
||||
|
||||
const TensorShapeProto& TensorShapeProto::default_instance() {
|
||||
protobuf_InitDefaults_tensor_5fshape_2eproto();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
::google::protobuf::internal::ExplicitlyConstructed<TensorShapeProto> TensorShapeProto_default_instance_;
|
||||
|
||||
TensorShapeProto* TensorShapeProto::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<TensorShapeProto>(arena);
|
||||
}
|
||||
|
||||
void TensorShapeProto::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:tensorflow.TensorShapeProto)
|
||||
unknown_rank_ = false;
|
||||
dim_.Clear();
|
||||
}
|
||||
|
||||
bool TensorShapeProto::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:tensorflow.TensorShapeProto)
|
||||
for (;;) {
|
||||
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// repeated .tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
case 2: {
|
||||
if (tag == 18) {
|
||||
DO_(input->IncrementRecursionDepth());
|
||||
parse_loop_dim:
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
|
||||
input, add_dim()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
if (input->ExpectTag(18)) goto parse_loop_dim;
|
||||
input->UnsafeDecrementRecursionDepth();
|
||||
if (input->ExpectTag(24)) goto parse_unknown_rank;
|
||||
break;
|
||||
}
|
||||
|
||||
// optional bool unknown_rank = 3;
|
||||
case 3: {
|
||||
if (tag == 24) {
|
||||
parse_unknown_rank:
|
||||
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
|
||||
input, &unknown_rank_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
if (input->ExpectAtEnd()) goto success;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0 ||
|
||||
::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:tensorflow.TensorShapeProto)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:tensorflow.TensorShapeProto)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void TensorShapeProto::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:tensorflow.TensorShapeProto)
|
||||
// repeated .tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
for (unsigned int i = 0, n = this->dim_size(); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
2, this->dim(i), output);
|
||||
}
|
||||
|
||||
// optional bool unknown_rank = 3;
|
||||
if (this->unknown_rank() != 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteBool(3, this->unknown_rank(), output);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(serialize_end:tensorflow.TensorShapeProto)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* TensorShapeProto::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:tensorflow.TensorShapeProto)
|
||||
// repeated .tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
for (unsigned int i = 0, n = this->dim_size(); i < n; i++) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::
|
||||
InternalWriteMessageNoVirtualToArray(
|
||||
2, this->dim(i), false, target);
|
||||
}
|
||||
|
||||
// optional bool unknown_rank = 3;
|
||||
if (this->unknown_rank() != 0) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->unknown_rank(), target);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(serialize_to_array_end:tensorflow.TensorShapeProto)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t TensorShapeProto::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:tensorflow.TensorShapeProto)
|
||||
size_t total_size = 0;
|
||||
|
||||
// optional bool unknown_rank = 3;
|
||||
if (this->unknown_rank() != 0) {
|
||||
total_size += 1 + 1;
|
||||
}
|
||||
|
||||
// repeated .tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
{
|
||||
unsigned int count = this->dim_size();
|
||||
total_size += 1UL * count;
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
total_size +=
|
||||
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
|
||||
this->dim(i));
|
||||
}
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void TensorShapeProto::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:tensorflow.TensorShapeProto)
|
||||
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
|
||||
const TensorShapeProto* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const TensorShapeProto>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:tensorflow.TensorShapeProto)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:tensorflow.TensorShapeProto)
|
||||
UnsafeMergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void TensorShapeProto::MergeFrom(const TensorShapeProto& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:tensorflow.TensorShapeProto)
|
||||
if (GOOGLE_PREDICT_TRUE(&from != this)) {
|
||||
UnsafeMergeFrom(from);
|
||||
} else {
|
||||
MergeFromFail(__LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
void TensorShapeProto::UnsafeMergeFrom(const TensorShapeProto& from) {
|
||||
GOOGLE_DCHECK(&from != this);
|
||||
dim_.MergeFrom(from.dim_);
|
||||
if (from.unknown_rank() != 0) {
|
||||
set_unknown_rank(from.unknown_rank());
|
||||
}
|
||||
}
|
||||
|
||||
void TensorShapeProto::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:tensorflow.TensorShapeProto)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void TensorShapeProto::CopyFrom(const TensorShapeProto& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:tensorflow.TensorShapeProto)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
UnsafeMergeFrom(from);
|
||||
}
|
||||
|
||||
bool TensorShapeProto::IsInitialized() const {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TensorShapeProto::Swap(TensorShapeProto* other) {
|
||||
if (other == this) return;
|
||||
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
TensorShapeProto temp;
|
||||
temp.UnsafeMergeFrom(*this);
|
||||
CopyFrom(*other);
|
||||
other->CopyFrom(temp);
|
||||
}
|
||||
}
|
||||
void TensorShapeProto::UnsafeArenaSwap(TensorShapeProto* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
|
||||
InternalSwap(other);
|
||||
}
|
||||
void TensorShapeProto::InternalSwap(TensorShapeProto* other) {
|
||||
dim_.UnsafeArenaSwap(&other->dim_);
|
||||
std::swap(unknown_rank_, other->unknown_rank_);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
std::swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata TensorShapeProto::GetMetadata() const {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::Metadata metadata;
|
||||
metadata.descriptor = TensorShapeProto_descriptor_;
|
||||
metadata.reflection = TensorShapeProto_reflection_;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
#if PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// TensorShapeProto_Dim
|
||||
|
||||
// optional int64 size = 1;
|
||||
void TensorShapeProto_Dim::clear_size() {
|
||||
size_ = GOOGLE_LONGLONG(0);
|
||||
}
|
||||
::google::protobuf::int64 TensorShapeProto_Dim::size() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorShapeProto.Dim.size)
|
||||
return size_;
|
||||
}
|
||||
void TensorShapeProto_Dim::set_size(::google::protobuf::int64 value) {
|
||||
|
||||
size_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorShapeProto.Dim.size)
|
||||
}
|
||||
|
||||
// optional string name = 2;
|
||||
void TensorShapeProto_Dim::clear_name() {
|
||||
name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
const ::std::string& TensorShapeProto_Dim::name() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorShapeProto.Dim.name)
|
||||
return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
void TensorShapeProto_Dim::set_name(const ::std::string& value) {
|
||||
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
void TensorShapeProto_Dim::set_name(const char* value) {
|
||||
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_char:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
void TensorShapeProto_Dim::set_name(const char* value,
|
||||
size_t size) {
|
||||
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_pointer:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
::std::string* TensorShapeProto_Dim::mutable_name() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.TensorShapeProto.Dim.name)
|
||||
return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
::std::string* TensorShapeProto_Dim::release_name() {
|
||||
// @@protoc_insertion_point(field_release:tensorflow.TensorShapeProto.Dim.name)
|
||||
|
||||
return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
::std::string* TensorShapeProto_Dim::unsafe_arena_release_name() {
|
||||
// @@protoc_insertion_point(field_unsafe_arena_release:tensorflow.TensorShapeProto.Dim.name)
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
|
||||
return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
}
|
||||
void TensorShapeProto_Dim::set_allocated_name(::std::string* name) {
|
||||
if (name != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
void TensorShapeProto_Dim::unsafe_arena_set_allocated_name(
|
||||
::std::string* name) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (name != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
name, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_unsafe_arena_set_allocated:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
|
||||
inline const TensorShapeProto_Dim* TensorShapeProto_Dim::internal_default_instance() {
|
||||
return &TensorShapeProto_Dim_default_instance_.get();
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// TensorShapeProto
|
||||
|
||||
// repeated .tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
int TensorShapeProto::dim_size() const {
|
||||
return dim_.size();
|
||||
}
|
||||
void TensorShapeProto::clear_dim() {
|
||||
dim_.Clear();
|
||||
}
|
||||
const ::tensorflow::TensorShapeProto_Dim& TensorShapeProto::dim(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorShapeProto.dim)
|
||||
return dim_.Get(index);
|
||||
}
|
||||
::tensorflow::TensorShapeProto_Dim* TensorShapeProto::mutable_dim(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.TensorShapeProto.dim)
|
||||
return dim_.Mutable(index);
|
||||
}
|
||||
::tensorflow::TensorShapeProto_Dim* TensorShapeProto::add_dim() {
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorShapeProto.dim)
|
||||
return dim_.Add();
|
||||
}
|
||||
::google::protobuf::RepeatedPtrField< ::tensorflow::TensorShapeProto_Dim >*
|
||||
TensorShapeProto::mutable_dim() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorShapeProto.dim)
|
||||
return &dim_;
|
||||
}
|
||||
const ::google::protobuf::RepeatedPtrField< ::tensorflow::TensorShapeProto_Dim >&
|
||||
TensorShapeProto::dim() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorShapeProto.dim)
|
||||
return dim_;
|
||||
}
|
||||
|
||||
// optional bool unknown_rank = 3;
|
||||
void TensorShapeProto::clear_unknown_rank() {
|
||||
unknown_rank_ = false;
|
||||
}
|
||||
bool TensorShapeProto::unknown_rank() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorShapeProto.unknown_rank)
|
||||
return unknown_rank_;
|
||||
}
|
||||
void TensorShapeProto::set_unknown_rank(bool value) {
|
||||
|
||||
unknown_rank_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorShapeProto.unknown_rank)
|
||||
}
|
||||
|
||||
inline const TensorShapeProto* TensorShapeProto::internal_default_instance() {
|
||||
return &TensorShapeProto_default_instance_.get();
|
||||
}
|
||||
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace tensorflow
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
423
modules/dnn/misc/tensorflow/tensor_shape.pb.h
Normal file
423
modules/dnn/misc/tensorflow/tensor_shape.pb.h
Normal file
@ -0,0 +1,423 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: tensor_shape.proto
|
||||
|
||||
#ifndef PROTOBUF_tensor_5fshape_2eproto__INCLUDED
|
||||
#define PROTOBUF_tensor_5fshape_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3001000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3001000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
// Internal implementation detail -- do not call these.
|
||||
void protobuf_AddDesc_tensor_5fshape_2eproto();
|
||||
void protobuf_InitDefaults_tensor_5fshape_2eproto();
|
||||
void protobuf_AssignDesc_tensor_5fshape_2eproto();
|
||||
void protobuf_ShutdownFile_tensor_5fshape_2eproto();
|
||||
|
||||
class TensorShapeProto;
|
||||
class TensorShapeProto_Dim;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class TensorShapeProto_Dim : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:tensorflow.TensorShapeProto.Dim) */ {
|
||||
public:
|
||||
TensorShapeProto_Dim();
|
||||
virtual ~TensorShapeProto_Dim();
|
||||
|
||||
TensorShapeProto_Dim(const TensorShapeProto_Dim& from);
|
||||
|
||||
inline TensorShapeProto_Dim& operator=(const TensorShapeProto_Dim& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
|
||||
inline void* GetMaybeArenaPointer() const {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const TensorShapeProto_Dim& default_instance();
|
||||
|
||||
static const TensorShapeProto_Dim* internal_default_instance();
|
||||
|
||||
void UnsafeArenaSwap(TensorShapeProto_Dim* other);
|
||||
void Swap(TensorShapeProto_Dim* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline TensorShapeProto_Dim* New() const { return New(NULL); }
|
||||
|
||||
TensorShapeProto_Dim* New(::google::protobuf::Arena* arena) const;
|
||||
void CopyFrom(const ::google::protobuf::Message& from);
|
||||
void MergeFrom(const ::google::protobuf::Message& from);
|
||||
void CopyFrom(const TensorShapeProto_Dim& from);
|
||||
void MergeFrom(const TensorShapeProto_Dim& from);
|
||||
void Clear();
|
||||
bool IsInitialized() const;
|
||||
|
||||
size_t ByteSizeLong() const;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input);
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* output) const;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
|
||||
return InternalSerializeWithCachedSizesToArray(false, output);
|
||||
}
|
||||
int GetCachedSize() const { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(TensorShapeProto_Dim* other);
|
||||
void UnsafeMergeFrom(const TensorShapeProto_Dim& from);
|
||||
protected:
|
||||
explicit TensorShapeProto_Dim(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return _internal_metadata_.raw_arena_ptr();
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// optional int64 size = 1;
|
||||
void clear_size();
|
||||
static const int kSizeFieldNumber = 1;
|
||||
::google::protobuf::int64 size() const;
|
||||
void set_size(::google::protobuf::int64 value);
|
||||
|
||||
// optional string name = 2;
|
||||
void clear_name();
|
||||
static const int kNameFieldNumber = 2;
|
||||
const ::std::string& name() const;
|
||||
void set_name(const ::std::string& value);
|
||||
void set_name(const char* value);
|
||||
void set_name(const char* value, size_t size);
|
||||
::std::string* mutable_name();
|
||||
::std::string* release_name();
|
||||
void set_allocated_name(::std::string* name);
|
||||
::std::string* unsafe_arena_release_name();
|
||||
void unsafe_arena_set_allocated_name(
|
||||
::std::string* name);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:tensorflow.TensorShapeProto.Dim)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::internal::ArenaStringPtr name_;
|
||||
::google::protobuf::int64 size_;
|
||||
mutable int _cached_size_;
|
||||
friend void protobuf_InitDefaults_tensor_5fshape_2eproto_impl();
|
||||
friend void protobuf_AddDesc_tensor_5fshape_2eproto_impl();
|
||||
friend void protobuf_AssignDesc_tensor_5fshape_2eproto();
|
||||
friend void protobuf_ShutdownFile_tensor_5fshape_2eproto();
|
||||
|
||||
void InitAsDefaultInstance();
|
||||
};
|
||||
extern ::google::protobuf::internal::ExplicitlyConstructed<TensorShapeProto_Dim> TensorShapeProto_Dim_default_instance_;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
class TensorShapeProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:tensorflow.TensorShapeProto) */ {
|
||||
public:
|
||||
TensorShapeProto();
|
||||
virtual ~TensorShapeProto();
|
||||
|
||||
TensorShapeProto(const TensorShapeProto& from);
|
||||
|
||||
inline TensorShapeProto& operator=(const TensorShapeProto& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
|
||||
inline void* GetMaybeArenaPointer() const {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const TensorShapeProto& default_instance();
|
||||
|
||||
static const TensorShapeProto* internal_default_instance();
|
||||
|
||||
void UnsafeArenaSwap(TensorShapeProto* other);
|
||||
void Swap(TensorShapeProto* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline TensorShapeProto* New() const { return New(NULL); }
|
||||
|
||||
TensorShapeProto* New(::google::protobuf::Arena* arena) const;
|
||||
void CopyFrom(const ::google::protobuf::Message& from);
|
||||
void MergeFrom(const ::google::protobuf::Message& from);
|
||||
void CopyFrom(const TensorShapeProto& from);
|
||||
void MergeFrom(const TensorShapeProto& from);
|
||||
void Clear();
|
||||
bool IsInitialized() const;
|
||||
|
||||
size_t ByteSizeLong() const;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input);
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* output) const;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
|
||||
return InternalSerializeWithCachedSizesToArray(false, output);
|
||||
}
|
||||
int GetCachedSize() const { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(TensorShapeProto* other);
|
||||
void UnsafeMergeFrom(const TensorShapeProto& from);
|
||||
protected:
|
||||
explicit TensorShapeProto(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return _internal_metadata_.raw_arena_ptr();
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
typedef TensorShapeProto_Dim Dim;
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// repeated .tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
int dim_size() const;
|
||||
void clear_dim();
|
||||
static const int kDimFieldNumber = 2;
|
||||
const ::tensorflow::TensorShapeProto_Dim& dim(int index) const;
|
||||
::tensorflow::TensorShapeProto_Dim* mutable_dim(int index);
|
||||
::tensorflow::TensorShapeProto_Dim* add_dim();
|
||||
::google::protobuf::RepeatedPtrField< ::tensorflow::TensorShapeProto_Dim >*
|
||||
mutable_dim();
|
||||
const ::google::protobuf::RepeatedPtrField< ::tensorflow::TensorShapeProto_Dim >&
|
||||
dim() const;
|
||||
|
||||
// optional bool unknown_rank = 3;
|
||||
void clear_unknown_rank();
|
||||
static const int kUnknownRankFieldNumber = 3;
|
||||
bool unknown_rank() const;
|
||||
void set_unknown_rank(bool value);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:tensorflow.TensorShapeProto)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::RepeatedPtrField< ::tensorflow::TensorShapeProto_Dim > dim_;
|
||||
bool unknown_rank_;
|
||||
mutable int _cached_size_;
|
||||
friend void protobuf_InitDefaults_tensor_5fshape_2eproto_impl();
|
||||
friend void protobuf_AddDesc_tensor_5fshape_2eproto_impl();
|
||||
friend void protobuf_AssignDesc_tensor_5fshape_2eproto();
|
||||
friend void protobuf_ShutdownFile_tensor_5fshape_2eproto();
|
||||
|
||||
void InitAsDefaultInstance();
|
||||
};
|
||||
extern ::google::protobuf::internal::ExplicitlyConstructed<TensorShapeProto> TensorShapeProto_default_instance_;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// TensorShapeProto_Dim
|
||||
|
||||
// optional int64 size = 1;
|
||||
inline void TensorShapeProto_Dim::clear_size() {
|
||||
size_ = GOOGLE_LONGLONG(0);
|
||||
}
|
||||
inline ::google::protobuf::int64 TensorShapeProto_Dim::size() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorShapeProto.Dim.size)
|
||||
return size_;
|
||||
}
|
||||
inline void TensorShapeProto_Dim::set_size(::google::protobuf::int64 value) {
|
||||
|
||||
size_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorShapeProto.Dim.size)
|
||||
}
|
||||
|
||||
// optional string name = 2;
|
||||
inline void TensorShapeProto_Dim::clear_name() {
|
||||
name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline const ::std::string& TensorShapeProto_Dim::name() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorShapeProto.Dim.name)
|
||||
return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void TensorShapeProto_Dim::set_name(const ::std::string& value) {
|
||||
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
inline void TensorShapeProto_Dim::set_name(const char* value) {
|
||||
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_char:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
inline void TensorShapeProto_Dim::set_name(const char* value,
|
||||
size_t size) {
|
||||
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_pointer:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
inline ::std::string* TensorShapeProto_Dim::mutable_name() {
|
||||
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.TensorShapeProto.Dim.name)
|
||||
return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* TensorShapeProto_Dim::release_name() {
|
||||
// @@protoc_insertion_point(field_release:tensorflow.TensorShapeProto.Dim.name)
|
||||
|
||||
return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* TensorShapeProto_Dim::unsafe_arena_release_name() {
|
||||
// @@protoc_insertion_point(field_unsafe_arena_release:tensorflow.TensorShapeProto.Dim.name)
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
|
||||
return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
}
|
||||
inline void TensorShapeProto_Dim::set_allocated_name(::std::string* name) {
|
||||
if (name != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
inline void TensorShapeProto_Dim::unsafe_arena_set_allocated_name(
|
||||
::std::string* name) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (name != NULL) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
name, GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_unsafe_arena_set_allocated:tensorflow.TensorShapeProto.Dim.name)
|
||||
}
|
||||
|
||||
inline const TensorShapeProto_Dim* TensorShapeProto_Dim::internal_default_instance() {
|
||||
return &TensorShapeProto_Dim_default_instance_.get();
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// TensorShapeProto
|
||||
|
||||
// repeated .tensorflow.TensorShapeProto.Dim dim = 2;
|
||||
inline int TensorShapeProto::dim_size() const {
|
||||
return dim_.size();
|
||||
}
|
||||
inline void TensorShapeProto::clear_dim() {
|
||||
dim_.Clear();
|
||||
}
|
||||
inline const ::tensorflow::TensorShapeProto_Dim& TensorShapeProto::dim(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorShapeProto.dim)
|
||||
return dim_.Get(index);
|
||||
}
|
||||
inline ::tensorflow::TensorShapeProto_Dim* TensorShapeProto::mutable_dim(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:tensorflow.TensorShapeProto.dim)
|
||||
return dim_.Mutable(index);
|
||||
}
|
||||
inline ::tensorflow::TensorShapeProto_Dim* TensorShapeProto::add_dim() {
|
||||
// @@protoc_insertion_point(field_add:tensorflow.TensorShapeProto.dim)
|
||||
return dim_.Add();
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::tensorflow::TensorShapeProto_Dim >*
|
||||
TensorShapeProto::mutable_dim() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.TensorShapeProto.dim)
|
||||
return &dim_;
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::tensorflow::TensorShapeProto_Dim >&
|
||||
TensorShapeProto::dim() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.TensorShapeProto.dim)
|
||||
return dim_;
|
||||
}
|
||||
|
||||
// optional bool unknown_rank = 3;
|
||||
inline void TensorShapeProto::clear_unknown_rank() {
|
||||
unknown_rank_ = false;
|
||||
}
|
||||
inline bool TensorShapeProto::unknown_rank() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.TensorShapeProto.unknown_rank)
|
||||
return unknown_rank_;
|
||||
}
|
||||
inline void TensorShapeProto::set_unknown_rank(bool value) {
|
||||
|
||||
unknown_rank_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.TensorShapeProto.unknown_rank)
|
||||
}
|
||||
|
||||
inline const TensorShapeProto* TensorShapeProto::internal_default_instance() {
|
||||
return &TensorShapeProto_default_instance_.get();
|
||||
}
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace tensorflow
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_tensor_5fshape_2eproto__INCLUDED
|
163
modules/dnn/misc/tensorflow/types.pb.cc
Normal file
163
modules/dnn/misc/tensorflow/types.pb.cc
Normal file
@ -0,0 +1,163 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: types.proto
|
||||
|
||||
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
||||
#include "types.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
namespace {
|
||||
|
||||
const ::google::protobuf::EnumDescriptor* DataType_descriptor_ = NULL;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void protobuf_AssignDesc_types_2eproto() GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_AssignDesc_types_2eproto() {
|
||||
protobuf_AddDesc_types_2eproto();
|
||||
const ::google::protobuf::FileDescriptor* file =
|
||||
::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
|
||||
"types.proto");
|
||||
GOOGLE_CHECK(file != NULL);
|
||||
DataType_descriptor_ = file->enum_type(0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
|
||||
&protobuf_AssignDesc_types_2eproto);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void protobuf_ShutdownFile_types_2eproto() {
|
||||
}
|
||||
|
||||
void protobuf_InitDefaults_types_2eproto_impl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_InitDefaults_types_2eproto_once_);
|
||||
void protobuf_InitDefaults_types_2eproto() {
|
||||
::google::protobuf::GoogleOnceInit(&protobuf_InitDefaults_types_2eproto_once_,
|
||||
&protobuf_InitDefaults_types_2eproto_impl);
|
||||
}
|
||||
void protobuf_AddDesc_types_2eproto_impl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
protobuf_InitDefaults_types_2eproto();
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
"\n\013types.proto\022\ntensorflow*\234\005\n\010DataType\022\016"
|
||||
"\n\nDT_INVALID\020\000\022\014\n\010DT_FLOAT\020\001\022\r\n\tDT_DOUBL"
|
||||
"E\020\002\022\014\n\010DT_INT32\020\003\022\014\n\010DT_UINT8\020\004\022\014\n\010DT_IN"
|
||||
"T16\020\005\022\013\n\007DT_INT8\020\006\022\r\n\tDT_STRING\020\007\022\020\n\014DT_"
|
||||
"COMPLEX64\020\010\022\014\n\010DT_INT64\020\t\022\013\n\007DT_BOOL\020\n\022\014"
|
||||
"\n\010DT_QINT8\020\013\022\r\n\tDT_QUINT8\020\014\022\r\n\tDT_QINT32"
|
||||
"\020\r\022\017\n\013DT_BFLOAT16\020\016\022\r\n\tDT_QINT16\020\017\022\016\n\nDT"
|
||||
"_QUINT16\020\020\022\r\n\tDT_UINT16\020\021\022\021\n\rDT_COMPLEX1"
|
||||
"28\020\022\022\013\n\007DT_HALF\020\023\022\020\n\014DT_FLOAT_REF\020e\022\021\n\rD"
|
||||
"T_DOUBLE_REF\020f\022\020\n\014DT_INT32_REF\020g\022\020\n\014DT_U"
|
||||
"INT8_REF\020h\022\020\n\014DT_INT16_REF\020i\022\017\n\013DT_INT8_"
|
||||
"REF\020j\022\021\n\rDT_STRING_REF\020k\022\024\n\020DT_COMPLEX64"
|
||||
"_REF\020l\022\020\n\014DT_INT64_REF\020m\022\017\n\013DT_BOOL_REF\020"
|
||||
"n\022\020\n\014DT_QINT8_REF\020o\022\021\n\rDT_QUINT8_REF\020p\022\021"
|
||||
"\n\rDT_QINT32_REF\020q\022\023\n\017DT_BFLOAT16_REF\020r\022\021"
|
||||
"\n\rDT_QINT16_REF\020s\022\022\n\016DT_QUINT16_REF\020t\022\021\n"
|
||||
"\rDT_UINT16_REF\020u\022\025\n\021DT_COMPLEX128_REF\020v\022"
|
||||
"\017\n\013DT_HALF_REF\020wB,\n\030org.tensorflow.frame"
|
||||
"workB\013TypesProtosP\001\370\001\001b\006proto3", 750);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"types.proto", &protobuf_RegisterTypes);
|
||||
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_types_2eproto);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AddDesc_types_2eproto_once_);
|
||||
void protobuf_AddDesc_types_2eproto() {
|
||||
::google::protobuf::GoogleOnceInit(&protobuf_AddDesc_types_2eproto_once_,
|
||||
&protobuf_AddDesc_types_2eproto_impl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at static initialization time.
|
||||
struct StaticDescriptorInitializer_types_2eproto {
|
||||
StaticDescriptorInitializer_types_2eproto() {
|
||||
protobuf_AddDesc_types_2eproto();
|
||||
}
|
||||
} static_descriptor_initializer_types_2eproto_;
|
||||
const ::google::protobuf::EnumDescriptor* DataType_descriptor() {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
return DataType_descriptor_;
|
||||
}
|
||||
bool DataType_IsValid(int value) {
|
||||
switch (value) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 104:
|
||||
case 105:
|
||||
case 106:
|
||||
case 107:
|
||||
case 108:
|
||||
case 109:
|
||||
case 110:
|
||||
case 111:
|
||||
case 112:
|
||||
case 113:
|
||||
case 114:
|
||||
case 115:
|
||||
case 116:
|
||||
case 117:
|
||||
case 118:
|
||||
case 119:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace tensorflow
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
129
modules/dnn/misc/tensorflow/types.pb.h
Normal file
129
modules/dnn/misc/tensorflow/types.pb.h
Normal file
@ -0,0 +1,129 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: types.proto
|
||||
|
||||
#ifndef PROTOBUF_types_2eproto__INCLUDED
|
||||
#define PROTOBUF_types_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3001000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3001000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/generated_enum_reflection.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
// Internal implementation detail -- do not call these.
|
||||
void protobuf_AddDesc_types_2eproto();
|
||||
void protobuf_InitDefaults_types_2eproto();
|
||||
void protobuf_AssignDesc_types_2eproto();
|
||||
void protobuf_ShutdownFile_types_2eproto();
|
||||
|
||||
|
||||
enum DataType {
|
||||
DT_INVALID = 0,
|
||||
DT_FLOAT = 1,
|
||||
DT_DOUBLE = 2,
|
||||
DT_INT32 = 3,
|
||||
DT_UINT8 = 4,
|
||||
DT_INT16 = 5,
|
||||
DT_INT8 = 6,
|
||||
DT_STRING = 7,
|
||||
DT_COMPLEX64 = 8,
|
||||
DT_INT64 = 9,
|
||||
DT_BOOL = 10,
|
||||
DT_QINT8 = 11,
|
||||
DT_QUINT8 = 12,
|
||||
DT_QINT32 = 13,
|
||||
DT_BFLOAT16 = 14,
|
||||
DT_QINT16 = 15,
|
||||
DT_QUINT16 = 16,
|
||||
DT_UINT16 = 17,
|
||||
DT_COMPLEX128 = 18,
|
||||
DT_HALF = 19,
|
||||
DT_FLOAT_REF = 101,
|
||||
DT_DOUBLE_REF = 102,
|
||||
DT_INT32_REF = 103,
|
||||
DT_UINT8_REF = 104,
|
||||
DT_INT16_REF = 105,
|
||||
DT_INT8_REF = 106,
|
||||
DT_STRING_REF = 107,
|
||||
DT_COMPLEX64_REF = 108,
|
||||
DT_INT64_REF = 109,
|
||||
DT_BOOL_REF = 110,
|
||||
DT_QINT8_REF = 111,
|
||||
DT_QUINT8_REF = 112,
|
||||
DT_QINT32_REF = 113,
|
||||
DT_BFLOAT16_REF = 114,
|
||||
DT_QINT16_REF = 115,
|
||||
DT_QUINT16_REF = 116,
|
||||
DT_UINT16_REF = 117,
|
||||
DT_COMPLEX128_REF = 118,
|
||||
DT_HALF_REF = 119,
|
||||
DataType_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
|
||||
DataType_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
|
||||
};
|
||||
bool DataType_IsValid(int value);
|
||||
const DataType DataType_MIN = DT_INVALID;
|
||||
const DataType DataType_MAX = DT_HALF_REF;
|
||||
const int DataType_ARRAYSIZE = DataType_MAX + 1;
|
||||
|
||||
const ::google::protobuf::EnumDescriptor* DataType_descriptor();
|
||||
inline const ::std::string& DataType_Name(DataType value) {
|
||||
return ::google::protobuf::internal::NameOfEnum(
|
||||
DataType_descriptor(), value);
|
||||
}
|
||||
inline bool DataType_Parse(
|
||||
const ::std::string& name, DataType* value) {
|
||||
return ::google::protobuf::internal::ParseNamedEnum<DataType>(
|
||||
DataType_descriptor(), name, value);
|
||||
}
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace tensorflow
|
||||
|
||||
#ifndef SWIG
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
template <> struct is_proto_enum< ::tensorflow::DataType> : ::google::protobuf::internal::true_type {};
|
||||
template <>
|
||||
inline const EnumDescriptor* GetEnumDescriptor< ::tensorflow::DataType>() {
|
||||
return ::tensorflow::DataType_descriptor();
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // SWIG
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_types_2eproto__INCLUDED
|
572
modules/dnn/misc/tensorflow/versions.pb.cc
Normal file
572
modules/dnn/misc/tensorflow/versions.pb.cc
Normal file
@ -0,0 +1,572 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: versions.proto
|
||||
|
||||
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
|
||||
#include "versions.pb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
namespace {
|
||||
|
||||
const ::google::protobuf::Descriptor* VersionDef_descriptor_ = NULL;
|
||||
const ::google::protobuf::internal::GeneratedMessageReflection*
|
||||
VersionDef_reflection_ = NULL;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void protobuf_AssignDesc_versions_2eproto() GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_AssignDesc_versions_2eproto() {
|
||||
protobuf_AddDesc_versions_2eproto();
|
||||
const ::google::protobuf::FileDescriptor* file =
|
||||
::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
|
||||
"versions.proto");
|
||||
GOOGLE_CHECK(file != NULL);
|
||||
VersionDef_descriptor_ = file->message_type(0);
|
||||
static const int VersionDef_offsets_[3] = {
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(VersionDef, producer_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(VersionDef, min_consumer_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(VersionDef, bad_consumers_),
|
||||
};
|
||||
VersionDef_reflection_ =
|
||||
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
|
||||
VersionDef_descriptor_,
|
||||
VersionDef::internal_default_instance(),
|
||||
VersionDef_offsets_,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
sizeof(VersionDef),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(VersionDef, _internal_metadata_));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
|
||||
void protobuf_AssignDescriptorsOnce() {
|
||||
::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
|
||||
&protobuf_AssignDesc_versions_2eproto);
|
||||
}
|
||||
|
||||
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
|
||||
VersionDef_descriptor_, VersionDef::internal_default_instance());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void protobuf_ShutdownFile_versions_2eproto() {
|
||||
VersionDef_default_instance_.Shutdown();
|
||||
delete VersionDef_reflection_;
|
||||
}
|
||||
|
||||
void protobuf_InitDefaults_versions_2eproto_impl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
VersionDef_default_instance_.DefaultConstruct();
|
||||
VersionDef_default_instance_.get_mutable()->InitAsDefaultInstance();
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_InitDefaults_versions_2eproto_once_);
|
||||
void protobuf_InitDefaults_versions_2eproto() {
|
||||
::google::protobuf::GoogleOnceInit(&protobuf_InitDefaults_versions_2eproto_once_,
|
||||
&protobuf_InitDefaults_versions_2eproto_impl);
|
||||
}
|
||||
void protobuf_AddDesc_versions_2eproto_impl() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
protobuf_InitDefaults_versions_2eproto();
|
||||
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
|
||||
"\n\016versions.proto\022\ntensorflow\"K\n\nVersionD"
|
||||
"ef\022\020\n\010producer\030\001 \001(\005\022\024\n\014min_consumer\030\002 \001"
|
||||
"(\005\022\025\n\rbad_consumers\030\003 \003(\005B/\n\030org.tensorf"
|
||||
"low.frameworkB\016VersionsProtosP\001\370\001\001b\006prot"
|
||||
"o3", 162);
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
|
||||
"versions.proto", &protobuf_RegisterTypes);
|
||||
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_versions_2eproto);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AddDesc_versions_2eproto_once_);
|
||||
void protobuf_AddDesc_versions_2eproto() {
|
||||
::google::protobuf::GoogleOnceInit(&protobuf_AddDesc_versions_2eproto_once_,
|
||||
&protobuf_AddDesc_versions_2eproto_impl);
|
||||
}
|
||||
// Force AddDescriptors() to be called at static initialization time.
|
||||
struct StaticDescriptorInitializer_versions_2eproto {
|
||||
StaticDescriptorInitializer_versions_2eproto() {
|
||||
protobuf_AddDesc_versions_2eproto();
|
||||
}
|
||||
} static_descriptor_initializer_versions_2eproto_;
|
||||
|
||||
namespace {
|
||||
|
||||
static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD GOOGLE_ATTRIBUTE_NORETURN;
|
||||
static void MergeFromFail(int line) {
|
||||
::google::protobuf::internal::MergeFromFail(__FILE__, line);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
const int VersionDef::kProducerFieldNumber;
|
||||
const int VersionDef::kMinConsumerFieldNumber;
|
||||
const int VersionDef::kBadConsumersFieldNumber;
|
||||
#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
|
||||
VersionDef::VersionDef()
|
||||
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
|
||||
if (this != internal_default_instance()) protobuf_InitDefaults_versions_2eproto();
|
||||
SharedCtor();
|
||||
// @@protoc_insertion_point(constructor:tensorflow.VersionDef)
|
||||
}
|
||||
VersionDef::VersionDef(::google::protobuf::Arena* arena)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(arena),
|
||||
bad_consumers_(arena) {
|
||||
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
|
||||
protobuf_InitDefaults_versions_2eproto();
|
||||
#endif // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
|
||||
SharedCtor();
|
||||
RegisterArenaDtor(arena);
|
||||
// @@protoc_insertion_point(arena_constructor:tensorflow.VersionDef)
|
||||
}
|
||||
|
||||
void VersionDef::InitAsDefaultInstance() {
|
||||
}
|
||||
|
||||
VersionDef::VersionDef(const VersionDef& from)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(NULL) {
|
||||
SharedCtor();
|
||||
UnsafeMergeFrom(from);
|
||||
// @@protoc_insertion_point(copy_constructor:tensorflow.VersionDef)
|
||||
}
|
||||
|
||||
void VersionDef::SharedCtor() {
|
||||
::memset(&producer_, 0, reinterpret_cast<char*>(&min_consumer_) -
|
||||
reinterpret_cast<char*>(&producer_) + sizeof(min_consumer_));
|
||||
_cached_size_ = 0;
|
||||
}
|
||||
|
||||
VersionDef::~VersionDef() {
|
||||
// @@protoc_insertion_point(destructor:tensorflow.VersionDef)
|
||||
SharedDtor();
|
||||
}
|
||||
|
||||
void VersionDef::SharedDtor() {
|
||||
::google::protobuf::Arena* arena = GetArenaNoVirtual();
|
||||
if (arena != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VersionDef::ArenaDtor(void* object) {
|
||||
VersionDef* _this = reinterpret_cast< VersionDef* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void VersionDef::RegisterArenaDtor(::google::protobuf::Arena* arena) {
|
||||
}
|
||||
void VersionDef::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
}
|
||||
const ::google::protobuf::Descriptor* VersionDef::descriptor() {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
return VersionDef_descriptor_;
|
||||
}
|
||||
|
||||
const VersionDef& VersionDef::default_instance() {
|
||||
protobuf_InitDefaults_versions_2eproto();
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
::google::protobuf::internal::ExplicitlyConstructed<VersionDef> VersionDef_default_instance_;
|
||||
|
||||
VersionDef* VersionDef::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<VersionDef>(arena);
|
||||
}
|
||||
|
||||
void VersionDef::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:tensorflow.VersionDef)
|
||||
#if defined(__clang__)
|
||||
#define ZR_HELPER_(f) \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
|
||||
__builtin_offsetof(VersionDef, f) \
|
||||
_Pragma("clang diagnostic pop")
|
||||
#else
|
||||
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
|
||||
&reinterpret_cast<VersionDef*>(16)->f)
|
||||
#endif
|
||||
|
||||
#define ZR_(first, last) do {\
|
||||
::memset(&(first), 0,\
|
||||
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
|
||||
} while (0)
|
||||
|
||||
ZR_(producer_, min_consumer_);
|
||||
|
||||
#undef ZR_HELPER_
|
||||
#undef ZR_
|
||||
|
||||
bad_consumers_.Clear();
|
||||
}
|
||||
|
||||
bool VersionDef::MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input) {
|
||||
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
|
||||
::google::protobuf::uint32 tag;
|
||||
// @@protoc_insertion_point(parse_start:tensorflow.VersionDef)
|
||||
for (;;) {
|
||||
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
|
||||
tag = p.first;
|
||||
if (!p.second) goto handle_unusual;
|
||||
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
|
||||
// optional int32 producer = 1;
|
||||
case 1: {
|
||||
if (tag == 8) {
|
||||
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
|
||||
input, &producer_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
if (input->ExpectTag(16)) goto parse_min_consumer;
|
||||
break;
|
||||
}
|
||||
|
||||
// optional int32 min_consumer = 2;
|
||||
case 2: {
|
||||
if (tag == 16) {
|
||||
parse_min_consumer:
|
||||
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
|
||||
input, &min_consumer_)));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
if (input->ExpectTag(26)) goto parse_bad_consumers;
|
||||
break;
|
||||
}
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
case 3: {
|
||||
if (tag == 26) {
|
||||
parse_bad_consumers:
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
|
||||
::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
|
||||
input, this->mutable_bad_consumers())));
|
||||
} else if (tag == 24) {
|
||||
DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
|
||||
::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
|
||||
1, 26, input, this->mutable_bad_consumers())));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
if (input->ExpectAtEnd()) goto success;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
handle_unusual:
|
||||
if (tag == 0 ||
|
||||
::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
|
||||
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
goto success;
|
||||
}
|
||||
DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
// @@protoc_insertion_point(parse_success:tensorflow.VersionDef)
|
||||
return true;
|
||||
failure:
|
||||
// @@protoc_insertion_point(parse_failure:tensorflow.VersionDef)
|
||||
return false;
|
||||
#undef DO_
|
||||
}
|
||||
|
||||
void VersionDef::SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const {
|
||||
// @@protoc_insertion_point(serialize_start:tensorflow.VersionDef)
|
||||
// optional int32 producer = 1;
|
||||
if (this->producer() != 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->producer(), output);
|
||||
}
|
||||
|
||||
// optional int32 min_consumer = 2;
|
||||
if (this->min_consumer() != 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->min_consumer(), output);
|
||||
}
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
if (this->bad_consumers_size() > 0) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteTag(3, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
|
||||
output->WriteVarint32(_bad_consumers_cached_byte_size_);
|
||||
}
|
||||
for (int i = 0; i < this->bad_consumers_size(); i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
|
||||
this->bad_consumers(i), output);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(serialize_end:tensorflow.VersionDef)
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* VersionDef::InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* target) const {
|
||||
(void)deterministic; // Unused
|
||||
// @@protoc_insertion_point(serialize_to_array_start:tensorflow.VersionDef)
|
||||
// optional int32 producer = 1;
|
||||
if (this->producer() != 0) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->producer(), target);
|
||||
}
|
||||
|
||||
// optional int32 min_consumer = 2;
|
||||
if (this->min_consumer() != 0) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->min_consumer(), target);
|
||||
}
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
if (this->bad_consumers_size() > 0) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
|
||||
3,
|
||||
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
|
||||
target);
|
||||
target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
|
||||
_bad_consumers_cached_byte_size_, target);
|
||||
}
|
||||
for (int i = 0; i < this->bad_consumers_size(); i++) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::
|
||||
WriteInt32NoTagToArray(this->bad_consumers(i), target);
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(serialize_to_array_end:tensorflow.VersionDef)
|
||||
return target;
|
||||
}
|
||||
|
||||
size_t VersionDef::ByteSizeLong() const {
|
||||
// @@protoc_insertion_point(message_byte_size_start:tensorflow.VersionDef)
|
||||
size_t total_size = 0;
|
||||
|
||||
// optional int32 producer = 1;
|
||||
if (this->producer() != 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::Int32Size(
|
||||
this->producer());
|
||||
}
|
||||
|
||||
// optional int32 min_consumer = 2;
|
||||
if (this->min_consumer() != 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::Int32Size(
|
||||
this->min_consumer());
|
||||
}
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
{
|
||||
size_t data_size = 0;
|
||||
unsigned int count = this->bad_consumers_size();
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
data_size += ::google::protobuf::internal::WireFormatLite::
|
||||
Int32Size(this->bad_consumers(i));
|
||||
}
|
||||
if (data_size > 0) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
|
||||
}
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_bad_consumers_cached_byte_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
total_size += data_size;
|
||||
}
|
||||
|
||||
int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = cached_size;
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_END();
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void VersionDef::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_start:tensorflow.VersionDef)
|
||||
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
|
||||
const VersionDef* source =
|
||||
::google::protobuf::internal::DynamicCastToGenerated<const VersionDef>(
|
||||
&from);
|
||||
if (source == NULL) {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_fail:tensorflow.VersionDef)
|
||||
::google::protobuf::internal::ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
// @@protoc_insertion_point(generalized_merge_from_cast_success:tensorflow.VersionDef)
|
||||
UnsafeMergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void VersionDef::MergeFrom(const VersionDef& from) {
|
||||
// @@protoc_insertion_point(class_specific_merge_from_start:tensorflow.VersionDef)
|
||||
if (GOOGLE_PREDICT_TRUE(&from != this)) {
|
||||
UnsafeMergeFrom(from);
|
||||
} else {
|
||||
MergeFromFail(__LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
void VersionDef::UnsafeMergeFrom(const VersionDef& from) {
|
||||
GOOGLE_DCHECK(&from != this);
|
||||
bad_consumers_.UnsafeMergeFrom(from.bad_consumers_);
|
||||
if (from.producer() != 0) {
|
||||
set_producer(from.producer());
|
||||
}
|
||||
if (from.min_consumer() != 0) {
|
||||
set_min_consumer(from.min_consumer());
|
||||
}
|
||||
}
|
||||
|
||||
void VersionDef::CopyFrom(const ::google::protobuf::Message& from) {
|
||||
// @@protoc_insertion_point(generalized_copy_from_start:tensorflow.VersionDef)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void VersionDef::CopyFrom(const VersionDef& from) {
|
||||
// @@protoc_insertion_point(class_specific_copy_from_start:tensorflow.VersionDef)
|
||||
if (&from == this) return;
|
||||
Clear();
|
||||
UnsafeMergeFrom(from);
|
||||
}
|
||||
|
||||
bool VersionDef::IsInitialized() const {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VersionDef::Swap(VersionDef* other) {
|
||||
if (other == this) return;
|
||||
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
VersionDef temp;
|
||||
temp.UnsafeMergeFrom(*this);
|
||||
CopyFrom(*other);
|
||||
other->CopyFrom(temp);
|
||||
}
|
||||
}
|
||||
void VersionDef::UnsafeArenaSwap(VersionDef* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
|
||||
InternalSwap(other);
|
||||
}
|
||||
void VersionDef::InternalSwap(VersionDef* other) {
|
||||
std::swap(producer_, other->producer_);
|
||||
std::swap(min_consumer_, other->min_consumer_);
|
||||
bad_consumers_.UnsafeArenaSwap(&other->bad_consumers_);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
std::swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
|
||||
::google::protobuf::Metadata VersionDef::GetMetadata() const {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::Metadata metadata;
|
||||
metadata.descriptor = VersionDef_descriptor_;
|
||||
metadata.reflection = VersionDef_reflection_;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
#if PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// VersionDef
|
||||
|
||||
// optional int32 producer = 1;
|
||||
void VersionDef::clear_producer() {
|
||||
producer_ = 0;
|
||||
}
|
||||
::google::protobuf::int32 VersionDef::producer() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.VersionDef.producer)
|
||||
return producer_;
|
||||
}
|
||||
void VersionDef::set_producer(::google::protobuf::int32 value) {
|
||||
|
||||
producer_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.VersionDef.producer)
|
||||
}
|
||||
|
||||
// optional int32 min_consumer = 2;
|
||||
void VersionDef::clear_min_consumer() {
|
||||
min_consumer_ = 0;
|
||||
}
|
||||
::google::protobuf::int32 VersionDef::min_consumer() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.VersionDef.min_consumer)
|
||||
return min_consumer_;
|
||||
}
|
||||
void VersionDef::set_min_consumer(::google::protobuf::int32 value) {
|
||||
|
||||
min_consumer_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.VersionDef.min_consumer)
|
||||
}
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
int VersionDef::bad_consumers_size() const {
|
||||
return bad_consumers_.size();
|
||||
}
|
||||
void VersionDef::clear_bad_consumers() {
|
||||
bad_consumers_.Clear();
|
||||
}
|
||||
::google::protobuf::int32 VersionDef::bad_consumers(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.VersionDef.bad_consumers)
|
||||
return bad_consumers_.Get(index);
|
||||
}
|
||||
void VersionDef::set_bad_consumers(int index, ::google::protobuf::int32 value) {
|
||||
bad_consumers_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.VersionDef.bad_consumers)
|
||||
}
|
||||
void VersionDef::add_bad_consumers(::google::protobuf::int32 value) {
|
||||
bad_consumers_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.VersionDef.bad_consumers)
|
||||
}
|
||||
const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
|
||||
VersionDef::bad_consumers() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.VersionDef.bad_consumers)
|
||||
return bad_consumers_;
|
||||
}
|
||||
::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
|
||||
VersionDef::mutable_bad_consumers() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.VersionDef.bad_consumers)
|
||||
return &bad_consumers_;
|
||||
}
|
||||
|
||||
inline const VersionDef* VersionDef::internal_default_instance() {
|
||||
return &VersionDef_default_instance_.get();
|
||||
}
|
||||
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace tensorflow
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
239
modules/dnn/misc/tensorflow/versions.pb.h
Normal file
239
modules/dnn/misc/tensorflow/versions.pb.h
Normal file
@ -0,0 +1,239 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: versions.proto
|
||||
|
||||
#ifndef PROTOBUF_versions_2eproto__INCLUDED
|
||||
#define PROTOBUF_versions_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#if GOOGLE_PROTOBUF_VERSION < 3001000
|
||||
#error This file was generated by a newer version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please update
|
||||
#error your headers.
|
||||
#endif
|
||||
#if 3001000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
|
||||
#error This file was generated by an older version of protoc which is
|
||||
#error incompatible with your Protocol Buffer headers. Please
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/metadata.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
// @@protoc_insertion_point(includes)
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
// Internal implementation detail -- do not call these.
|
||||
void protobuf_AddDesc_versions_2eproto();
|
||||
void protobuf_InitDefaults_versions_2eproto();
|
||||
void protobuf_AssignDesc_versions_2eproto();
|
||||
void protobuf_ShutdownFile_versions_2eproto();
|
||||
|
||||
class VersionDef;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
class VersionDef : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:tensorflow.VersionDef) */ {
|
||||
public:
|
||||
VersionDef();
|
||||
virtual ~VersionDef();
|
||||
|
||||
VersionDef(const VersionDef& from);
|
||||
|
||||
inline VersionDef& operator=(const VersionDef& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
|
||||
inline void* GetMaybeArenaPointer() const {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const VersionDef& default_instance();
|
||||
|
||||
static const VersionDef* internal_default_instance();
|
||||
|
||||
void UnsafeArenaSwap(VersionDef* other);
|
||||
void Swap(VersionDef* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline VersionDef* New() const { return New(NULL); }
|
||||
|
||||
VersionDef* New(::google::protobuf::Arena* arena) const;
|
||||
void CopyFrom(const ::google::protobuf::Message& from);
|
||||
void MergeFrom(const ::google::protobuf::Message& from);
|
||||
void CopyFrom(const VersionDef& from);
|
||||
void MergeFrom(const VersionDef& from);
|
||||
void Clear();
|
||||
bool IsInitialized() const;
|
||||
|
||||
size_t ByteSizeLong() const;
|
||||
bool MergePartialFromCodedStream(
|
||||
::google::protobuf::io::CodedInputStream* input);
|
||||
void SerializeWithCachedSizes(
|
||||
::google::protobuf::io::CodedOutputStream* output) const;
|
||||
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
|
||||
bool deterministic, ::google::protobuf::uint8* output) const;
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
|
||||
return InternalSerializeWithCachedSizesToArray(false, output);
|
||||
}
|
||||
int GetCachedSize() const { return _cached_size_; }
|
||||
private:
|
||||
void SharedCtor();
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(VersionDef* other);
|
||||
void UnsafeMergeFrom(const VersionDef& from);
|
||||
protected:
|
||||
explicit VersionDef(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
}
|
||||
inline void* MaybeArenaPtr() const {
|
||||
return _internal_metadata_.raw_arena_ptr();
|
||||
}
|
||||
public:
|
||||
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
// optional int32 producer = 1;
|
||||
void clear_producer();
|
||||
static const int kProducerFieldNumber = 1;
|
||||
::google::protobuf::int32 producer() const;
|
||||
void set_producer(::google::protobuf::int32 value);
|
||||
|
||||
// optional int32 min_consumer = 2;
|
||||
void clear_min_consumer();
|
||||
static const int kMinConsumerFieldNumber = 2;
|
||||
::google::protobuf::int32 min_consumer() const;
|
||||
void set_min_consumer(::google::protobuf::int32 value);
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
int bad_consumers_size() const;
|
||||
void clear_bad_consumers();
|
||||
static const int kBadConsumersFieldNumber = 3;
|
||||
::google::protobuf::int32 bad_consumers(int index) const;
|
||||
void set_bad_consumers(int index, ::google::protobuf::int32 value);
|
||||
void add_bad_consumers(::google::protobuf::int32 value);
|
||||
const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
|
||||
bad_consumers() const;
|
||||
::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
|
||||
mutable_bad_consumers();
|
||||
|
||||
// @@protoc_insertion_point(class_scope:tensorflow.VersionDef)
|
||||
private:
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::RepeatedField< ::google::protobuf::int32 > bad_consumers_;
|
||||
mutable int _bad_consumers_cached_byte_size_;
|
||||
::google::protobuf::int32 producer_;
|
||||
::google::protobuf::int32 min_consumer_;
|
||||
mutable int _cached_size_;
|
||||
friend void protobuf_InitDefaults_versions_2eproto_impl();
|
||||
friend void protobuf_AddDesc_versions_2eproto_impl();
|
||||
friend void protobuf_AssignDesc_versions_2eproto();
|
||||
friend void protobuf_ShutdownFile_versions_2eproto();
|
||||
|
||||
void InitAsDefaultInstance();
|
||||
};
|
||||
extern ::google::protobuf::internal::ExplicitlyConstructed<VersionDef> VersionDef_default_instance_;
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
// VersionDef
|
||||
|
||||
// optional int32 producer = 1;
|
||||
inline void VersionDef::clear_producer() {
|
||||
producer_ = 0;
|
||||
}
|
||||
inline ::google::protobuf::int32 VersionDef::producer() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.VersionDef.producer)
|
||||
return producer_;
|
||||
}
|
||||
inline void VersionDef::set_producer(::google::protobuf::int32 value) {
|
||||
|
||||
producer_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.VersionDef.producer)
|
||||
}
|
||||
|
||||
// optional int32 min_consumer = 2;
|
||||
inline void VersionDef::clear_min_consumer() {
|
||||
min_consumer_ = 0;
|
||||
}
|
||||
inline ::google::protobuf::int32 VersionDef::min_consumer() const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.VersionDef.min_consumer)
|
||||
return min_consumer_;
|
||||
}
|
||||
inline void VersionDef::set_min_consumer(::google::protobuf::int32 value) {
|
||||
|
||||
min_consumer_ = value;
|
||||
// @@protoc_insertion_point(field_set:tensorflow.VersionDef.min_consumer)
|
||||
}
|
||||
|
||||
// repeated int32 bad_consumers = 3;
|
||||
inline int VersionDef::bad_consumers_size() const {
|
||||
return bad_consumers_.size();
|
||||
}
|
||||
inline void VersionDef::clear_bad_consumers() {
|
||||
bad_consumers_.Clear();
|
||||
}
|
||||
inline ::google::protobuf::int32 VersionDef::bad_consumers(int index) const {
|
||||
// @@protoc_insertion_point(field_get:tensorflow.VersionDef.bad_consumers)
|
||||
return bad_consumers_.Get(index);
|
||||
}
|
||||
inline void VersionDef::set_bad_consumers(int index, ::google::protobuf::int32 value) {
|
||||
bad_consumers_.Set(index, value);
|
||||
// @@protoc_insertion_point(field_set:tensorflow.VersionDef.bad_consumers)
|
||||
}
|
||||
inline void VersionDef::add_bad_consumers(::google::protobuf::int32 value) {
|
||||
bad_consumers_.Add(value);
|
||||
// @@protoc_insertion_point(field_add:tensorflow.VersionDef.bad_consumers)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
|
||||
VersionDef::bad_consumers() const {
|
||||
// @@protoc_insertion_point(field_list:tensorflow.VersionDef.bad_consumers)
|
||||
return bad_consumers_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
|
||||
VersionDef::mutable_bad_consumers() {
|
||||
// @@protoc_insertion_point(field_mutable_list:tensorflow.VersionDef.bad_consumers)
|
||||
return &bad_consumers_;
|
||||
}
|
||||
|
||||
inline const VersionDef* VersionDef::internal_default_instance() {
|
||||
return &VersionDef_default_instance_.get();
|
||||
}
|
||||
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
|
||||
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
|
||||
} // namespace tensorflow
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
||||
#endif // PROTOBUF_versions_2eproto__INCLUDED
|
106
modules/dnn/perf/perf_convolution.cpp
Normal file
106
modules/dnn/perf/perf_convolution.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include "perf_precomp.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cvtest
|
||||
{
|
||||
|
||||
using std::tr1::tuple;
|
||||
using std::tr1::get;
|
||||
using std::tr1::make_tuple;
|
||||
using std::make_pair;
|
||||
using namespace perf;
|
||||
using namespace testing;
|
||||
using namespace cv;
|
||||
using namespace cv::dnn;
|
||||
|
||||
enum {STRIDE_OFF = 1, STRIDE_ON = 2};
|
||||
CV_ENUM(StrideSize, STRIDE_OFF, STRIDE_ON);
|
||||
|
||||
enum {GROUP_OFF = 1, GROUP_2 = 2};
|
||||
CV_ENUM(GroupSize, GROUP_OFF, GROUP_2);
|
||||
|
||||
//Squared Size
|
||||
#define SSZ(n) cv::Size(n, n)
|
||||
|
||||
typedef std::pair<MatShape, int> InpShapeNumOut;
|
||||
typedef tuple<Size, InpShapeNumOut, GroupSize, StrideSize> ConvParam; //kernel_size, inp shape, groups, stride
|
||||
typedef TestBaseWithParam<ConvParam> ConvolutionPerfTest;
|
||||
|
||||
static inline MatShape blobShape(int count, int nplanes, int height, int width)
|
||||
{
|
||||
int data[] = {count, nplanes, height, width};
|
||||
return MatShape(data, data+4);
|
||||
}
|
||||
|
||||
PERF_TEST_P( ConvolutionPerfTest, perf, Combine(
|
||||
Values(Size(1, 1), Size(3, 3), Size(5, 5), Size(11, 11)),
|
||||
Values(make_pair(blobShape(1, 4, 224, 224), 64),
|
||||
make_pair(blobShape(1, 64, 112, 122), 128),
|
||||
make_pair(blobShape(1, 256, 28, 28), 512)),
|
||||
GroupSize::all(),
|
||||
StrideSize::all())
|
||||
)
|
||||
{
|
||||
RNG rng(0);
|
||||
|
||||
ConvParam params = GetParam();
|
||||
int ksz = get<0>(params).width;
|
||||
MatShape inpShape = get<1>(params).first;
|
||||
int outCn = get<1>(params).second;
|
||||
int groups = get<2>(params);
|
||||
int stride = (ksz >= 11) ? 4 : (int)get<3>(params);
|
||||
|
||||
int inpCn = inpShape[1];
|
||||
int wgtSize[] = { outCn, inpCn/groups, ksz, ksz };
|
||||
int biasSize[] = { outCn, 1, 1, 1 };
|
||||
const int wtype = CV_32F;
|
||||
Mat wgtBlob(4, wgtSize, wtype), biasBlob(4, biasSize, wtype);
|
||||
Mat inpBlob(4, &inpShape[0], wtype);
|
||||
rng.fill(biasBlob, RNG::UNIFORM, -1, +1);
|
||||
rng.fill(wgtBlob, RNG::UNIFORM, -1, +1);
|
||||
rng.fill(inpBlob, RNG::UNIFORM, -1, +1);
|
||||
|
||||
LayerParams lp;
|
||||
lp.set("num_output", outCn);
|
||||
lp.set("group", groups);
|
||||
lp.set("stride", stride);
|
||||
lp.set("kernel_size", ksz);
|
||||
lp.blobs.reserve(2);
|
||||
lp.blobs.push_back(wgtBlob);
|
||||
lp.blobs.push_back(biasBlob);
|
||||
|
||||
std::vector<Mat*> inpBlobs(1, &inpBlob);
|
||||
std::vector<Mat> outBlobs, internalBlobs;
|
||||
|
||||
cv::setNumThreads(cv::getNumberOfCPUs());
|
||||
|
||||
Ptr<Layer> layer = cv::dnn::LayerFactory::createLayerInstance("Convolution", lp);
|
||||
std::vector<MatShape> inputShapes(1, shape(inpBlob)), outShapes, internals;
|
||||
layer->getMemoryShapes(inputShapes, 0, outShapes, internals);
|
||||
for (int i = 0; i < outShapes.size(); i++)
|
||||
{
|
||||
outBlobs.push_back(Mat(outShapes[i], CV_32F));
|
||||
}
|
||||
for (int i = 0; i < internals.size(); i++)
|
||||
{
|
||||
internalBlobs.push_back(Mat());
|
||||
if (total(internals[i]))
|
||||
internalBlobs.back().create(internals[i], CV_32F);
|
||||
}
|
||||
|
||||
layer->finalize(inpBlobs, outBlobs);
|
||||
|
||||
Mat inpBlob2D = inpBlob.reshape(1, outCn);
|
||||
Mat wgtBlob2D = wgtBlob.reshape(1, outCn*(inpCn/groups));
|
||||
Mat outBlob2D = outBlobs[0].reshape(1, outBlobs[0].size[0]);
|
||||
declare.in(inpBlob2D, wgtBlob2D, WARMUP_RNG).out(outBlob2D).tbb_threads(cv::getNumThreads());
|
||||
|
||||
TEST_CYCLE_N(10)
|
||||
{
|
||||
layer->forward(inpBlobs, outBlobs, internalBlobs);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
}
|
172
modules/dnn/perf/perf_halide_net.cpp
Normal file
172
modules/dnn/perf/perf_halide_net.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
namespace cvtest
|
||||
{
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
using namespace cv;
|
||||
using namespace dnn;
|
||||
|
||||
static void loadNet(std::string weights, std::string proto, std::string scheduler,
|
||||
int inWidth, int inHeight, const std::string& outputLayer,
|
||||
const std::string& framework, int targetId, Net* net)
|
||||
{
|
||||
Mat input(inHeight, inWidth, CV_32FC3);
|
||||
randu(input, 0.0f, 1.0f);
|
||||
|
||||
weights = findDataFile(weights, false);
|
||||
if (!proto.empty())
|
||||
proto = findDataFile(proto, false);
|
||||
if (!scheduler.empty())
|
||||
scheduler = findDataFile(scheduler, false);
|
||||
if (framework == "caffe")
|
||||
{
|
||||
*net = cv::dnn::readNetFromCaffe(proto, weights);
|
||||
}
|
||||
else if (framework == "torch")
|
||||
{
|
||||
*net = cv::dnn::readNetFromTorch(weights);
|
||||
}
|
||||
else if (framework == "tensorflow")
|
||||
{
|
||||
*net = cv::dnn::readNetFromTensorflow(weights);
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsNotImplemented, "Unknown framework " + framework);
|
||||
|
||||
net->setInput(blobFromImage(input, 1.0, Size(), Scalar(), false));
|
||||
net->setPreferableBackend(DNN_BACKEND_HALIDE);
|
||||
net->setPreferableTarget(targetId);
|
||||
net->setHalideScheduler(scheduler);
|
||||
net->forward(outputLayer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CPU target
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
PERF_TEST(GoogLeNet, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/bvlc_googlenet.caffemodel", "dnn/bvlc_googlenet.prototxt",
|
||||
"", 227, 227, "prob", "caffe", DNN_TARGET_CPU, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(AlexNet, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/bvlc_alexnet.caffemodel", "dnn/bvlc_alexnet.prototxt",
|
||||
"dnn/halide_scheduler_alexnet.yml", 227, 227, "prob", "caffe",
|
||||
DNN_TARGET_CPU, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(ResNet50, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/ResNet-50-model.caffemodel", "dnn/ResNet-50-deploy.prototxt",
|
||||
"dnn/halide_scheduler_resnet_50.yml", 224, 224, "prob", "caffe",
|
||||
DNN_TARGET_CPU, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(SqueezeNet_v1_1, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/squeezenet_v1_1.caffemodel", "dnn/squeezenet_v1_1.prototxt",
|
||||
"dnn/halide_scheduler_squeezenet_v1_1.yml", 227, 227, "prob",
|
||||
"caffe", DNN_TARGET_CPU, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(Inception_5h, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/tensorflow_inception_graph.pb", "",
|
||||
"dnn/halide_scheduler_inception_5h.yml",
|
||||
224, 224, "softmax2", "tensorflow", DNN_TARGET_CPU, &net);
|
||||
TEST_CYCLE() net.forward("softmax2");
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(ENet, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/Enet-model-best.net", "", "dnn/halide_scheduler_enet.yml",
|
||||
512, 256, "l367_Deconvolution", "torch", DNN_TARGET_CPU, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// OpenCL target
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
PERF_TEST(GoogLeNet_opencl, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/bvlc_googlenet.caffemodel", "dnn/bvlc_googlenet.prototxt",
|
||||
"", 227, 227, "prob", "caffe", DNN_TARGET_OPENCL, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(AlexNet_opencl, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/bvlc_alexnet.caffemodel", "dnn/bvlc_alexnet.prototxt",
|
||||
"dnn/halide_scheduler_opencl_alexnet.yml", 227, 227, "prob", "caffe",
|
||||
DNN_TARGET_OPENCL, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(ResNet50_opencl, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/ResNet-50-model.caffemodel", "dnn/ResNet-50-deploy.prototxt",
|
||||
"dnn/halide_scheduler_opencl_resnet_50.yml", 224, 224, "prob", "caffe",
|
||||
DNN_TARGET_OPENCL, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
|
||||
PERF_TEST(SqueezeNet_v1_1_opencl, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/squeezenet_v1_1.caffemodel", "dnn/squeezenet_v1_1.prototxt",
|
||||
"dnn/halide_scheduler_opencl_squeezenet_v1_1.yml", 227, 227, "prob",
|
||||
"caffe", DNN_TARGET_OPENCL, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(Inception_5h_opencl, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/tensorflow_inception_graph.pb", "",
|
||||
"dnn/halide_scheduler_opencl_inception_5h.yml",
|
||||
224, 224, "softmax2", "tensorflow", DNN_TARGET_OPENCL, &net);
|
||||
TEST_CYCLE() net.forward("softmax2");
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST(ENet_opencl, HalidePerfTest)
|
||||
{
|
||||
Net net;
|
||||
loadNet("dnn/Enet-model-best.net", "", "dnn/halide_scheduler_opencl_enet.yml",
|
||||
512, 256, "l367_Deconvolution", "torch", DNN_TARGET_OPENCL, &net);
|
||||
TEST_CYCLE() net.forward();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
} // namespace cvtest
|
12
modules/dnn/perf/perf_main.cpp
Normal file
12
modules/dnn/perf/perf_main.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
static const char* extraTestDataPath =
|
||||
#ifdef WINRT
|
||||
NULL;
|
||||
#else
|
||||
getenv("OPENCV_DNN_TEST_DATA_PATH");
|
||||
#endif
|
||||
|
||||
CV_PERF_TEST_MAIN(dnn,
|
||||
extraTestDataPath ? (void)cvtest::addDataSearchPath(extraTestDataPath) : (void)0
|
||||
)
|
17
modules/dnn/perf/perf_precomp.hpp
Normal file
17
modules/dnn/perf/perf_precomp.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-declarations"
|
||||
# if defined __clang__ || defined __APPLE__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-prototypes"
|
||||
# pragma GCC diagnostic ignored "-Wextra"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __OPENCV_PERF_PRECOMP_HPP__
|
||||
#define __OPENCV_PERF_PRECOMP_HPP__
|
||||
|
||||
#include <opencv2/ts.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
#endif
|
1581
modules/dnn/src/caffe/caffe.proto
Normal file
1581
modules/dnn/src/caffe/caffe.proto
Normal file
File diff suppressed because it is too large
Load Diff
382
modules/dnn/src/caffe/caffe_importer.cpp
Normal file
382
modules/dnn/src/caffe/caffe_importer.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
using namespace cv;
|
||||
using namespace cv::dnn;
|
||||
|
||||
#if HAVE_PROTOBUF
|
||||
#include "caffe.pb.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include "caffe_io.hpp"
|
||||
|
||||
using ::google::protobuf::RepeatedField;
|
||||
using ::google::protobuf::RepeatedPtrField;
|
||||
using ::google::protobuf::Message;
|
||||
using ::google::protobuf::Descriptor;
|
||||
using ::google::protobuf::FieldDescriptor;
|
||||
using ::google::protobuf::Reflection;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
static cv::String toString(const T &v)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
class CaffeImporter : public Importer
|
||||
{
|
||||
caffe::NetParameter net;
|
||||
caffe::NetParameter netBinary;
|
||||
|
||||
public:
|
||||
|
||||
CaffeImporter(const char *pototxt, const char *caffeModel)
|
||||
{
|
||||
ReadNetParamsFromTextFileOrDie(pototxt, &net);
|
||||
|
||||
if (caffeModel && caffeModel[0])
|
||||
ReadNetParamsFromBinaryFileOrDie(caffeModel, &netBinary);
|
||||
}
|
||||
|
||||
void addParam(const Message &msg, const FieldDescriptor *field, cv::dnn::LayerParams ¶ms)
|
||||
{
|
||||
const Reflection *refl = msg.GetReflection();
|
||||
int type = field->cpp_type();
|
||||
bool isRepeated = field->is_repeated();
|
||||
const std::string &name = field->name();
|
||||
|
||||
#define SET_UP_FILED(getter, arrayConstr, gtype) \
|
||||
if (isRepeated) { \
|
||||
const RepeatedField<gtype> &v = refl->GetRepeatedField<gtype>(msg, field); \
|
||||
params.set(name, DictValue::arrayConstr(v.begin(), (int)v.size())); \
|
||||
} \
|
||||
else { \
|
||||
params.set(name, refl->getter(msg, field)); \
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
SET_UP_FILED(GetInt32, arrayInt, ::google::protobuf::int32);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
SET_UP_FILED(GetUInt32, arrayInt, ::google::protobuf::uint32);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
SET_UP_FILED(GetInt32, arrayInt, ::google::protobuf::int64);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
SET_UP_FILED(GetUInt32, arrayInt, ::google::protobuf::uint64);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
SET_UP_FILED(GetBool, arrayInt, bool);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
SET_UP_FILED(GetDouble, arrayReal, double);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
SET_UP_FILED(GetFloat, arrayReal, float);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
if (isRepeated) {
|
||||
const RepeatedPtrField<std::string> &v = refl->GetRepeatedPtrField<std::string>(msg, field);
|
||||
params.set(name, DictValue::arrayString(v.begin(), (int)v.size()));
|
||||
}
|
||||
else {
|
||||
params.set(name, refl->GetString(msg, field));
|
||||
}
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
if (isRepeated) {
|
||||
int size = refl->FieldSize(msg, field);
|
||||
std::vector<cv::String> buf(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
buf[i] = refl->GetRepeatedEnum(msg, field, i)->name();
|
||||
params.set(name, DictValue::arrayString(buf.begin(), size));
|
||||
}
|
||||
else {
|
||||
params.set(name, refl->GetEnum(msg, field)->name());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsError, "Unknown type \"" + String(field->type_name()) + "\" in prototxt");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool ends_with_param(const std::string &str)
|
||||
{
|
||||
static const std::string _param("_param");
|
||||
return (str.size() >= _param.size()) && str.compare(str.size() - _param.size(), _param.size(), _param) == 0;
|
||||
}
|
||||
|
||||
void extractLayerParams(const Message &msg, cv::dnn::LayerParams ¶ms, bool isInternal = false)
|
||||
{
|
||||
const Descriptor *msgDesc = msg.GetDescriptor();
|
||||
const Reflection *msgRefl = msg.GetReflection();
|
||||
|
||||
for (int fieldId = 0; fieldId < msgDesc->field_count(); fieldId++)
|
||||
{
|
||||
const FieldDescriptor *fd = msgDesc->field(fieldId);
|
||||
|
||||
if (!isInternal && !ends_with_param(fd->name()))
|
||||
continue;
|
||||
|
||||
bool hasData = fd->is_required() ||
|
||||
(fd->is_optional() && msgRefl->HasField(msg, fd)) ||
|
||||
(fd->is_repeated() && msgRefl->FieldSize(msg, fd) > 0);
|
||||
if (!hasData)
|
||||
continue;
|
||||
|
||||
if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE)
|
||||
{
|
||||
if (fd->is_repeated()) //Extract only first item!
|
||||
extractLayerParams(msgRefl->GetRepeatedMessage(msg, fd, 0), params, true);
|
||||
else
|
||||
extractLayerParams(msgRefl->GetMessage(msg, fd), params, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
addParam(msg, fd, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void blobShapeFromProto(const caffe::BlobProto &pbBlob, MatShape& shape)
|
||||
{
|
||||
shape.clear();
|
||||
if (pbBlob.has_num() || pbBlob.has_channels() || pbBlob.has_height() || pbBlob.has_width())
|
||||
{
|
||||
shape.push_back(pbBlob.num());
|
||||
shape.push_back(pbBlob.channels());
|
||||
shape.push_back(pbBlob.height());
|
||||
shape.push_back(pbBlob.width());
|
||||
}
|
||||
else if (pbBlob.has_shape())
|
||||
{
|
||||
const caffe::BlobShape &_shape = pbBlob.shape();
|
||||
|
||||
for (int i = 0; i < _shape.dim_size(); i++)
|
||||
shape.push_back((int)_shape.dim(i));
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsError, "Unknown shape of input blob");
|
||||
}
|
||||
|
||||
void blobFromProto(const caffe::BlobProto &pbBlob, cv::Mat &dstBlob)
|
||||
{
|
||||
MatShape shape;
|
||||
blobShapeFromProto(pbBlob, shape);
|
||||
|
||||
dstBlob.create((int)shape.size(), &shape[0], CV_32F);
|
||||
CV_Assert(pbBlob.data_size() == (int)dstBlob.total());
|
||||
|
||||
CV_DbgAssert(pbBlob.GetDescriptor()->FindFieldByLowercaseName("data")->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT);
|
||||
float *dstData = dstBlob.ptr<float>();
|
||||
|
||||
for (int i = 0; i < pbBlob.data_size(); i++)
|
||||
dstData[i] = pbBlob.data(i);
|
||||
}
|
||||
|
||||
void extractBinaryLayerParms(const caffe::LayerParameter& layer, LayerParams& layerParams)
|
||||
{
|
||||
const std::string &name = layer.name();
|
||||
|
||||
int li;
|
||||
for (li = 0; li != netBinary.layer_size(); li++)
|
||||
{
|
||||
if (netBinary.layer(li).name() == name)
|
||||
break;
|
||||
}
|
||||
|
||||
if (li == netBinary.layer_size() || netBinary.layer(li).blobs_size() == 0)
|
||||
return;
|
||||
|
||||
const caffe::LayerParameter &binLayer = netBinary.layer(li);
|
||||
layerParams.blobs.resize(binLayer.blobs_size());
|
||||
for (int bi = 0; bi < binLayer.blobs_size(); bi++)
|
||||
{
|
||||
blobFromProto(binLayer.blobs(bi), layerParams.blobs[bi]);
|
||||
}
|
||||
}
|
||||
|
||||
struct BlobNote
|
||||
{
|
||||
BlobNote(const std::string &_name, int _layerId, int _outNum) :
|
||||
name(_name.c_str()), layerId(_layerId), outNum(_outNum) {}
|
||||
|
||||
const char *name;
|
||||
int layerId, outNum;
|
||||
};
|
||||
|
||||
std::vector<BlobNote> addedBlobs;
|
||||
std::map<String, int> layerCounter;
|
||||
|
||||
void populateNet(Net dstNet)
|
||||
{
|
||||
int layersSize = net.layer_size();
|
||||
layerCounter.clear();
|
||||
addedBlobs.clear();
|
||||
addedBlobs.reserve(layersSize + 1);
|
||||
|
||||
//setup input layer names
|
||||
{
|
||||
std::vector<String> netInputs(net.input_size());
|
||||
for (int inNum = 0; inNum < net.input_size(); inNum++)
|
||||
{
|
||||
addedBlobs.push_back(BlobNote(net.input(inNum), 0, inNum));
|
||||
netInputs[inNum] = net.input(inNum);
|
||||
}
|
||||
dstNet.setInputsNames(netInputs);
|
||||
}
|
||||
|
||||
for (int li = 0; li < layersSize; li++)
|
||||
{
|
||||
const caffe::LayerParameter &layer = net.layer(li);
|
||||
String name = layer.name();
|
||||
String type = layer.type();
|
||||
LayerParams layerParams;
|
||||
|
||||
extractLayerParams(layer, layerParams);
|
||||
extractBinaryLayerParms(layer, layerParams);
|
||||
|
||||
int repetitions = layerCounter[name]++;
|
||||
if (repetitions)
|
||||
name += String("_") + toString(repetitions);
|
||||
|
||||
int id = dstNet.addLayer(name, type, layerParams);
|
||||
|
||||
for (int inNum = 0; inNum < layer.bottom_size(); inNum++)
|
||||
addInput(layer.bottom(inNum), id, inNum, dstNet);
|
||||
|
||||
for (int outNum = 0; outNum < layer.top_size(); outNum++)
|
||||
addOutput(layer, id, outNum);
|
||||
}
|
||||
|
||||
addedBlobs.clear();
|
||||
}
|
||||
|
||||
void addOutput(const caffe::LayerParameter &layer, int layerId, int outNum)
|
||||
{
|
||||
const std::string &name = layer.top(outNum);
|
||||
|
||||
bool haveDups = false;
|
||||
for (int idx = (int)addedBlobs.size() - 1; idx >= 0; idx--)
|
||||
{
|
||||
if (addedBlobs[idx].name == name)
|
||||
{
|
||||
haveDups = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (haveDups)
|
||||
{
|
||||
bool isInplace = layer.bottom_size() > outNum && layer.bottom(outNum) == name;
|
||||
if (!isInplace)
|
||||
CV_Error(Error::StsBadArg, "Duplicate blobs produced by multiple sources");
|
||||
}
|
||||
|
||||
addedBlobs.push_back(BlobNote(name, layerId, outNum));
|
||||
}
|
||||
|
||||
void addInput(const std::string &name, int layerId, int inNum, Net &dstNet)
|
||||
{
|
||||
int idx;
|
||||
for (idx = (int)addedBlobs.size() - 1; idx >= 0; idx--)
|
||||
{
|
||||
if (addedBlobs[idx].name == name)
|
||||
break;
|
||||
}
|
||||
|
||||
if (idx < 0)
|
||||
{
|
||||
CV_Error(Error::StsObjectNotFound, "Can't find output blob \"" + name + "\"");
|
||||
return;
|
||||
}
|
||||
|
||||
dstNet.connect(addedBlobs[idx].layerId, addedBlobs[idx].outNum, layerId, inNum);
|
||||
}
|
||||
|
||||
~CaffeImporter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Ptr<Importer> cv::dnn::createCaffeImporter(const String &prototxt, const String &caffeModel)
|
||||
{
|
||||
return Ptr<Importer>(new CaffeImporter(prototxt.c_str(), caffeModel.c_str()));
|
||||
}
|
||||
|
||||
#else //HAVE_PROTOBUF
|
||||
|
||||
Ptr<Importer> cv::dnn::createCaffeImporter(const String&, const String&)
|
||||
{
|
||||
CV_Error(cv::Error::StsNotImplemented, "libprotobuf required to import data from Caffe models");
|
||||
return Ptr<Importer>();
|
||||
}
|
||||
|
||||
#endif //HAVE_PROTOBUF
|
||||
|
||||
Net cv::dnn::readNetFromCaffe(const String &prototxt, const String &caffeModel /*= String()*/)
|
||||
{
|
||||
Ptr<Importer> caffeImporter = createCaffeImporter(prototxt, caffeModel);
|
||||
Net net;
|
||||
if (caffeImporter)
|
||||
caffeImporter->populateNet(net);
|
||||
return net;
|
||||
}
|
1151
modules/dnn/src/caffe/caffe_io.cpp
Normal file
1151
modules/dnn/src/caffe/caffe_io.cpp
Normal file
File diff suppressed because it is too large
Load Diff
108
modules/dnn/src/caffe/caffe_io.hpp
Normal file
108
modules/dnn/src/caffe/caffe_io.hpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//COPYRIGHT
|
||||
//
|
||||
//All contributions by the University of California:
|
||||
//Copyright (c) 2014, The Regents of the University of California (Regents)
|
||||
//All rights reserved.
|
||||
//
|
||||
//All other contributions:
|
||||
//Copyright (c) 2014, the respective contributors
|
||||
//All rights reserved.
|
||||
//
|
||||
//Caffe uses a shared copyright model: each contributor holds copyright over
|
||||
//their contributions to Caffe. The project versioning records all such
|
||||
//contribution and copyright details. If a contributor wants to further mark
|
||||
//their specific copyright on a particular contribution, they should indicate
|
||||
//their copyright solely in the commit message of the change when it is
|
||||
//committed.
|
||||
//
|
||||
//LICENSE
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
//1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
//DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
//ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//CONTRIBUTION AGREEMENT
|
||||
//
|
||||
//By contributing to the BVLC/caffe repository through pull-request, comment,
|
||||
//or otherwise, the contributor releases their content to the
|
||||
//license and copyright terms herein.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_DNN_CAFFE_IO_HPP__
|
||||
#define __OPENCV_DNN_CAFFE_IO_HPP__
|
||||
#if HAVE_PROTOBUF
|
||||
|
||||
#include "caffe.pb.h"
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
|
||||
// Read parameters from a file into a NetParameter proto message.
|
||||
void ReadNetParamsFromTextFileOrDie(const char* param_file,
|
||||
caffe::NetParameter* param);
|
||||
void ReadNetParamsFromBinaryFileOrDie(const char* param_file,
|
||||
caffe::NetParameter* param);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
104
modules/dnn/src/caffe/glog_emulator.hpp
Normal file
104
modules/dnn/src/caffe/glog_emulator.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_DNN_CAFFE_GLOG_EMULATOR_HPP__
|
||||
#define __OPENCV_DNN_CAFFE_GLOG_EMULATOR_HPP__
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#define CHECK(cond) for(cv::dnn::GLogWrapper _logger(__FILE__, CV_Func, __LINE__, "CHECK", #cond, cond); _logger.exit(); _logger.check()) _logger.stream()
|
||||
#define CHECK_EQ(a, b) for(cv::dnn::GLogWrapper _logger(__FILE__, CV_Func, __LINE__, "CHECK", #a"="#b, ((a) == (b))); _logger.exit(); _logger.check()) _logger.stream()
|
||||
#define LOG(TYPE) for(cv::dnn::GLogWrapper _logger(__FILE__, CV_Func, __LINE__, #TYPE); _logger.exit(); _logger.check()) _logger.stream()
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class GLogWrapper
|
||||
{
|
||||
const char *file, *func, *type, *cond_str;
|
||||
int line;
|
||||
bool cond_staus, exit_loop;
|
||||
std::stringstream sstream;
|
||||
|
||||
public:
|
||||
|
||||
GLogWrapper(const char *_file, const char *_func, int _line,
|
||||
const char *_type,
|
||||
const char *_cond_str = NULL, bool _cond_status = true
|
||||
) :
|
||||
file(_file), func(_func), type(_type), cond_str(_cond_str),
|
||||
line(_line), cond_staus(_cond_status), exit_loop(true) {}
|
||||
|
||||
std::iostream &stream()
|
||||
{
|
||||
return sstream;
|
||||
}
|
||||
|
||||
bool exit()
|
||||
{
|
||||
return exit_loop;
|
||||
}
|
||||
|
||||
void check()
|
||||
{
|
||||
exit_loop = false;
|
||||
|
||||
if (cond_str && !cond_staus)
|
||||
{
|
||||
cv::error(cv::Error::StsError, "FAILED: " + String(cond_str) + ". " + sstream.str(), func, file, line);
|
||||
}
|
||||
else if (!cond_str && strcmp(type, "CHECK"))
|
||||
{
|
||||
if (!std::strcmp(type, "INFO"))
|
||||
std::cout << sstream.str() << std::endl;
|
||||
else
|
||||
std::cerr << sstream.str() << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
2001
modules/dnn/src/dnn.cpp
Normal file
2001
modules/dnn/src/dnn.cpp
Normal file
File diff suppressed because it is too large
Load Diff
284
modules/dnn/src/halide_scheduler.cpp
Normal file
284
modules/dnn/src/halide_scheduler.cpp
Normal file
@ -0,0 +1,284 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "halide_scheduler.hpp"
|
||||
#include "op_halide.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
static void applySplit(const FileNode& directive, Halide::Func& func,
|
||||
const FileNode& params)
|
||||
{
|
||||
for (const auto& varNode : directive)
|
||||
{
|
||||
const std::string varName = varNode.name();
|
||||
const std::string factorName = (std::string)varNode;
|
||||
Halide::Var var(varName);
|
||||
Halide::Var outerVar(varName + "o");
|
||||
Halide::Var innerVar(varName + "i");
|
||||
// If split factor is integer or parameters map has parameter value.
|
||||
CV_Assert(varNode.isString() && !params[factorName].empty() ||
|
||||
varNode.isInt());
|
||||
int factor = (int)(varNode.isInt() ? varNode : params[factorName]);
|
||||
func.split(var, outerVar, innerVar, factor);
|
||||
}
|
||||
}
|
||||
|
||||
static void applyReorder(const FileNode& directive, Halide::Func& func)
|
||||
{
|
||||
std::string varName;
|
||||
const int numVars = directive.size();
|
||||
std::vector<Halide::VarOrRVar> reorderedVars;
|
||||
reorderedVars.reserve(numVars);
|
||||
for (int i = 0; i < numVars; ++i)
|
||||
{
|
||||
directive[i] >> varName;
|
||||
reorderedVars.push_back(Halide::Var(varName));
|
||||
}
|
||||
func.reorder(reorderedVars);
|
||||
}
|
||||
|
||||
static void applyFuse(const FileNode& directive, Halide::Func& func)
|
||||
{
|
||||
CV_Assert(directive["src"].size() >= 2);
|
||||
CV_Assert(directive["dst"].size() == 1);
|
||||
|
||||
std::string str;
|
||||
directive["src"][0] >> str;
|
||||
Halide::Var firstVar(str);
|
||||
directive["src"][1] >> str;
|
||||
Halide::Var secondVar(str);
|
||||
directive["dst"] >> str;
|
||||
Halide::Var dstVar(str);
|
||||
|
||||
func.fuse(firstVar, secondVar, dstVar);
|
||||
for (int i = 2, n = directive["src"].size(); i < n; ++i)
|
||||
{
|
||||
directive["src"][i] >> str;
|
||||
func.fuse(Halide::Var(str), dstVar, dstVar);
|
||||
}
|
||||
}
|
||||
|
||||
static void applyParallel(const FileNode& directive, Halide::Func& func)
|
||||
{
|
||||
std::string varName;
|
||||
for (int i = 0, n = directive.size(); i < n; ++i)
|
||||
{
|
||||
directive[i] >> varName;
|
||||
func.parallel(Halide::Var(varName));
|
||||
}
|
||||
}
|
||||
|
||||
static void applyUnroll(const FileNode& directive, Halide::Func& func)
|
||||
{
|
||||
std::string varName;
|
||||
for (int i = 0, n = directive.size(); i < n; ++i)
|
||||
{
|
||||
directive[i] >> varName;
|
||||
func.unroll(Halide::Var(varName));
|
||||
}
|
||||
}
|
||||
|
||||
static void applyVectorize(const FileNode& directive, Halide::Func& func,
|
||||
const FileNode& params)
|
||||
{
|
||||
for (const auto& varNode : directive)
|
||||
{
|
||||
const std::string varName = varNode.name();
|
||||
const std::string factorName = (std::string)varNode;
|
||||
// If split factor is integer or parameters map has parameter value.
|
||||
CV_Assert(varNode.isString() && !params[factorName].empty() ||
|
||||
varNode.isInt());
|
||||
int factor = (int)(varNode.isInt() ? varNode : params[factorName]);
|
||||
Halide::Var var(varName);
|
||||
Halide::Var inner(varName + "v");
|
||||
func.split(var, var, inner, factor);
|
||||
func.vectorize(inner);
|
||||
}
|
||||
}
|
||||
|
||||
static void applyStoreAt(const FileNode& directive, Halide::Func& func,
|
||||
std::map<std::string, Halide::Func>& funcsMap)
|
||||
{
|
||||
for (const auto& funcNode : directive)
|
||||
{
|
||||
const std::string targetFuncName = funcNode.name();
|
||||
if (funcsMap.find(targetFuncName) == funcsMap.end())
|
||||
CV_Error(cv::Error::StsParseError, "Function " + targetFuncName +
|
||||
" is not represented in Halide pipeline");
|
||||
Halide::Func targetFunc = funcsMap[targetFuncName];
|
||||
func.store_at(targetFunc, (std::string)funcNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void applyComputeAt(const FileNode& directive, Halide::Func& func,
|
||||
std::map<std::string, Halide::Func>& funcsMap)
|
||||
{
|
||||
for (const auto& funcNode : directive)
|
||||
{
|
||||
const std::string targetFuncName = funcNode.name();
|
||||
if (funcsMap.find(targetFuncName) == funcsMap.end())
|
||||
CV_Error(cv::Error::StsParseError, "Function " + targetFuncName +
|
||||
" is not represented in Halide pipeline");
|
||||
Halide::Func targetFunc = funcsMap[targetFuncName];
|
||||
func.compute_at(targetFunc, (std::string)funcNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void applyComputeRoot(const FileNode& directive, Halide::Func& func)
|
||||
{
|
||||
bool compute_root;
|
||||
directive >> compute_root;
|
||||
if (compute_root)
|
||||
func.compute_root();
|
||||
}
|
||||
|
||||
static void applyGpuBlocks(const FileNode& directive, Halide::Func& func)
|
||||
{
|
||||
std::string varName;
|
||||
for (int i = 0, n = directive.size(); i < n; ++i)
|
||||
{
|
||||
directive[i] >> varName;
|
||||
func.gpu_blocks(Halide::Var(varName));
|
||||
}
|
||||
}
|
||||
|
||||
static void applyGpuThreads(const FileNode& directive, Halide::Func& func)
|
||||
{
|
||||
std::string varName;
|
||||
for (int i = 0, n = directive.size(); i < n; ++i)
|
||||
{
|
||||
directive[i] >> varName;
|
||||
func.gpu_threads(Halide::Var(varName));
|
||||
}
|
||||
}
|
||||
|
||||
static void apply(const FileNode& directives, Halide::Func& func,
|
||||
std::map<std::string, Halide::Func>& funcsMap,
|
||||
const FileNode& params)
|
||||
{
|
||||
for (const auto& directive : directives)
|
||||
{
|
||||
if (directive.name() == "split")
|
||||
applySplit(directive, func, params);
|
||||
else if (directive.name() == "reorder")
|
||||
applyReorder(directive, func);
|
||||
else if (directive.name() == "fuse")
|
||||
applyFuse(directive, func);
|
||||
else if (directive.name() == "parallel")
|
||||
applyParallel(directive, func);
|
||||
else if (directive.name() == "unroll")
|
||||
applyUnroll(directive, func);
|
||||
else if (directive.name() == "vectorize")
|
||||
applyVectorize(directive, func, params);
|
||||
else if (directive.name() == "store_at")
|
||||
applyStoreAt(directive, func, funcsMap);
|
||||
else if (directive.name() == "compute_at")
|
||||
applyComputeAt(directive, func, funcsMap);
|
||||
else if (directive.name() == "compute_root")
|
||||
applyComputeRoot(directive, func);
|
||||
else if (directive.name() == "gpu_blocks")
|
||||
applyGpuBlocks(directive, func);
|
||||
else if (directive.name() == "gpu_threads")
|
||||
applyGpuThreads(directive, func);
|
||||
else
|
||||
CV_Error(Error::StsNotImplemented, "Scheduling directive " +
|
||||
directive.name() + " is not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any numeric symbols after '$' sign.
|
||||
static std::string Deunique(std::string str)
|
||||
{
|
||||
int pos = -1;
|
||||
do
|
||||
{
|
||||
pos = str.find('$');
|
||||
if (pos != -1)
|
||||
{
|
||||
int len = str.find_first_not_of("0123456789", pos + 1) - pos;
|
||||
str = str.replace(pos, len, "");
|
||||
}
|
||||
}
|
||||
while (pos != -1);
|
||||
return str;
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
HalideScheduler::HalideScheduler(const std::string& configFile)
|
||||
{
|
||||
if (!configFile.empty())
|
||||
fs = FileStorage(configFile, FileStorage::READ);
|
||||
}
|
||||
|
||||
HalideScheduler::~HalideScheduler()
|
||||
{
|
||||
if (fs.isOpened())
|
||||
fs.release();
|
||||
}
|
||||
|
||||
bool HalideScheduler::process(Ptr<BackendNode>& node)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
if (!fs.isOpened())
|
||||
return false;
|
||||
|
||||
const FileNode& scheduleNode = fs["scheduling"];
|
||||
if (scheduleNode.empty())
|
||||
CV_Error(cv::Error::StsParseError, "Scheduling file should has scheduling node");
|
||||
|
||||
std::string str;
|
||||
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.
|
||||
CV_Assert(!node.empty());
|
||||
std::vector<Halide::Func>& funcs = node.dynamicCast<HalideBackendNode>()->funcs;
|
||||
for (int i = funcs.size() - 1; i >= 0; --i)
|
||||
{
|
||||
Halide::Func& func = funcs[i];
|
||||
// For functions with the same name Halide generates unique names
|
||||
// for example func, func$1, func$2.
|
||||
// They are always formed with '$' and number.
|
||||
std::string funcName = Deunique(func.name());
|
||||
|
||||
const FileNode& funcNode = scheduleNode[funcName];
|
||||
if (!funcNode.empty())
|
||||
{
|
||||
if (!funcNode["pattern"].empty())
|
||||
{
|
||||
funcNode["pattern"] >> str;
|
||||
if (fs["patterns"][str].empty())
|
||||
CV_Error(cv::Error::StsParseError, "Scheduling pattern " + str +
|
||||
" is not defined");
|
||||
apply(fs["patterns"][str], func, funcsMap, funcNode["params"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
apply(funcNode, func, funcsMap, funcNode["params"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (funcsMap.empty())
|
||||
return false;
|
||||
}
|
||||
funcsMap[funcName] = func;
|
||||
}
|
||||
return true;
|
||||
#endif // HAVE_HALIDE
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace dnn
|
||||
} // namespace cv
|
37
modules/dnn/src/halide_scheduler.hpp
Normal file
37
modules/dnn/src/halide_scheduler.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#ifndef __OPENCV_DNN_HALIDE_SCHEDULER_HPP__
|
||||
#define __OPENCV_DNN_HALIDE_SCHEDULER_HPP__
|
||||
|
||||
#include <opencv2/dnn.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class HalideScheduler
|
||||
{
|
||||
public:
|
||||
HalideScheduler(const std::string& configFile);
|
||||
|
||||
~HalideScheduler();
|
||||
|
||||
// Returns true if pipeline found in scheduling file.
|
||||
// If more than one function, returns true if the top function scheduled.
|
||||
// Other functions are optional to scheduling.
|
||||
bool process(Ptr<BackendNode>& node);
|
||||
|
||||
private:
|
||||
FileStorage fs;
|
||||
};
|
||||
|
||||
} // namespace dnn
|
||||
} // namespace cv
|
||||
|
||||
#endif // __OPENCV_DNN_HALIDE_SCHEDULER_HPP__
|
107
modules/dnn/src/init.cpp
Normal file
107
modules/dnn/src/init.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
struct AutoInitializer
|
||||
{
|
||||
bool status;
|
||||
|
||||
AutoInitializer() : status(false)
|
||||
{
|
||||
initModule();
|
||||
}
|
||||
};
|
||||
|
||||
static AutoInitializer init;
|
||||
|
||||
void initModule()
|
||||
{
|
||||
if (init.status)
|
||||
return;
|
||||
|
||||
REG_RUNTIME_LAYER_CLASS(Slice, SliceLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Split, SplitLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Concat, ConcatLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Reshape, ReshapeLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Flatten, FlattenLayer);
|
||||
|
||||
REG_RUNTIME_LAYER_CLASS(Convolution, ConvolutionLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Pooling, PoolingLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(LRN, LRNLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(InnerProduct, InnerProductLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Softmax, SoftmaxLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(MVN, MVNLayer);
|
||||
|
||||
REG_RUNTIME_LAYER_CLASS(ReLU, ReLULayer);
|
||||
REG_RUNTIME_LAYER_CLASS(ChannelsPReLU, ChannelsPReLULayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Sigmoid, SigmoidLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(TanH, TanHLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(BNLL, BNLLLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(AbsVal, AbsLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Power, PowerLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(BatchNorm, BatchNormLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(MaxUnpool, MaxUnpoolLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Dropout, BlankLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Identity, BlankLayer);
|
||||
|
||||
REG_RUNTIME_LAYER_CLASS(Crop, CropLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Eltwise, EltwiseLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Permute, PermuteLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(PriorBox, PriorBoxLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(DetectionOutput, DetectionOutputLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(NormalizeBBox, NormalizeBBoxLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Normalize, NormalizeBBoxLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Shift, ShiftLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Padding, PaddingLayer);
|
||||
REG_RUNTIME_LAYER_CLASS(Scale, ScaleLayer);
|
||||
|
||||
init.status = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
198
modules/dnn/src/layers/batch_norm_layer.cpp
Normal file
198
modules/dnn/src/layers/batch_norm_layer.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2016, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
/*
|
||||
Implementation of Batch Normalization layer.
|
||||
*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class BatchNormLayerImpl : public BatchNormLayer
|
||||
{
|
||||
public:
|
||||
Mat weights_, bias_;
|
||||
|
||||
BatchNormLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
CV_Assert(blobs.size() >= 3);
|
||||
|
||||
hasWeights = params.get<bool>("has_weight", false);
|
||||
hasBias = params.get<bool>("has_bias", false);
|
||||
epsilon = params.get<float>("eps", 1E-5);
|
||||
|
||||
size_t n = blobs[0].total();
|
||||
CV_Assert(blobs[1].total() == n &&
|
||||
blobs[0].isContinuous() && blobs[1].isContinuous() &&
|
||||
blobs[0].type() == CV_32F && blobs[1].type() == CV_32F);
|
||||
|
||||
float varMeanScale = 1.f;
|
||||
if (!hasWeights && !hasBias) {
|
||||
CV_Assert(blobs[2].type() == CV_32F);
|
||||
varMeanScale = blobs[2].at<float>(0);
|
||||
if (varMeanScale != 0)
|
||||
varMeanScale = 1/varMeanScale;
|
||||
}
|
||||
|
||||
const int weightsBlobIndex = 2;
|
||||
const int biasBlobIndex = weightsBlobIndex + hasWeights;
|
||||
|
||||
if( hasWeights )
|
||||
{
|
||||
CV_Assert((size_t)weightsBlobIndex < blobs.size());
|
||||
const Mat& w = blobs[weightsBlobIndex];
|
||||
CV_Assert(w.isContinuous() && w.type() == CV_32F && w.total() == (size_t)n);
|
||||
}
|
||||
|
||||
if( hasBias )
|
||||
{
|
||||
CV_Assert((size_t)biasBlobIndex < blobs.size());
|
||||
const Mat& b = blobs[weightsBlobIndex];
|
||||
CV_Assert(b.isContinuous() && b.type() == CV_32F && b.total() == (size_t)n);
|
||||
}
|
||||
|
||||
const float* meanData = blobs[0].ptr<float>();
|
||||
const float* stdData = blobs[1].ptr<float>();
|
||||
const float* weightsData = hasWeights ? blobs[weightsBlobIndex].ptr<float>() : 0;
|
||||
const float* biasData = hasBias ? blobs[biasBlobIndex].ptr<float>() : 0;
|
||||
|
||||
weights_.create(1, (int)n, CV_32F);
|
||||
bias_.create(1, (int)n, CV_32F);
|
||||
|
||||
float* dstWeightsData = weights_.ptr<float>();
|
||||
float* dstBiasData = bias_.ptr<float>();
|
||||
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
float w = (hasWeights ? weightsData[i] : 1.0f) / sqrt(stdData[i] * varMeanScale + epsilon);
|
||||
dstWeightsData[i] = w;
|
||||
dstBiasData[i] = (hasBias ? biasData[i] : 0.0f) - w * meanData[i] * varMeanScale;
|
||||
}
|
||||
}
|
||||
|
||||
void getScaleShift(Mat& scale, Mat& shift) const
|
||||
{
|
||||
scale = weights_;
|
||||
shift = bias_;
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide();
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
CV_Assert(blobs.size() >= 2);
|
||||
CV_Assert(inputs.size() == 1);
|
||||
|
||||
Mat &inpBlob = *inputs[0];
|
||||
int rows = inpBlob.size[2];
|
||||
int cols = inpBlob.size[3];
|
||||
|
||||
for (size_t ii = 0; ii < outputs.size(); ii++)
|
||||
{
|
||||
Mat &outBlob = outputs[ii];
|
||||
|
||||
for(int num = 0; num < outBlob.size[0]; num++)
|
||||
{
|
||||
for (int n = 0; n < outBlob.size[1]; n++)
|
||||
{
|
||||
float w = weights_.at<float>(n);
|
||||
float b = bias_.at<float>(n);
|
||||
Mat inpBlobPlane(rows, cols, CV_32F, inpBlob.ptr<float>(num, n));
|
||||
Mat outBlobPlane(rows, cols, CV_32F, outBlob.ptr<float>(num, n));
|
||||
inpBlobPlane.convertTo(outBlobPlane, CV_32F, w, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> tryAttach(const Ptr<BackendNode>& node)
|
||||
{
|
||||
switch (node->backendId)
|
||||
{
|
||||
case DNN_BACKEND_HALIDE:
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
auto base = node.dynamicCast<HalideBackendNode>();
|
||||
Halide::Func& input = base->funcs.back();
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = attachHalide(input(x, y, c, n));
|
||||
return Ptr<BackendNode>(new HalideBackendNode(base, top));
|
||||
#endif // HAVE_HALIDE
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
Halide::Buffer<float> input = halideBuffer(inputs[0]);
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = attachHalide(input(x, y, c, n));
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
// attachHalide can work both with Halide::Buffer and Halide::Func. In the
|
||||
// second case it will be a fusion.
|
||||
Halide::Func attachHalide(const Halide::Expr& input)
|
||||
{
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
|
||||
const int numChannels = weights_.total();
|
||||
auto weights = wrapToHalideBuffer(weights_, {numChannels});
|
||||
auto bias = wrapToHalideBuffer(bias_, {numChannels});
|
||||
top(x, y, c, n) = input * weights(c) + bias(c);
|
||||
return top;
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)outputs; // suppress unused variable warning
|
||||
|
||||
int64 flops = 0;
|
||||
for(int i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
flops += 3*total(inputs[i]);
|
||||
}
|
||||
return flops;
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<BatchNormLayer> BatchNormLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<BatchNormLayer>(new BatchNormLayerImpl(params));
|
||||
}
|
||||
|
||||
} // namespace dnn
|
||||
} // namespace cv
|
78
modules/dnn/src/layers/blank_layer.cpp
Normal file
78
modules/dnn/src/layers/blank_layer.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
#include "../precomp.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
class BlankLayerImpl : public BlankLayer
|
||||
{
|
||||
public:
|
||||
BlankLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
|
||||
return true;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
for (int i = 0, n = outputs.size(); i < n; ++i)
|
||||
if (outputs[i].data != inputs[i]->data)
|
||||
inputs[i]->copyTo(outputs[i]);
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<BlankLayer> BlankLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<BlankLayer>(new BlankLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
141
modules/dnn/src/layers/concat_layer.cpp
Normal file
141
modules/dnn/src/layers/concat_layer.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "op_halide.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class ConcatLayerImpl : public ConcatLayer
|
||||
{
|
||||
public:
|
||||
ConcatLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
axis = params.get<int>("axis", 1);
|
||||
}
|
||||
|
||||
virtual bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() > 0);
|
||||
outputs.clear();
|
||||
outputs.push_back(inputs[0]);
|
||||
int cAxis = clamp(axis, inputs[0]);
|
||||
|
||||
int axisSum = 0;
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
MatShape curShape = inputs[i];
|
||||
|
||||
CV_Assert(curShape.size() == outputs.back().size());
|
||||
for (int curAxis = 0; curAxis < outputs.back().size(); curAxis++)
|
||||
{
|
||||
if (curAxis != cAxis && outputs.back()[curAxis] != curShape[curAxis])
|
||||
CV_Error(Error::StsBadSize, "Inconsitent shape for ConcatLayer");
|
||||
}
|
||||
|
||||
axisSum += curShape[cAxis];
|
||||
}
|
||||
|
||||
outputs.back()[cAxis] = axisSum;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide() && axis == 1; // By channels
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
int cAxis = clamp(axis, inputs[0]->dims);
|
||||
Mat& outMat = outputs[0];
|
||||
std::vector<Range> ranges(outputs[0].dims, Range::all());
|
||||
|
||||
ranges[cAxis].start = 0;
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
ranges[cAxis].end = ranges[cAxis].start + inputs[i]->size[cAxis];
|
||||
inputs[i]->copyTo(outMat(&ranges[0]));
|
||||
ranges[cAxis].start = ranges[cAxis].end;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &input)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
std::vector<Halide::Buffer<> > inputBuffers = halideBuffers(input);
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
int offset = inputBuffers[0].channels();
|
||||
Halide::Expr topExpr = select(c < offset,
|
||||
inputBuffers[0](x, y, c, n),
|
||||
inputBuffers[1](x, y, c - offset, n));
|
||||
for (int i = 2; i < input.size(); ++i)
|
||||
{
|
||||
offset += inputBuffers[i - 1].channels();
|
||||
topExpr = select(c < offset, topExpr,
|
||||
inputBuffers[i](x, y, c - offset, n));
|
||||
}
|
||||
top(x, y, c, n) = topExpr;
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<ConcatLayer> ConcatLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<ConcatLayer>(new ConcatLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
1145
modules/dnn/src/layers/convolution_layer.cpp
Normal file
1145
modules/dnn/src/layers/convolution_layer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
153
modules/dnn/src/layers/crop_layer.cpp
Normal file
153
modules/dnn/src/layers/crop_layer.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class CropLayerImpl : public CropLayer
|
||||
{
|
||||
public:
|
||||
CropLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
startAxis = params.get<int>("axis", 2);
|
||||
const DictValue *paramOffset = params.ptr("offset");
|
||||
|
||||
if (paramOffset)
|
||||
{
|
||||
for (int i = 0; i < paramOffset->size(); i++)
|
||||
offset.push_back(paramOffset->get<int>(i));
|
||||
}
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() == 2);
|
||||
|
||||
MatShape dstShape = inputs[0];
|
||||
int start = clamp(startAxis, dstShape);
|
||||
for (int i = start; i < dstShape.size(); i++)
|
||||
{
|
||||
dstShape[i] = inputs[1][i];
|
||||
}
|
||||
|
||||
outputs.resize(1, dstShape);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void finalize(const std::vector<Mat *> &inputs, std::vector<Mat> &outputs)
|
||||
{
|
||||
CV_Assert(2 == inputs.size());
|
||||
|
||||
const Mat &inpBlob = *inputs[0];
|
||||
const Mat &inpSzBlob = *inputs[1];
|
||||
|
||||
int dims = inpBlob.dims;
|
||||
int start_axis = clamp(startAxis, dims);
|
||||
|
||||
std::vector<int> offset_final(dims, 0);
|
||||
if (offset.size() == 1)
|
||||
{
|
||||
for (int i = start_axis; i < dims; i++)
|
||||
offset_final[i] = offset[0];
|
||||
}
|
||||
else if (offset.size() > 1)
|
||||
{
|
||||
if ((int)offset.size() != dims - start_axis)
|
||||
CV_Error(Error::StsBadArg, "number of offset values specified must be "
|
||||
"equal to the number of dimensions following axis.");
|
||||
|
||||
for (int i = start_axis; i < dims; i++)
|
||||
offset_final[i] = offset[i - start_axis];
|
||||
}
|
||||
|
||||
crop_ranges.resize(dims, Range::all());
|
||||
for (int i = 0; i < dims; i++)
|
||||
{
|
||||
if( i < start_axis )
|
||||
continue;
|
||||
|
||||
if (!offset.empty()) //normal case
|
||||
{
|
||||
if (offset_final[i] < 0 || offset_final[i] + inpSzBlob.size[i] > inpBlob.size[i])
|
||||
CV_Error(Error::StsBadArg, "invalid crop parameters");
|
||||
|
||||
crop_ranges[i] = Range(offset_final[i], offset_final[i] + inpSzBlob.size[i]);
|
||||
}
|
||||
else //detect offset automatically so that cropped image is center of original one
|
||||
{
|
||||
if (inpSzBlob.size[i] > inpBlob.size[i])
|
||||
CV_Error(Error::StsBadArg, "invalid output blob size");
|
||||
|
||||
int cur_crop = (inpBlob.size[i] - inpSzBlob.size[i]) / 2;
|
||||
crop_ranges[i] = Range(cur_crop, cur_crop + inpSzBlob.size[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat *> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
Mat &input = *inputs[0];
|
||||
Mat &output = outputs[0];
|
||||
|
||||
input(&crop_ranges[0]).copyTo(output);
|
||||
}
|
||||
|
||||
std::vector<Range> crop_ranges;
|
||||
};
|
||||
|
||||
|
||||
Ptr<CropLayer> CropLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<CropLayer>(new CropLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
798
modules/dnn/src/layers/detection_output_layer.cpp
Normal file
798
modules/dnn/src/layers/detection_output_layer.cpp
Normal file
@ -0,0 +1,798 @@
|
||||
/*M ///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include <float.h>
|
||||
#include <string>
|
||||
#include <caffe.pb.h>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
namespace util
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
std::string to_string(T value)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << value;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void make_error(const std::string& message1, const T& message2)
|
||||
{
|
||||
std::string error(message1);
|
||||
error += std::string(util::to_string<int>(message2));
|
||||
CV_Error(Error::StsBadArg, error.c_str());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool SortScorePairDescend(const std::pair<float, T>& pair1,
|
||||
const std::pair<float, T>& pair2)
|
||||
{
|
||||
return pair1.first > pair2.first;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DetectionOutputLayerImpl : public DetectionOutputLayer
|
||||
{
|
||||
public:
|
||||
unsigned _numClasses;
|
||||
bool _shareLocation;
|
||||
int _numLocClasses;
|
||||
|
||||
int _backgroundLabelId;
|
||||
|
||||
typedef caffe::PriorBoxParameter_CodeType CodeType;
|
||||
CodeType _codeType;
|
||||
|
||||
bool _varianceEncodedInTarget;
|
||||
int _keepTopK;
|
||||
float _confidenceThreshold;
|
||||
|
||||
float _nmsThreshold;
|
||||
int _topK;
|
||||
|
||||
enum { _numAxes = 4 };
|
||||
static const std::string _layerName;
|
||||
|
||||
typedef std::map<int, std::vector<caffe::NormalizedBBox> > LabelBBox;
|
||||
|
||||
bool getParameterDict(const LayerParams ¶ms,
|
||||
const std::string ¶meterName,
|
||||
DictValue& result)
|
||||
{
|
||||
if (!params.has(parameterName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result = params.get(parameterName);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T getParameter(const LayerParams ¶ms,
|
||||
const std::string ¶meterName,
|
||||
const size_t &idx=0,
|
||||
const bool required=true,
|
||||
const T& defaultValue=T())
|
||||
{
|
||||
DictValue dictValue;
|
||||
bool success = getParameterDict(params, parameterName, dictValue);
|
||||
if(!success)
|
||||
{
|
||||
if(required)
|
||||
{
|
||||
std::string message = _layerName;
|
||||
message += " layer parameter does not contain ";
|
||||
message += parameterName;
|
||||
message += " parameter.";
|
||||
CV_Error(Error::StsBadArg, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return dictValue.get<T>(idx);
|
||||
}
|
||||
|
||||
void getCodeType(const LayerParams ¶ms)
|
||||
{
|
||||
String codeTypeString = params.get<String>("code_type").toLowerCase();
|
||||
if (codeTypeString == "corner")
|
||||
_codeType = caffe::PriorBoxParameter_CodeType_CORNER;
|
||||
else if (codeTypeString == "center_size")
|
||||
_codeType = caffe::PriorBoxParameter_CodeType_CENTER_SIZE;
|
||||
else
|
||||
_codeType = caffe::PriorBoxParameter_CodeType_CORNER;
|
||||
}
|
||||
|
||||
DetectionOutputLayerImpl(const LayerParams ¶ms)
|
||||
{
|
||||
_numClasses = getParameter<unsigned>(params, "num_classes");
|
||||
_shareLocation = getParameter<bool>(params, "share_location");
|
||||
_numLocClasses = _shareLocation ? 1 : _numClasses;
|
||||
_backgroundLabelId = getParameter<int>(params, "background_label_id");
|
||||
_varianceEncodedInTarget = getParameter<bool>(params, "variance_encoded_in_target", 0, false, false);
|
||||
_keepTopK = getParameter<int>(params, "keep_top_k");
|
||||
_confidenceThreshold = getParameter<float>(params, "confidence_threshold", 0, false, -FLT_MAX);
|
||||
_topK = getParameter<int>(params, "top_k", 0, false, -1);
|
||||
|
||||
getCodeType(params);
|
||||
|
||||
// Parameters used in nms.
|
||||
_nmsThreshold = getParameter<float>(params, "nms_threshold");
|
||||
CV_Assert(_nmsThreshold > 0.);
|
||||
|
||||
setParamsFrom(params);
|
||||
}
|
||||
|
||||
void checkInputs(const std::vector<Mat*> &inputs)
|
||||
{
|
||||
for (size_t i = 1; i < inputs.size(); i++)
|
||||
{
|
||||
CV_Assert(inputs[i]->size == inputs[0]->size);
|
||||
}
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() > 0);
|
||||
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]);
|
||||
|
||||
// num() and channels() are 1.
|
||||
// Since the number of bboxes to be kept is unknown before nms, we manually
|
||||
// set it to (fake) 1.
|
||||
// Each row is a 7 dimension std::vector, which stores
|
||||
// [image_id, label, confidence, xmin, ymin, xmax, ymax]
|
||||
outputs.resize(1, shape(1, 1, 1, 7));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
const float* locationData = inputs[0]->ptr<float>();
|
||||
const float* confidenceData = inputs[1]->ptr<float>();
|
||||
const float* priorData = inputs[2]->ptr<float>();
|
||||
|
||||
int num = inputs[0]->size[0];
|
||||
int numPriors = inputs[2]->size[2] / 4;
|
||||
|
||||
// Retrieve all location predictions.
|
||||
std::vector<LabelBBox> allLocationPredictions;
|
||||
GetLocPredictions(locationData, num, numPriors, _numLocClasses,
|
||||
_shareLocation, &allLocationPredictions);
|
||||
|
||||
// Retrieve all confidences.
|
||||
std::vector<std::map<int, std::vector<float> > > allConfidenceScores;
|
||||
GetConfidenceScores(confidenceData, num, numPriors, _numClasses,
|
||||
&allConfidenceScores);
|
||||
|
||||
// Retrieve all prior bboxes. It is same within a batch since we assume all
|
||||
// images in a batch are of same dimension.
|
||||
std::vector<caffe::NormalizedBBox> priorBBoxes;
|
||||
std::vector<std::vector<float> > priorVariances;
|
||||
GetPriorBBoxes(priorData, numPriors, &priorBBoxes, &priorVariances);
|
||||
|
||||
const bool clip_bbox = false;
|
||||
// Decode all loc predictions to bboxes.
|
||||
std::vector<LabelBBox> allDecodedBBoxes;
|
||||
DecodeBBoxesAll(allLocationPredictions, priorBBoxes, priorVariances, num,
|
||||
_shareLocation, _numLocClasses, _backgroundLabelId,
|
||||
_codeType, _varianceEncodedInTarget, clip_bbox, &allDecodedBBoxes);
|
||||
|
||||
int numKept = 0;
|
||||
std::vector<std::map<int, std::vector<int> > > allIndices;
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
const LabelBBox& decodeBBoxes = allDecodedBBoxes[i];
|
||||
const std::map<int, std::vector<float> >& confidenceScores =
|
||||
allConfidenceScores[i];
|
||||
std::map<int, std::vector<int> > indices;
|
||||
int numDetections = 0;
|
||||
for (int c = 0; c < (int)_numClasses; ++c)
|
||||
{
|
||||
if (c == _backgroundLabelId)
|
||||
{
|
||||
// Ignore background class.
|
||||
continue;
|
||||
}
|
||||
if (confidenceScores.find(c) == confidenceScores.end())
|
||||
{
|
||||
// Something bad happened if there are no predictions for current label.
|
||||
util::make_error<int>("Could not find confidence predictions for label ", c);
|
||||
}
|
||||
|
||||
const std::vector<float>& scores = confidenceScores.find(c)->second;
|
||||
int label = _shareLocation ? -1 : c;
|
||||
if (decodeBBoxes.find(label) == decodeBBoxes.end())
|
||||
{
|
||||
// Something bad happened if there are no predictions for current label.
|
||||
util::make_error<int>("Could not find location predictions for label ", label);
|
||||
continue;
|
||||
}
|
||||
const std::vector<caffe::NormalizedBBox>& bboxes =
|
||||
decodeBBoxes.find(label)->second;
|
||||
ApplyNMSFast(bboxes, scores, _confidenceThreshold, _nmsThreshold, 1.0,
|
||||
_topK, &(indices[c]));
|
||||
numDetections += indices[c].size();
|
||||
}
|
||||
if (_keepTopK > -1 && numDetections > _keepTopK)
|
||||
{
|
||||
std::vector<std::pair<float, std::pair<int, int> > > scoreIndexPairs;
|
||||
for (std::map<int, std::vector<int> >::iterator it = indices.begin();
|
||||
it != indices.end(); ++it)
|
||||
{
|
||||
int label = it->first;
|
||||
const std::vector<int>& labelIndices = it->second;
|
||||
if (confidenceScores.find(label) == confidenceScores.end())
|
||||
{
|
||||
// Something bad happened for current label.
|
||||
util::make_error<int>("Could not find location predictions for label ", label);
|
||||
continue;
|
||||
}
|
||||
const std::vector<float>& scores = confidenceScores.find(label)->second;
|
||||
for (size_t j = 0; j < labelIndices.size(); ++j)
|
||||
{
|
||||
size_t idx = labelIndices[j];
|
||||
CV_Assert(idx < scores.size());
|
||||
scoreIndexPairs.push_back(
|
||||
std::make_pair(scores[idx], std::make_pair(label, idx)));
|
||||
}
|
||||
}
|
||||
// Keep outputs k results per image.
|
||||
std::sort(scoreIndexPairs.begin(), scoreIndexPairs.end(),
|
||||
util::SortScorePairDescend<std::pair<int, int> >);
|
||||
scoreIndexPairs.resize(_keepTopK);
|
||||
// Store the new indices.
|
||||
std::map<int, std::vector<int> > newIndices;
|
||||
for (size_t j = 0; j < scoreIndexPairs.size(); ++j)
|
||||
{
|
||||
int label = scoreIndexPairs[j].second.first;
|
||||
int idx = scoreIndexPairs[j].second.second;
|
||||
newIndices[label].push_back(idx);
|
||||
}
|
||||
allIndices.push_back(newIndices);
|
||||
numKept += _keepTopK;
|
||||
}
|
||||
else
|
||||
{
|
||||
allIndices.push_back(indices);
|
||||
numKept += numDetections;
|
||||
}
|
||||
}
|
||||
|
||||
if (numKept == 0)
|
||||
{
|
||||
CV_ErrorNoReturn(Error::StsError, "Couldn't find any detections");
|
||||
return;
|
||||
}
|
||||
int outputShape[] = {1, 1, numKept, 7};
|
||||
outputs[0].create(4, outputShape, CV_32F);
|
||||
float* outputsData = outputs[0].ptr<float>();
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
const std::map<int, std::vector<float> >& confidenceScores =
|
||||
allConfidenceScores[i];
|
||||
const LabelBBox& decodeBBoxes = allDecodedBBoxes[i];
|
||||
for (std::map<int, std::vector<int> >::iterator it = allIndices[i].begin();
|
||||
it != allIndices[i].end(); ++it)
|
||||
{
|
||||
int label = it->first;
|
||||
if (confidenceScores.find(label) == confidenceScores.end())
|
||||
{
|
||||
// Something bad happened if there are no predictions for current label.
|
||||
util::make_error<int>("Could not find confidence predictions for label ", label);
|
||||
continue;
|
||||
}
|
||||
const std::vector<float>& scores = confidenceScores.find(label)->second;
|
||||
int locLabel = _shareLocation ? -1 : label;
|
||||
if (decodeBBoxes.find(locLabel) == decodeBBoxes.end())
|
||||
{
|
||||
// Something bad happened if there are no predictions for current label.
|
||||
util::make_error<int>("Could not find location predictions for label ", locLabel);
|
||||
continue;
|
||||
}
|
||||
const std::vector<caffe::NormalizedBBox>& bboxes =
|
||||
decodeBBoxes.find(locLabel)->second;
|
||||
std::vector<int>& indices = it->second;
|
||||
|
||||
for (size_t j = 0; j < indices.size(); ++j)
|
||||
{
|
||||
int idx = indices[j];
|
||||
outputsData[count * 7] = i;
|
||||
outputsData[count * 7 + 1] = label;
|
||||
outputsData[count * 7 + 2] = scores[idx];
|
||||
caffe::NormalizedBBox clipBBox = bboxes[idx];
|
||||
outputsData[count * 7 + 3] = clipBBox.xmin();
|
||||
outputsData[count * 7 + 4] = clipBBox.ymin();
|
||||
outputsData[count * 7 + 5] = clipBBox.xmax();
|
||||
outputsData[count * 7 + 6] = clipBBox.ymax();
|
||||
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute bbox size.
|
||||
float BBoxSize(const caffe::NormalizedBBox& bbox,
|
||||
const bool normalized=true)
|
||||
{
|
||||
if (bbox.xmax() < bbox.xmin() || bbox.ymax() < bbox.ymin())
|
||||
{
|
||||
// If bbox is invalid (e.g. xmax < xmin or ymax < ymin), return 0.
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bbox.has_size())
|
||||
{
|
||||
return bbox.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
float width = bbox.xmax() - bbox.xmin();
|
||||
float height = bbox.ymax() - bbox.ymin();
|
||||
if (normalized)
|
||||
{
|
||||
return width * height;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If bbox is not within range [0, 1].
|
||||
return (width + 1) * (height + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clip the caffe::NormalizedBBox such that the range for each corner is [0, 1].
|
||||
void ClipBBox(const caffe::NormalizedBBox& bbox,
|
||||
caffe::NormalizedBBox* clipBBox)
|
||||
{
|
||||
clipBBox->set_xmin(std::max(std::min(bbox.xmin(), 1.f), 0.f));
|
||||
clipBBox->set_ymin(std::max(std::min(bbox.ymin(), 1.f), 0.f));
|
||||
clipBBox->set_xmax(std::max(std::min(bbox.xmax(), 1.f), 0.f));
|
||||
clipBBox->set_ymax(std::max(std::min(bbox.ymax(), 1.f), 0.f));
|
||||
clipBBox->clear_size();
|
||||
clipBBox->set_size(BBoxSize(*clipBBox));
|
||||
clipBBox->set_difficult(bbox.difficult());
|
||||
}
|
||||
|
||||
// Decode a bbox according to a prior bbox.
|
||||
void DecodeBBox(
|
||||
const caffe::NormalizedBBox& prior_bbox, const std::vector<float>& prior_variance,
|
||||
const CodeType code_type, const bool variance_encoded_in_target,
|
||||
const bool clip_bbox, const caffe::NormalizedBBox& bbox,
|
||||
caffe::NormalizedBBox* decode_bbox) {
|
||||
if (code_type == caffe::PriorBoxParameter_CodeType_CORNER) {
|
||||
if (variance_encoded_in_target) {
|
||||
// variance is encoded in target, we simply need to add the offset
|
||||
// predictions.
|
||||
decode_bbox->set_xmin(prior_bbox.xmin() + bbox.xmin());
|
||||
decode_bbox->set_ymin(prior_bbox.ymin() + bbox.ymin());
|
||||
decode_bbox->set_xmax(prior_bbox.xmax() + bbox.xmax());
|
||||
decode_bbox->set_ymax(prior_bbox.ymax() + bbox.ymax());
|
||||
} else {
|
||||
// variance is encoded in bbox, we need to scale the offset accordingly.
|
||||
decode_bbox->set_xmin(
|
||||
prior_bbox.xmin() + prior_variance[0] * bbox.xmin());
|
||||
decode_bbox->set_ymin(
|
||||
prior_bbox.ymin() + prior_variance[1] * bbox.ymin());
|
||||
decode_bbox->set_xmax(
|
||||
prior_bbox.xmax() + prior_variance[2] * bbox.xmax());
|
||||
decode_bbox->set_ymax(
|
||||
prior_bbox.ymax() + prior_variance[3] * bbox.ymax());
|
||||
}
|
||||
} else if (code_type == caffe::PriorBoxParameter_CodeType_CENTER_SIZE) {
|
||||
float prior_width = prior_bbox.xmax() - prior_bbox.xmin();
|
||||
CV_Assert(prior_width > 0);
|
||||
float prior_height = prior_bbox.ymax() - prior_bbox.ymin();
|
||||
CV_Assert(prior_height > 0);
|
||||
float prior_center_x = (prior_bbox.xmin() + prior_bbox.xmax()) / 2.;
|
||||
float prior_center_y = (prior_bbox.ymin() + prior_bbox.ymax()) / 2.;
|
||||
|
||||
float decode_bbox_center_x, decode_bbox_center_y;
|
||||
float decode_bbox_width, decode_bbox_height;
|
||||
if (variance_encoded_in_target) {
|
||||
// variance is encoded in target, we simply need to retore the offset
|
||||
// predictions.
|
||||
decode_bbox_center_x = bbox.xmin() * prior_width + prior_center_x;
|
||||
decode_bbox_center_y = bbox.ymin() * prior_height + prior_center_y;
|
||||
decode_bbox_width = exp(bbox.xmax()) * prior_width;
|
||||
decode_bbox_height = exp(bbox.ymax()) * prior_height;
|
||||
} else {
|
||||
// variance is encoded in bbox, we need to scale the offset accordingly.
|
||||
decode_bbox_center_x =
|
||||
prior_variance[0] * bbox.xmin() * prior_width + prior_center_x;
|
||||
decode_bbox_center_y =
|
||||
prior_variance[1] * bbox.ymin() * prior_height + prior_center_y;
|
||||
decode_bbox_width =
|
||||
exp(prior_variance[2] * bbox.xmax()) * prior_width;
|
||||
decode_bbox_height =
|
||||
exp(prior_variance[3] * bbox.ymax()) * prior_height;
|
||||
}
|
||||
|
||||
decode_bbox->set_xmin(decode_bbox_center_x - decode_bbox_width / 2.);
|
||||
decode_bbox->set_ymin(decode_bbox_center_y - decode_bbox_height / 2.);
|
||||
decode_bbox->set_xmax(decode_bbox_center_x + decode_bbox_width / 2.);
|
||||
decode_bbox->set_ymax(decode_bbox_center_y + decode_bbox_height / 2.);
|
||||
} else {
|
||||
CV_Error(Error::StsBadArg, "Unknown LocLossType.");
|
||||
}
|
||||
float bbox_size = BBoxSize(*decode_bbox);
|
||||
decode_bbox->set_size(bbox_size);
|
||||
if (clip_bbox) {
|
||||
ClipBBox(*decode_bbox, decode_bbox);
|
||||
}
|
||||
}
|
||||
|
||||
// Decode a set of bboxes according to a set of prior bboxes.
|
||||
void DecodeBBoxes(
|
||||
const std::vector<caffe::NormalizedBBox>& prior_bboxes,
|
||||
const std::vector<std::vector<float> >& prior_variances,
|
||||
const CodeType code_type, const bool variance_encoded_in_target,
|
||||
const bool clip_bbox, const std::vector<caffe::NormalizedBBox>& bboxes,
|
||||
std::vector<caffe::NormalizedBBox>* decode_bboxes) {
|
||||
CV_Assert(prior_bboxes.size() == prior_variances.size());
|
||||
CV_Assert(prior_bboxes.size() == bboxes.size());
|
||||
int num_bboxes = prior_bboxes.size();
|
||||
if (num_bboxes >= 1) {
|
||||
CV_Assert(prior_variances[0].size() == 4);
|
||||
}
|
||||
decode_bboxes->clear();
|
||||
for (int i = 0; i < num_bboxes; ++i) {
|
||||
caffe::NormalizedBBox decode_bbox;
|
||||
DecodeBBox(prior_bboxes[i], prior_variances[i], code_type,
|
||||
variance_encoded_in_target, clip_bbox, bboxes[i], &decode_bbox);
|
||||
decode_bboxes->push_back(decode_bbox);
|
||||
}
|
||||
}
|
||||
|
||||
// Decode all bboxes in a batch.
|
||||
void DecodeBBoxesAll(const std::vector<LabelBBox>& all_loc_preds,
|
||||
const std::vector<caffe::NormalizedBBox>& prior_bboxes,
|
||||
const std::vector<std::vector<float> >& prior_variances,
|
||||
const int num, const bool share_location,
|
||||
const int num_loc_classes, const int background_label_id,
|
||||
const CodeType code_type, const bool variance_encoded_in_target,
|
||||
const bool clip, std::vector<LabelBBox>* all_decode_bboxes) {
|
||||
CV_Assert(all_loc_preds.size() == num);
|
||||
all_decode_bboxes->clear();
|
||||
all_decode_bboxes->resize(num);
|
||||
for (int i = 0; i < num; ++i) {
|
||||
// Decode predictions into bboxes.
|
||||
LabelBBox& decode_bboxes = (*all_decode_bboxes)[i];
|
||||
for (int c = 0; c < num_loc_classes; ++c) {
|
||||
int label = share_location ? -1 : c;
|
||||
if (label == background_label_id) {
|
||||
// Ignore background class.
|
||||
continue;
|
||||
}
|
||||
if (all_loc_preds[i].find(label) == all_loc_preds[i].end()) {
|
||||
// Something bad happened if there are no predictions for current label.
|
||||
util::make_error<int>("Could not find location predictions for label ", label);
|
||||
}
|
||||
const std::vector<caffe::NormalizedBBox>& label_loc_preds =
|
||||
all_loc_preds[i].find(label)->second;
|
||||
DecodeBBoxes(prior_bboxes, prior_variances,
|
||||
code_type, variance_encoded_in_target, clip,
|
||||
label_loc_preds, &(decode_bboxes[label]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get prior bounding boxes from prior_data.
|
||||
// prior_data: 1 x 2 x num_priors * 4 x 1 blob.
|
||||
// num_priors: number of priors.
|
||||
// prior_bboxes: stores all the prior bboxes in the format of caffe::NormalizedBBox.
|
||||
// prior_variances: stores all the variances needed by prior bboxes.
|
||||
void GetPriorBBoxes(const float* priorData, const int& numPriors,
|
||||
std::vector<caffe::NormalizedBBox>* priorBBoxes,
|
||||
std::vector<std::vector<float> >* priorVariances)
|
||||
{
|
||||
priorBBoxes->clear();
|
||||
priorVariances->clear();
|
||||
for (int i = 0; i < numPriors; ++i)
|
||||
{
|
||||
int startIdx = i * 4;
|
||||
caffe::NormalizedBBox bbox;
|
||||
bbox.set_xmin(priorData[startIdx]);
|
||||
bbox.set_ymin(priorData[startIdx + 1]);
|
||||
bbox.set_xmax(priorData[startIdx + 2]);
|
||||
bbox.set_ymax(priorData[startIdx + 3]);
|
||||
float bboxSize = BBoxSize(bbox);
|
||||
bbox.set_size(bboxSize);
|
||||
priorBBoxes->push_back(bbox);
|
||||
}
|
||||
|
||||
for (int i = 0; i < numPriors; ++i)
|
||||
{
|
||||
int startIdx = (numPriors + i) * 4;
|
||||
std::vector<float> var;
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
var.push_back(priorData[startIdx + j]);
|
||||
}
|
||||
priorVariances->push_back(var);
|
||||
}
|
||||
}
|
||||
|
||||
// Scale the caffe::NormalizedBBox w.r.t. height and width.
|
||||
void ScaleBBox(const caffe::NormalizedBBox& bbox,
|
||||
const int height, const int width,
|
||||
caffe::NormalizedBBox* scaleBBox)
|
||||
{
|
||||
scaleBBox->set_xmin(bbox.xmin() * width);
|
||||
scaleBBox->set_ymin(bbox.ymin() * height);
|
||||
scaleBBox->set_xmax(bbox.xmax() * width);
|
||||
scaleBBox->set_ymax(bbox.ymax() * height);
|
||||
scaleBBox->clear_size();
|
||||
bool normalized = !(width > 1 || height > 1);
|
||||
scaleBBox->set_size(BBoxSize(*scaleBBox, normalized));
|
||||
scaleBBox->set_difficult(bbox.difficult());
|
||||
}
|
||||
|
||||
// Get location predictions from loc_data.
|
||||
// loc_data: num x num_preds_per_class * num_loc_classes * 4 blob.
|
||||
// num: the number of images.
|
||||
// num_preds_per_class: number of predictions per class.
|
||||
// num_loc_classes: number of location classes. It is 1 if share_location is
|
||||
// true; and is equal to number of classes needed to predict otherwise.
|
||||
// share_location: if true, all classes share the same location prediction.
|
||||
// loc_preds: stores the location prediction, where each item contains
|
||||
// location prediction for an image.
|
||||
void GetLocPredictions(const float* locData, const int num,
|
||||
const int numPredsPerClass, const int numLocClasses,
|
||||
const bool shareLocation, std::vector<LabelBBox>* locPreds)
|
||||
{
|
||||
locPreds->clear();
|
||||
if (shareLocation)
|
||||
{
|
||||
CV_Assert(numLocClasses == 1);
|
||||
}
|
||||
locPreds->resize(num);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
LabelBBox& labelBBox = (*locPreds)[i];
|
||||
for (int p = 0; p < numPredsPerClass; ++p)
|
||||
{
|
||||
int startIdx = p * numLocClasses * 4;
|
||||
for (int c = 0; c < numLocClasses; ++c)
|
||||
{
|
||||
int label = shareLocation ? -1 : c;
|
||||
if (labelBBox.find(label) == labelBBox.end())
|
||||
{
|
||||
labelBBox[label].resize(numPredsPerClass);
|
||||
}
|
||||
labelBBox[label][p].set_xmin(locData[startIdx + c * 4]);
|
||||
labelBBox[label][p].set_ymin(locData[startIdx + c * 4 + 1]);
|
||||
labelBBox[label][p].set_xmax(locData[startIdx + c * 4 + 2]);
|
||||
labelBBox[label][p].set_ymax(locData[startIdx + c * 4 + 3]);
|
||||
}
|
||||
}
|
||||
locData += numPredsPerClass * numLocClasses * 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Get confidence predictions from conf_data.
|
||||
// conf_data: num x num_preds_per_class * num_classes blob.
|
||||
// num: the number of images.
|
||||
// num_preds_per_class: number of predictions per class.
|
||||
// num_classes: number of classes.
|
||||
// conf_preds: stores the confidence prediction, where each item contains
|
||||
// confidence prediction for an image.
|
||||
void GetConfidenceScores(const float* confData, const int num,
|
||||
const int numPredsPerClass, const int numClasses,
|
||||
std::vector<std::map<int, std::vector<float> > >* confPreds)
|
||||
{
|
||||
confPreds->clear();
|
||||
confPreds->resize(num);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
std::map<int, std::vector<float> >& labelScores = (*confPreds)[i];
|
||||
for (int p = 0; p < numPredsPerClass; ++p)
|
||||
{
|
||||
int startIdx = p * numClasses;
|
||||
for (int c = 0; c < numClasses; ++c)
|
||||
{
|
||||
labelScores[c].push_back(confData[startIdx + c]);
|
||||
}
|
||||
}
|
||||
confData += numPredsPerClass * numClasses;
|
||||
}
|
||||
}
|
||||
|
||||
// Do non maximum suppression given bboxes and scores.
|
||||
// Inspired by Piotr Dollar's NMS implementation in EdgeBox.
|
||||
// https://goo.gl/jV3JYS
|
||||
// bboxes: a set of bounding boxes.
|
||||
// scores: a set of corresponding confidences.
|
||||
// score_threshold: a threshold used to filter detection results.
|
||||
// nms_threshold: a threshold used in non maximum suppression.
|
||||
// top_k: if not -1, keep at most top_k picked indices.
|
||||
// indices: the kept indices of bboxes after nms.
|
||||
void ApplyNMSFast(const std::vector<caffe::NormalizedBBox>& bboxes,
|
||||
const std::vector<float>& scores, const float score_threshold,
|
||||
const float nms_threshold, const float eta, const int top_k,
|
||||
std::vector<int>* indices) {
|
||||
// Sanity check.
|
||||
CV_Assert(bboxes.size() == scores.size());
|
||||
|
||||
// Get top_k scores (with corresponding indices).
|
||||
std::vector<std::pair<float, int> > score_index_vec;
|
||||
GetMaxScoreIndex(scores, score_threshold, top_k, &score_index_vec);
|
||||
|
||||
// Do nms.
|
||||
float adaptive_threshold = nms_threshold;
|
||||
indices->clear();
|
||||
while (score_index_vec.size() != 0) {
|
||||
const int idx = score_index_vec.front().second;
|
||||
bool keep = true;
|
||||
for (int k = 0; k < indices->size(); ++k) {
|
||||
if (keep) {
|
||||
const int kept_idx = (*indices)[k];
|
||||
float overlap = JaccardOverlap(bboxes[idx], bboxes[kept_idx]);
|
||||
keep = overlap <= adaptive_threshold;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (keep) {
|
||||
indices->push_back(idx);
|
||||
}
|
||||
score_index_vec.erase(score_index_vec.begin());
|
||||
if (keep && eta < 1 && adaptive_threshold > 0.5) {
|
||||
adaptive_threshold *= eta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get max scores with corresponding indices.
|
||||
// scores: a set of scores.
|
||||
// threshold: only consider scores higher than the threshold.
|
||||
// top_k: if -1, keep all; otherwise, keep at most top_k.
|
||||
// score_index_vec: store the sorted (score, index) pair.
|
||||
void GetMaxScoreIndex(const std::vector<float>& scores, const float threshold,const int top_k,
|
||||
std::vector<std::pair<float, int> >* score_index_vec)
|
||||
{
|
||||
// Generate index score pairs.
|
||||
for (size_t i = 0; i < scores.size(); ++i)
|
||||
{
|
||||
if (scores[i] > threshold)
|
||||
{
|
||||
score_index_vec->push_back(std::make_pair(scores[i], i));
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the score pair according to the scores in descending order
|
||||
std::stable_sort(score_index_vec->begin(), score_index_vec->end(),
|
||||
util::SortScorePairDescend<int>);
|
||||
|
||||
// Keep top_k scores if needed.
|
||||
if (top_k > -1 && top_k < (int)score_index_vec->size())
|
||||
{
|
||||
score_index_vec->resize(top_k);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the intersection between two bboxes.
|
||||
void IntersectBBox(const caffe::NormalizedBBox& bbox1,
|
||||
const caffe::NormalizedBBox& bbox2,
|
||||
caffe::NormalizedBBox* intersect_bbox) {
|
||||
if (bbox2.xmin() > bbox1.xmax() || bbox2.xmax() < bbox1.xmin() ||
|
||||
bbox2.ymin() > bbox1.ymax() || bbox2.ymax() < bbox1.ymin())
|
||||
{
|
||||
// Return [0, 0, 0, 0] if there is no intersection.
|
||||
intersect_bbox->set_xmin(0);
|
||||
intersect_bbox->set_ymin(0);
|
||||
intersect_bbox->set_xmax(0);
|
||||
intersect_bbox->set_ymax(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
intersect_bbox->set_xmin(std::max(bbox1.xmin(), bbox2.xmin()));
|
||||
intersect_bbox->set_ymin(std::max(bbox1.ymin(), bbox2.ymin()));
|
||||
intersect_bbox->set_xmax(std::min(bbox1.xmax(), bbox2.xmax()));
|
||||
intersect_bbox->set_ymax(std::min(bbox1.ymax(), bbox2.ymax()));
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the jaccard (intersection over union IoU) overlap between two bboxes.
|
||||
float JaccardOverlap(const caffe::NormalizedBBox& bbox1,
|
||||
const caffe::NormalizedBBox& bbox2,
|
||||
const bool normalized=true)
|
||||
{
|
||||
caffe::NormalizedBBox intersect_bbox;
|
||||
IntersectBBox(bbox1, bbox2, &intersect_bbox);
|
||||
float intersect_width, intersect_height;
|
||||
if (normalized)
|
||||
{
|
||||
intersect_width = intersect_bbox.xmax() - intersect_bbox.xmin();
|
||||
intersect_height = intersect_bbox.ymax() - intersect_bbox.ymin();
|
||||
}
|
||||
else
|
||||
{
|
||||
intersect_width = intersect_bbox.xmax() - intersect_bbox.xmin() + 1;
|
||||
intersect_height = intersect_bbox.ymax() - intersect_bbox.ymin() + 1;
|
||||
}
|
||||
if (intersect_width > 0 && intersect_height > 0)
|
||||
{
|
||||
float intersect_size = intersect_width * intersect_height;
|
||||
float bbox1_size = BBoxSize(bbox1);
|
||||
float bbox2_size = BBoxSize(bbox2);
|
||||
return intersect_size / (bbox1_size + bbox2_size - intersect_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const std::string DetectionOutputLayerImpl::_layerName = std::string("DetectionOutput");
|
||||
|
||||
Ptr<DetectionOutputLayer> DetectionOutputLayer::create(const LayerParams ¶ms)
|
||||
{
|
||||
return Ptr<DetectionOutputLayer>(new DetectionOutputLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
502
modules/dnn/src/layers/elementwise_layers.cpp
Normal file
502
modules/dnn/src/layers/elementwise_layers.cpp
Normal file
@ -0,0 +1,502 @@
|
||||
#include "../precomp.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
using std::abs;
|
||||
using std::exp;
|
||||
using std::tanh;
|
||||
using std::pow;
|
||||
|
||||
template<typename Func>
|
||||
class ElementWiseLayer : public Func::Layer
|
||||
{
|
||||
public:
|
||||
class PBody : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
const Func* func_;
|
||||
const Mat* src_;
|
||||
Mat* dst_;
|
||||
int nstripes_;
|
||||
|
||||
PBody(const Func &func, const Mat &src, Mat& dst, int nstripes)
|
||||
{
|
||||
func_ = &func;
|
||||
src_ = &src;
|
||||
dst_ = &dst;
|
||||
nstripes_ = nstripes;
|
||||
}
|
||||
|
||||
void operator()(const Range &r) const
|
||||
{
|
||||
int nstripes = nstripes_, nsamples, outCn;
|
||||
size_t planeSize;
|
||||
|
||||
if( src_->dims == 4 )
|
||||
{
|
||||
nsamples = src_->size[0];
|
||||
outCn = src_->size[1];
|
||||
planeSize = (size_t)src_->size[2]*src_->size[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
nsamples = outCn = 1;
|
||||
planeSize = (size_t)src_->total();
|
||||
}
|
||||
|
||||
size_t stripeSize = (planeSize + nstripes - 1)/nstripes;
|
||||
size_t stripeStart = r.start*stripeSize;
|
||||
size_t stripeEnd = std::min(r.end*stripeSize, planeSize);
|
||||
|
||||
for( int i = 0; i < nsamples; i++ )
|
||||
{
|
||||
const float* srcptr = src_->ptr<float>(i) + stripeStart;
|
||||
float* dstptr = dst_->ptr<float>(i) + stripeStart;
|
||||
func_->apply(srcptr, dstptr, (int)(stripeEnd - stripeStart), planeSize, 0, outCn);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ElementWiseLayer(const Func &f=Func()) { func = f; }
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide();
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> tryAttach(const Ptr<BackendNode>& node)
|
||||
{
|
||||
switch (node->backendId)
|
||||
{
|
||||
case DNN_BACKEND_HALIDE:
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
auto base = node.dynamicCast<HalideBackendNode>();
|
||||
Halide::Func& input = base->funcs.back();
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (this->name.empty() ? Halide::Func() : Halide::Func(this->name));
|
||||
func.attachHalide(input(x, y, c, n), top);
|
||||
return Ptr<BackendNode>(new HalideBackendNode(base, top));
|
||||
#endif // HAVE_HALIDE
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
Halide::Buffer<float> input = halideBuffer(inputs[0]);
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (this->name.empty() ? Halide::Func() : Halide::Func(this->name));
|
||||
func.attachHalide(input(x, y, c, n), top);
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
|
||||
return true;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
const Mat &src = *inputs[i];
|
||||
Mat &dst = outputs[i];
|
||||
CV_Assert(src.size == dst.size && src.type() == dst.type() &&
|
||||
src.isContinuous() && dst.isContinuous() && src.type() == CV_32F);
|
||||
|
||||
const int nstripes = getNumThreads();
|
||||
PBody body(func, src, dst, nstripes);
|
||||
parallel_for_(Range(0, nstripes), body, nstripes);
|
||||
}
|
||||
}
|
||||
|
||||
void forwardSlice(const float* src, float* dst, int len, size_t planeSize, int cn0, int cn1) const
|
||||
{
|
||||
func.apply(src, dst, len, planeSize, cn0, cn1);
|
||||
}
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
long flops = 0;
|
||||
for (int i = 0; i < outputs.size(); i++)
|
||||
{
|
||||
flops += total(outputs[i]) * func.getFLOPSPerElement();
|
||||
}
|
||||
return flops;
|
||||
}
|
||||
|
||||
Func func;
|
||||
bool run_parallel;
|
||||
};
|
||||
|
||||
struct ReLUFunctor
|
||||
{
|
||||
typedef ReLULayer Layer;
|
||||
float slope;
|
||||
|
||||
explicit ReLUFunctor(float slope_=1.f) : slope(slope_) {}
|
||||
|
||||
void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const
|
||||
{
|
||||
float s = slope;
|
||||
for( int cn = cn0; cn < cn1; cn++, srcptr += planeSize, dstptr += planeSize )
|
||||
{
|
||||
int i = 0;
|
||||
#if CV_SIMD128
|
||||
v_float32x4 s4 = v_setall_f32(s), z = v_setzero_f32();
|
||||
for( ; i <= len - 16; i += 16 )
|
||||
{
|
||||
v_float32x4 x0 = v_load(srcptr + i);
|
||||
v_float32x4 x1 = v_load(srcptr + i + 4);
|
||||
v_float32x4 x2 = v_load(srcptr + i + 8);
|
||||
v_float32x4 x3 = v_load(srcptr + i + 12);
|
||||
x0 = v_select(x0 >= z, x0, x0*s4);
|
||||
x1 = v_select(x1 >= z, x1, x1*s4);
|
||||
x2 = v_select(x2 >= z, x2, x2*s4);
|
||||
x3 = v_select(x3 >= z, x3, x3*s4);
|
||||
v_store(dstptr + i, x0);
|
||||
v_store(dstptr + i + 4, x1);
|
||||
v_store(dstptr + i + 8, x2);
|
||||
v_store(dstptr + i + 12, x3);
|
||||
}
|
||||
#endif
|
||||
for( ; i < len; i++ )
|
||||
{
|
||||
float x = srcptr[i];
|
||||
dstptr[i] = x >= 0.f ? x : s*x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
void attachHalide(const Halide::Expr& input, Halide::Func& top)
|
||||
{
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
if (slope)
|
||||
{
|
||||
top(x, y, c, n) = select(input >= 0.0f, input, slope);
|
||||
}
|
||||
else
|
||||
{
|
||||
top(x, y, c, n) = max(input, 0.0f);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
int64 getFLOPSPerElement() const { return 1; }
|
||||
};
|
||||
|
||||
struct TanHFunctor
|
||||
{
|
||||
typedef TanHLayer Layer;
|
||||
|
||||
void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const
|
||||
{
|
||||
for( int cn = cn0; cn < cn1; cn++, srcptr += planeSize, dstptr += planeSize )
|
||||
{
|
||||
for( int i = 0; i < len; i++ )
|
||||
{
|
||||
float x = srcptr[i];
|
||||
dstptr[i] = tanh(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
void attachHalide(const Halide::Expr& input, Halide::Func& top)
|
||||
{
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
top(x, y, c, n) = tanh(input);
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
int64 getFLOPSPerElement() const { return 1; }
|
||||
};
|
||||
|
||||
struct SigmoidFunctor
|
||||
{
|
||||
typedef SigmoidLayer Layer;
|
||||
|
||||
void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const
|
||||
{
|
||||
for( int cn = cn0; cn < cn1; cn++, srcptr += planeSize, dstptr += planeSize )
|
||||
{
|
||||
for( int i = 0; i < len; i++ )
|
||||
{
|
||||
float x = srcptr[i];
|
||||
dstptr[i] = 1.f/(1.f + exp(-x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
void attachHalide(const Halide::Expr& input, Halide::Func& top)
|
||||
{
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
top(x, y, c, n) = 1.0f / (1.0f + exp(-input));
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
int64 getFLOPSPerElement() const { return 3; }
|
||||
};
|
||||
|
||||
struct AbsValFunctor
|
||||
{
|
||||
typedef AbsLayer Layer;
|
||||
|
||||
void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const
|
||||
{
|
||||
for( int cn = cn0; cn < cn1; cn++, srcptr += planeSize, dstptr += planeSize )
|
||||
{
|
||||
for( int i = 0; i < len; i++ )
|
||||
{
|
||||
float x = srcptr[i];
|
||||
dstptr[i] = abs(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
void attachHalide(const Halide::Expr& input, Halide::Func& top)
|
||||
{
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
top(x, y, c, n) = abs(input);
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
int64 getFLOPSPerElement() const { return 1; }
|
||||
};
|
||||
|
||||
struct BNLLFunctor
|
||||
{
|
||||
typedef BNLLLayer Layer;
|
||||
|
||||
void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const
|
||||
{
|
||||
for( int cn = cn0; cn < cn1; cn++, srcptr += planeSize, dstptr += planeSize )
|
||||
{
|
||||
for( int i = 0; i < len; i++ )
|
||||
{
|
||||
float x = srcptr[i];
|
||||
dstptr[i] = log(1.f + exp(-abs(x)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
void attachHalide(const Halide::Expr& input, Halide::Func& top)
|
||||
{
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
top(x, y, c, n) = log(1.0f + exp(-abs(input)));
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
int64 getFLOPSPerElement() const { return 5; }
|
||||
};
|
||||
|
||||
struct PowerFunctor
|
||||
{
|
||||
typedef PowerLayer Layer;
|
||||
|
||||
float power;
|
||||
float scale;
|
||||
float shift;
|
||||
|
||||
explicit PowerFunctor(float power_ = 1.f, float scale_ = 1.f, float shift_ = 0.f)
|
||||
: power(power_), scale(scale_), shift(shift_) {}
|
||||
|
||||
void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const
|
||||
{
|
||||
float a = scale, b = shift, p = power;
|
||||
if( p == 1.f )
|
||||
{
|
||||
for( int cn = cn0; cn < cn1; cn++, srcptr += planeSize, dstptr += planeSize )
|
||||
{
|
||||
for( int i = 0; i < len; i++ )
|
||||
{
|
||||
float x = srcptr[i];
|
||||
dstptr[i] = a*x + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int cn = cn0; cn < cn1; cn++, srcptr += planeSize, dstptr += planeSize )
|
||||
{
|
||||
for( int i = 0; i < len; i++ )
|
||||
{
|
||||
float x = srcptr[i];
|
||||
dstptr[i] = pow(a*x + b, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
void attachHalide(const Halide::Expr& input, Halide::Func& top)
|
||||
{
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Expr topExpr = (scale == 1.0f ? input : input * scale);
|
||||
if (shift)
|
||||
{
|
||||
topExpr += shift;
|
||||
}
|
||||
if (power != 1.0f)
|
||||
{
|
||||
topExpr = pow(topExpr, power);
|
||||
}
|
||||
top(x, y, c, n) = topExpr;
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
int64 getFLOPSPerElement() const { return power == 1 ? 2 : 10; }
|
||||
};
|
||||
|
||||
|
||||
struct ChannelsPReLUFunctor
|
||||
{
|
||||
typedef ChannelsPReLULayer Layer;
|
||||
Mat scale;
|
||||
|
||||
explicit ChannelsPReLUFunctor(const Mat& scale_=Mat()) : scale(scale_)
|
||||
{
|
||||
}
|
||||
|
||||
void apply(const float* srcptr, float* dstptr, int len, size_t planeSize, int cn0, int cn1) const
|
||||
{
|
||||
CV_Assert(scale.isContinuous() && scale.type() == CV_32F);
|
||||
|
||||
const float* scaleptr = scale.ptr<float>();
|
||||
CV_Assert( 0 <= cn0 && cn0 < cn1 && cn1 <= (int)scale.total() );
|
||||
|
||||
for( int cn = cn0; cn < cn1; cn++, srcptr += planeSize, dstptr += planeSize )
|
||||
{
|
||||
float s = scaleptr[cn];
|
||||
int i = 0;
|
||||
#if CV_SIMD128
|
||||
v_float32x4 s4 = v_setall_f32(s), z = v_setzero_f32();
|
||||
for( ; i <= len - 16; i += 16 )
|
||||
{
|
||||
v_float32x4 x0 = v_load(ptr + i);
|
||||
v_float32x4 x1 = v_load(ptr + i + 4);
|
||||
v_float32x4 x2 = v_load(ptr + i + 8);
|
||||
v_float32x4 x3 = v_load(ptr + i + 12);
|
||||
x0 = v_select(x0 >= z, x0, x0*s4);
|
||||
x1 = v_select(x1 >= z, x1, x1*s4);
|
||||
x2 = v_select(x2 >= z, x2, x2*s4);
|
||||
x3 = v_select(x3 >= z, x3, x3*s4);
|
||||
v_store(ptr + i, x0);
|
||||
v_store(ptr + i + 4, x1);
|
||||
v_store(ptr + i + 8, x2);
|
||||
v_store(ptr + i + 12, x3);
|
||||
}
|
||||
#endif
|
||||
for( ; i < len; i++ )
|
||||
{
|
||||
float x = srcptr[i];
|
||||
dstptr[i] = x >= 0.f ? x : s*x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
void attachHalide(const Halide::Expr& input, Halide::Func& top)
|
||||
{
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
auto weights = wrapToHalideBuffer(scale, {(int)scale.total()});
|
||||
top(x, y, c, n) = select(input >= 0.0f, input, weights(c) * input);
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
int64 getFLOPSPerElement() const { return 1; }
|
||||
};
|
||||
|
||||
#define ACTIVATION_CREATOR_FOR(_Layer, _Functor, ...) \
|
||||
Ptr<_Layer> _Layer::create() { \
|
||||
return return Ptr<_Layer>( new ElementWiseLayer<_Functor>(_Functor()) ); }
|
||||
|
||||
|
||||
Ptr<ReLULayer> ReLULayer::create(const LayerParams& params)
|
||||
{
|
||||
float negativeSlope = params.get<float>("negative_slope", 0.f);
|
||||
Ptr<ReLULayer> l(new ElementWiseLayer<ReLUFunctor>(ReLUFunctor(negativeSlope)));
|
||||
l->setParamsFrom(params);
|
||||
l->negativeSlope = negativeSlope;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
Ptr<TanHLayer> TanHLayer::create(const LayerParams& params)
|
||||
{
|
||||
Ptr<TanHLayer> l(new ElementWiseLayer<TanHFunctor>());
|
||||
l->setParamsFrom(params);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
Ptr<SigmoidLayer> SigmoidLayer::create(const LayerParams& params)
|
||||
{
|
||||
Ptr<SigmoidLayer> l(new ElementWiseLayer<SigmoidFunctor>());
|
||||
l->setParamsFrom(params);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
Ptr<AbsLayer> AbsLayer::create(const LayerParams& params)
|
||||
{
|
||||
Ptr<AbsLayer> l(new ElementWiseLayer<AbsValFunctor>());
|
||||
l->setParamsFrom(params);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
Ptr<BNLLLayer> BNLLLayer::create(const LayerParams& params)
|
||||
{
|
||||
Ptr<BNLLLayer> l(new ElementWiseLayer<BNLLFunctor>());
|
||||
l->setParamsFrom(params);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
Ptr<PowerLayer> PowerLayer::create(const LayerParams& params)
|
||||
{
|
||||
float power = params.get<float>("power", 1.0f);
|
||||
float scale = params.get<float>("scale", 1.0f);
|
||||
float shift = params.get<float>("shift", 0.0f);
|
||||
Ptr<PowerLayer> l(new ElementWiseLayer<PowerFunctor>(PowerFunctor(power, scale, shift)));
|
||||
l->setParamsFrom(params);
|
||||
l->power = power;
|
||||
l->scale = scale;
|
||||
l->shift = shift;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
Ptr<ChannelsPReLULayer> ChannelsPReLULayer::create(const LayerParams& params)
|
||||
{
|
||||
Ptr<ChannelsPReLULayer> l(new ElementWiseLayer<ChannelsPReLUFunctor>(ChannelsPReLUFunctor(params.blobs[0])));
|
||||
l->setParamsFrom(params);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
219
modules/dnn/src/layers/eltwise_layer.cpp
Normal file
219
modules/dnn/src/layers/eltwise_layer.cpp
Normal file
@ -0,0 +1,219 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "op_halide.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class EltwiseLayerImpl : public EltwiseLayer
|
||||
{
|
||||
public:
|
||||
EltwiseOp op;
|
||||
std::vector<int> coeffs;
|
||||
|
||||
EltwiseLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
op = EltwiseLayer::SUM;
|
||||
if (params.has("operation"))
|
||||
{
|
||||
String operation = params.get<String>("operation").toLowerCase();
|
||||
if (operation == "prod")
|
||||
op = EltwiseLayer::PROD;
|
||||
else if (operation == "sum")
|
||||
op = EltwiseLayer::SUM;
|
||||
else if (operation == "max")
|
||||
op = EltwiseLayer::MAX;
|
||||
else
|
||||
CV_Error(cv::Error::StsBadArg, "Unknown operaticon type \"" + operation + "\"");
|
||||
}
|
||||
|
||||
if (params.has("coeff"))
|
||||
{
|
||||
DictValue paramCoeff = params.get("coeff");
|
||||
int i, n = paramCoeff.size();
|
||||
coeffs.resize(n);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
coeffs[i] = paramCoeff.get<int>(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide();
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() >= 2);
|
||||
CV_Assert(coeffs.size() == 0 || coeffs.size() == inputs.size());
|
||||
CV_Assert(op == SUM || coeffs.size() == 0);
|
||||
|
||||
for (int i = 1; i < inputs.size(); i++)
|
||||
{
|
||||
CV_Assert(inputs[0] == inputs[i]);
|
||||
}
|
||||
|
||||
outputs.assign(1, inputs[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat *> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
Mat& output = outputs[0];
|
||||
switch (op)
|
||||
{
|
||||
case SUM:
|
||||
CV_Assert(coeffs.size() == 0 || coeffs.size() == inputs.size());
|
||||
if (0 < coeffs.size())
|
||||
{
|
||||
output.setTo(0.);
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
output += *inputs[i] * coeffs[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
add(*inputs[0], *inputs[1], output);
|
||||
for (size_t i = 2; i < inputs.size(); i++)
|
||||
{
|
||||
output += *inputs[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROD:
|
||||
output.setTo(1.);
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
output = output.mul(*inputs[i]);
|
||||
}
|
||||
break;
|
||||
case MAX:
|
||||
cv::max(*inputs[0], *inputs[1], output);
|
||||
for (size_t i = 2; i < inputs.size(); i++)
|
||||
{
|
||||
cv::max(output, *inputs[i], output);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CV_Assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &input)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::Expr topExpr;
|
||||
std::vector<Halide::Buffer<> > inputBuffers = halideBuffers(input);
|
||||
switch (op)
|
||||
{
|
||||
case SUM:
|
||||
if (coeffs.empty())
|
||||
{
|
||||
topExpr = inputBuffers[0](x, y, c, n) +
|
||||
inputBuffers[1](x, y, c, n);
|
||||
for (int i = 2; i < inputBuffers.size(); ++i)
|
||||
topExpr += inputBuffers[i](x, y, c, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
topExpr = coeffs[0] * inputBuffers[0](x, y, c, n) +
|
||||
coeffs[1] * inputBuffers[1](x, y, c, n);
|
||||
for (int i = 2; i < inputBuffers.size(); ++i)
|
||||
topExpr += coeffs[i] * inputBuffers[i](x, y, c, n);
|
||||
}
|
||||
break;
|
||||
case PROD:
|
||||
topExpr = inputBuffers[0](x, y, c, n) *
|
||||
inputBuffers[1](x, y, c, n);
|
||||
for (int i = 2; i < inputBuffers.size(); ++i)
|
||||
topExpr *= inputBuffers[i](x, y, c, n);
|
||||
break;
|
||||
case MAX:
|
||||
topExpr = max(inputBuffers[0](x, y, c, n),
|
||||
inputBuffers[1](x, y, c, n));
|
||||
for (int i = 2; i < inputBuffers.size(); ++i)
|
||||
topExpr = max(topExpr, inputBuffers[i](x, y, c, n));
|
||||
break;
|
||||
default:
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
top(x, y, c, n) = topExpr;
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)outputs; // suppress unused variable warning
|
||||
CV_Assert(inputs.size());
|
||||
|
||||
long flops = inputs.size() * total(inputs[0]);
|
||||
|
||||
return flops;
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<EltwiseLayer> EltwiseLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<EltwiseLayer>(new EltwiseLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
125
modules/dnn/src/layers/flatten_layer.cpp
Normal file
125
modules/dnn/src/layers/flatten_layer.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include <float.h>
|
||||
#include <algorithm>
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class FlattenLayerImpl : public FlattenLayer
|
||||
{
|
||||
public:
|
||||
FlattenLayerImpl(const LayerParams ¶ms)
|
||||
{
|
||||
_startAxis = params.get<int>("axis", 1);
|
||||
_endAxis = params.get<int>("end_axis", -1);
|
||||
setParamsFrom(params);
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() > 0);
|
||||
for (size_t i = 1; i < inputs.size(); i++)
|
||||
{
|
||||
CV_Assert(inputs[i] == inputs[0]);
|
||||
}
|
||||
|
||||
int numAxes = inputs[0].size();
|
||||
int startAxis = clamp(_startAxis, numAxes);
|
||||
int endAxis = clamp(_endAxis, numAxes);
|
||||
|
||||
for (size_t i = 1; i < inputs.size(); i++)
|
||||
{
|
||||
CV_Assert(inputs[i] == inputs[0]);
|
||||
}
|
||||
|
||||
|
||||
CV_Assert(startAxis >= 0);
|
||||
CV_Assert(endAxis >= startAxis && endAxis < (int)numAxes);
|
||||
|
||||
size_t flattenedDimensionSize = total(inputs[0], startAxis, endAxis + 1);
|
||||
|
||||
MatShape outputShapeVec;
|
||||
for (int i = 0; i < startAxis; i++)
|
||||
{
|
||||
outputShapeVec.push_back(inputs[0][i]);
|
||||
}
|
||||
outputShapeVec.push_back(flattenedDimensionSize);
|
||||
for (size_t i = endAxis + 1; i < numAxes; i++)
|
||||
{
|
||||
outputShapeVec.push_back(inputs[0][i]);
|
||||
}
|
||||
CV_Assert(outputShapeVec.size() <= 4);
|
||||
|
||||
outputs.resize(inputs.size(), outputShapeVec);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
MatShape outShape = shape(outputs[i]);
|
||||
outputs[i] = inputs[i]->reshape(1, (int)outShape.size(), &outShape[0]);
|
||||
}
|
||||
}
|
||||
|
||||
int _startAxis;
|
||||
int _endAxis;
|
||||
};
|
||||
|
||||
Ptr<FlattenLayer> FlattenLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<FlattenLayer>(new FlattenLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
281
modules/dnn/src/layers/fully_connected_layer.cpp
Normal file
281
modules/dnn/src/layers/fully_connected_layer.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class FullyConnectedLayerImpl : public InnerProductLayer
|
||||
{
|
||||
public:
|
||||
enum { VEC_ALIGN = 8 };
|
||||
|
||||
FullyConnectedLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
CV_Assert(1 <= blobs.size() && blobs.size() <= 2);
|
||||
|
||||
int numOutput = params.get<int>("num_output");
|
||||
int innerSize = (int)blobs[0].total() / numOutput;
|
||||
bias = params.get<bool>("bias_term", true);
|
||||
axis = params.get<int>("axis", 1);
|
||||
|
||||
CV_Assert(blobs[0].dims >= 2 && (size_t)(innerSize * numOutput) == blobs[0].total());
|
||||
CV_Assert(!bias || (blobs.size() == 2 && (size_t)numOutput == blobs[1].total()));
|
||||
|
||||
weightsMat = blobs[0] = blobs[0].reshape(1, numOutput);
|
||||
int vecsize = weightsMat.cols;
|
||||
if( vecsize % VEC_ALIGN != 0 )
|
||||
{
|
||||
int vecsize_aligned = (int)alignSize(vecsize, VEC_ALIGN);
|
||||
Mat weightsBuf(weightsMat.rows, vecsize_aligned, weightsMat.type());
|
||||
Mat wpadding = weightsBuf.colRange(vecsize, vecsize_aligned);
|
||||
wpadding.setTo(Scalar::all(0.));
|
||||
weightsMat = weightsBuf.colRange(0, vecsize);
|
||||
blobs[0].copyTo(weightsMat);
|
||||
blobs[0] = weightsMat;
|
||||
}
|
||||
|
||||
if (bias)
|
||||
biasMat = blobs[1] = blobs[1].reshape(1, 1);
|
||||
else
|
||||
biasMat = Mat::zeros(1, numOutput, weightsMat.type());
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &) const
|
||||
{
|
||||
CV_Assert(inputs.size() > 0);
|
||||
CV_Assert(1 <= blobs.size() && blobs.size() <= 2);
|
||||
CV_Assert(blobs[0].dims == 2);
|
||||
|
||||
int cAxis = clamp(axis, inputs[0]);
|
||||
int outerSize = total(inputs[0], 0, cAxis);
|
||||
int numOutput = blobs[0].size[0];
|
||||
outputs.resize(inputs.size(), shape(outerSize, numOutput));
|
||||
|
||||
CV_Assert(!bias || (size_t)numOutput == blobs[1].total());
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide() && axis == 1;
|
||||
}
|
||||
|
||||
class FullConnected : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
FullConnected(const Mat& srcMat, const Mat& weights, const Mat& biasMat, Mat& dstMat, int nstripes)
|
||||
{
|
||||
CV_Assert( srcMat.dims == 2 && srcMat.cols == weights.cols &&
|
||||
dstMat.rows == srcMat.rows && dstMat.cols == weights.rows &&
|
||||
srcMat.type() == weights.type() && weights.type() == dstMat.type() &&
|
||||
srcMat.type() == CV_32F &&
|
||||
(biasMat.empty() || (biasMat.type() == srcMat.type() &&
|
||||
biasMat.isContinuous() && (int)biasMat.total() == dstMat.cols)) );
|
||||
|
||||
srcMat_ = &srcMat;
|
||||
weights_ = &weights;
|
||||
biasMat_ = &biasMat;
|
||||
dstMat_ = &dstMat;
|
||||
nstripes_ = nstripes;
|
||||
useAVX2_ = checkHardwareSupport(CPU_AVX2);
|
||||
}
|
||||
|
||||
void operator()(const Range& r) const
|
||||
{
|
||||
int valign = FullyConnectedLayerImpl::VEC_ALIGN;
|
||||
int nsamples = srcMat_->rows;
|
||||
int nw0 = weights_->rows;
|
||||
int k, vecsize = srcMat_->cols;
|
||||
int vecsize_aligned = (int)alignSize(vecsize, VEC_ALIGN);
|
||||
int nstripes = nstripes_;
|
||||
size_t total = (size_t)nsamples*nw0;
|
||||
size_t stripeSize = (total + nstripes - 1)/nstripes;
|
||||
size_t stripeStart = r.start*stripeSize;
|
||||
size_t stripeEnd = r.end == nstripes ? total : std::min(r.end*stripeSize, total);
|
||||
size_t wstep = weights_->step1();
|
||||
AutoBuffer<float> srcbuf(vecsize_aligned + valign);
|
||||
float* sptr = alignPtr((float*)srcbuf, (int)(valign*sizeof(float)));
|
||||
|
||||
for( k = vecsize; k < vecsize_aligned; k++ )
|
||||
sptr[k] = 0.f;
|
||||
|
||||
for( size_t ofs = stripeStart; ofs < stripeEnd; )
|
||||
{
|
||||
int sampleIdx = (int)(ofs / nw0);
|
||||
int delta = (int)(ofs - (size_t)sampleIdx*nw0);
|
||||
const float* sptr_ = srcMat_->ptr<float>(sampleIdx);
|
||||
const float* wptr = weights_->ptr<float>(delta);
|
||||
float* dptr = dstMat_->ptr<float>(sampleIdx) + delta;
|
||||
const float* biasptr = biasMat_->ptr<float>() + delta;
|
||||
int nw = std::min(nw0 - delta, (int)(stripeEnd - ofs));
|
||||
|
||||
memcpy(sptr, sptr_, vecsize*sizeof(sptr[0]));
|
||||
|
||||
#if CV_DNN_TRY_AVX2
|
||||
if( useAVX2_ )
|
||||
fastGEMM1T_avx2( sptr, wptr, wstep, biasptr, dptr, nw, vecsize);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
#if CV_SIMD128
|
||||
for( ; i <= nw - 4; i += 4, wptr += 4*wstep )
|
||||
{
|
||||
vfloat32x4 vs0 = v_setall_f32(0.f), vs1 = v_setall_f32(0.f);
|
||||
vfloat32x4 vs2 = v_setall_f32(0.f), vs3 = v_setall_f32(0.f);
|
||||
|
||||
for( k = 0; k < vecsize; k += 4 )
|
||||
{
|
||||
vfloat32x4 v = v_load_aligned(sptr + k);
|
||||
vs0 += v*v_load_aligned(wptr + k);
|
||||
vs1 += v*v_load_aligned(wptr + wstep + k);
|
||||
vs2 += v*v_load_aligned(wptr + wstep*2 + k);
|
||||
vs3 += v*v_load_aligned(wptr + wstep*3 + k);
|
||||
}
|
||||
|
||||
vfloat32x4 s = v_reduce_sum4(vs0, vs1, vs2, vs3);
|
||||
s += v_load(biasptr + i);
|
||||
v_store(dptr + i, s);
|
||||
}
|
||||
#endif
|
||||
|
||||
for( ; i < nw; i++, wptr += wstep )
|
||||
{
|
||||
float s0=biasptr[i];
|
||||
|
||||
for( k = 0; k < vecsize; k++ )
|
||||
{
|
||||
float v = sptr[k];
|
||||
s0 += v*wptr[k];
|
||||
}
|
||||
dptr[i] = s0;
|
||||
}
|
||||
}
|
||||
ofs += nw;
|
||||
}
|
||||
}
|
||||
|
||||
const Mat *srcMat_, *weights_, *biasMat_;
|
||||
Mat* dstMat_;
|
||||
int nstripes_;
|
||||
bool useAVX2_;
|
||||
};
|
||||
|
||||
void forward(std::vector<Mat*> &input, std::vector<Mat> &output, std::vector<Mat> &)
|
||||
{
|
||||
int axisCan = clamp(axis, input[0]->dims);
|
||||
int outerSize = input[0]->total(0, axisCan);
|
||||
|
||||
for (size_t i = 0; i < input.size(); i++)
|
||||
{
|
||||
Mat srcMat = input[i]->reshape(1, outerSize);
|
||||
Mat dstMat = output[i].reshape(1, outerSize);
|
||||
|
||||
const int nstripes = getNumThreads();
|
||||
FullConnected fconn(srcMat, weightsMat, biasMat, dstMat, nstripes);
|
||||
parallel_for_(Range(0, nstripes), fconn, nstripes);
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
int inW, inH, inC, inN, outC = blobs[0].size[0];
|
||||
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
|
||||
getCanonicalSize(inputBuffer, &inW, &inH, &inC, &inN);
|
||||
auto weights = wrapToHalideBuffer(blobs[0], {inW, inH, inC, outC});
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::RDom r(0, inW, 0, inH, 0, inC);
|
||||
Halide::Expr topExpr = sum(inputBuffer(r.x, r.y, r.z, n) *
|
||||
weights(r.x, r.y, r.z, c));
|
||||
if (bias)
|
||||
{
|
||||
Halide::Buffer<float> bias = wrapToHalideBuffer(blobs[1], {outC});
|
||||
topExpr += bias(c);
|
||||
}
|
||||
top(x, y, c, n) = topExpr;
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)inputs; // suppress unused variable warning
|
||||
long flops = 0;
|
||||
|
||||
int innerSize = blobs[0].size[1];
|
||||
for(int i = 0; i < outputs.size(); i++)
|
||||
{
|
||||
flops += 3*innerSize*total(outputs[i]);
|
||||
}
|
||||
|
||||
return flops;
|
||||
|
||||
}
|
||||
|
||||
bool bias;
|
||||
Mat weightsMat, biasMat;
|
||||
};
|
||||
|
||||
Ptr<InnerProductLayer> InnerProductLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<InnerProductLayer>(new FullyConnectedLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
358
modules/dnn/src/layers/layers_common.avx2.cpp
Normal file
358
modules/dnn/src/layers/layers_common.avx2.cpp
Normal file
@ -0,0 +1,358 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "opencv2/core/hal/intrin.hpp"
|
||||
|
||||
#if CV_DNN_TRY_AVX2
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
|
||||
#define _mm256_load_ps _mm256_loadu_ps // "weights" in fastConv_avx2 is not always aligned to 32 bytes
|
||||
|
||||
void fastConv_avx2( const float* weights, size_t wstep, const float* bias,
|
||||
const float* rowbuf, float* output, const int* outShape,
|
||||
int blockSize, int vecsize, int vecsize_aligned,
|
||||
const float* relu, bool initOutput )
|
||||
{
|
||||
int outCn = outShape[1];
|
||||
size_t outPlaneSize = outShape[2]*outShape[3];
|
||||
float r0 = 1.f, r1 = 1.f, r2 = 1.f;
|
||||
__m256 vr0 = _mm256_set1_ps(1.f), vr1 = vr0, vr2 = vr0, z = _mm256_setzero_ps();
|
||||
|
||||
// now compute dot product of the weights
|
||||
// and im2row-transformed part of the tensor
|
||||
for( int i = 0; i < outCn; i += 3 )
|
||||
{
|
||||
const float* wptr0 = weights + i*wstep;
|
||||
const float* wptr1 = wptr0 + wstep;
|
||||
const float* wptr2 = wptr1 + wstep;
|
||||
float* outptr0 = output + i*outPlaneSize;
|
||||
float* outptr1 = outptr0 + outPlaneSize;
|
||||
float* outptr2 = outptr1 + outPlaneSize;
|
||||
float bias0 = bias[i], bias1 = bias[i+1], bias2 = bias[i+2];
|
||||
|
||||
if( i+2 >= outCn )
|
||||
{
|
||||
wptr2 = wptr1;
|
||||
outptr2 = outptr1;
|
||||
bias2 = bias1;
|
||||
if( i+1 >= outCn )
|
||||
{
|
||||
wptr2 = wptr1 = wptr0;
|
||||
outptr2 = outptr1 = outptr0;
|
||||
bias2 = bias1 = bias0;
|
||||
}
|
||||
}
|
||||
|
||||
if( relu )
|
||||
{
|
||||
r0 = relu[i];
|
||||
r1 = relu[i+1];
|
||||
r2 = relu[i+2];
|
||||
vr0 = _mm256_set1_ps(r0);
|
||||
vr1 = _mm256_set1_ps(r1);
|
||||
vr2 = _mm256_set1_ps(r2);
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
for( ; j <= blockSize - 4; j += 4 )
|
||||
{
|
||||
const float* rptr = rowbuf + j*vecsize_aligned;
|
||||
|
||||
__m256 vs00 = _mm256_setzero_ps(), vs01 = _mm256_setzero_ps(),
|
||||
vs02 = _mm256_setzero_ps(), vs03 = _mm256_setzero_ps(),
|
||||
vs10 = _mm256_setzero_ps(), vs11 = _mm256_setzero_ps(),
|
||||
vs12 = _mm256_setzero_ps(), vs13 = _mm256_setzero_ps(),
|
||||
vs20 = _mm256_setzero_ps(), vs21 = _mm256_setzero_ps(),
|
||||
vs22 = _mm256_setzero_ps(), vs23 = _mm256_setzero_ps();
|
||||
|
||||
for( int k = 0; k < vecsize; k += 8, rptr += 8 )
|
||||
{
|
||||
__m256 w0 = _mm256_load_ps(wptr0 + k);
|
||||
__m256 w1 = _mm256_load_ps(wptr1 + k);
|
||||
__m256 w2 = _mm256_load_ps(wptr2 + k);
|
||||
__m256 r0 = _mm256_load_ps(rptr);
|
||||
|
||||
vs00 = _mm256_fmadd_ps(w0, r0, vs00);
|
||||
vs10 = _mm256_fmadd_ps(w1, r0, vs10);
|
||||
vs20 = _mm256_fmadd_ps(w2, r0, vs20);
|
||||
|
||||
r0 = _mm256_load_ps(rptr + vecsize_aligned);
|
||||
vs01 = _mm256_fmadd_ps(w0, r0, vs01);
|
||||
vs11 = _mm256_fmadd_ps(w1, r0, vs11);
|
||||
vs21 = _mm256_fmadd_ps(w2, r0, vs21);
|
||||
|
||||
r0 = _mm256_load_ps(rptr + vecsize_aligned*2);
|
||||
vs02 = _mm256_fmadd_ps(w0, r0, vs02);
|
||||
vs12 = _mm256_fmadd_ps(w1, r0, vs12);
|
||||
vs22 = _mm256_fmadd_ps(w2, r0, vs22);
|
||||
|
||||
r0 = _mm256_load_ps(rptr + vecsize_aligned*3);
|
||||
vs03 = _mm256_fmadd_ps(w0, r0, vs03);
|
||||
vs13 = _mm256_fmadd_ps(w1, r0, vs13);
|
||||
vs23 = _mm256_fmadd_ps(w2, r0, vs23);
|
||||
}
|
||||
|
||||
__m256 t0 = _mm256_hadd_ps(_mm256_hadd_ps(vs00, vs01), _mm256_hadd_ps(vs02, vs03));
|
||||
__m256 t1 = _mm256_hadd_ps(_mm256_hadd_ps(vs10, vs11), _mm256_hadd_ps(vs12, vs13));
|
||||
__m256 t2 = _mm256_hadd_ps(_mm256_hadd_ps(vs20, vs21), _mm256_hadd_ps(vs22, vs23));
|
||||
|
||||
t0 = _mm256_add_ps(t0, _mm256_permute2f128_ps(t0, t0, 1));
|
||||
t1 = _mm256_add_ps(t1, _mm256_permute2f128_ps(t1, t1, 1));
|
||||
t2 = _mm256_add_ps(t2, _mm256_permute2f128_ps(t2, t2, 1));
|
||||
|
||||
__m256 s0, s1, s2;
|
||||
|
||||
if( initOutput )
|
||||
{
|
||||
s0 = _mm256_set1_ps(bias0);
|
||||
s1 = _mm256_set1_ps(bias1);
|
||||
s2 = _mm256_set1_ps(bias2);
|
||||
}
|
||||
else
|
||||
{
|
||||
s0 = _mm256_castps128_ps256(_mm_loadu_ps(outptr0 + j));
|
||||
s1 = _mm256_castps128_ps256(_mm_loadu_ps(outptr1 + j));
|
||||
s2 = _mm256_castps128_ps256(_mm_loadu_ps(outptr2 + j));
|
||||
}
|
||||
|
||||
s0 = _mm256_add_ps(s0, t0);
|
||||
s1 = _mm256_add_ps(s1, t1);
|
||||
s2 = _mm256_add_ps(s2, t2);
|
||||
|
||||
if( relu )
|
||||
{
|
||||
__m256 m0 = _mm256_cmp_ps(s0, z, _CMP_GT_OS);
|
||||
__m256 m1 = _mm256_cmp_ps(s1, z, _CMP_GT_OS);
|
||||
__m256 m2 = _mm256_cmp_ps(s2, z, _CMP_GT_OS);
|
||||
s0 = _mm256_xor_ps(s0, _mm256_andnot_ps(m0, _mm256_xor_ps(_mm256_mul_ps(s0, vr0), s0)));
|
||||
s1 = _mm256_xor_ps(s1, _mm256_andnot_ps(m1, _mm256_xor_ps(_mm256_mul_ps(s1, vr1), s1)));
|
||||
s2 = _mm256_xor_ps(s2, _mm256_andnot_ps(m2, _mm256_xor_ps(_mm256_mul_ps(s2, vr2), s2)));
|
||||
}
|
||||
|
||||
_mm_storeu_ps(outptr0 + j, _mm256_castps256_ps128(s0));
|
||||
_mm_storeu_ps(outptr1 + j, _mm256_castps256_ps128(s1));
|
||||
_mm_storeu_ps(outptr2 + j, _mm256_castps256_ps128(s2));
|
||||
}
|
||||
|
||||
for( ; j < blockSize; j++ )
|
||||
{
|
||||
const float* rptr = rowbuf + j*vecsize_aligned;
|
||||
float s00, s10, s20;
|
||||
|
||||
if( initOutput )
|
||||
{
|
||||
s00 = bias0;
|
||||
s10 = bias1;
|
||||
s20 = bias2;
|
||||
}
|
||||
else
|
||||
{
|
||||
s00 = outptr0[j];
|
||||
s10 = outptr1[j];
|
||||
s20 = outptr2[j];
|
||||
}
|
||||
|
||||
for( int k = 0; k < vecsize; k++ )
|
||||
{
|
||||
float r0 = rptr[k];
|
||||
s00 += wptr0[k]*r0;
|
||||
s10 += wptr1[k]*r0;
|
||||
s20 += wptr2[k]*r0;
|
||||
}
|
||||
|
||||
if( relu )
|
||||
{
|
||||
s00 = s00 > 0.f ? s00 : s00*r0;
|
||||
s10 = s10 > 0.f ? s10 : s10*r1;
|
||||
s20 = s20 > 0.f ? s20 : s20*r2;
|
||||
}
|
||||
|
||||
outptr0[j] = s00;
|
||||
outptr1[j] = s10;
|
||||
outptr2[j] = s20;
|
||||
}
|
||||
}
|
||||
_mm256_zeroupper();
|
||||
}
|
||||
|
||||
// dst = vec * weights^t + bias
|
||||
void fastGEMM1T_avx2( const float* vec, const float* weights,
|
||||
size_t wstep, const float* bias,
|
||||
float* dst, int nvecs, int vecsize )
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for( ; i <= nvecs - 8; i += 8 )
|
||||
{
|
||||
const float* wptr = weights + i*wstep;
|
||||
__m256 vs0 = _mm256_setzero_ps(), vs1 = _mm256_setzero_ps(),
|
||||
vs2 = _mm256_setzero_ps(), vs3 = _mm256_setzero_ps(),
|
||||
vs4 = _mm256_setzero_ps(), vs5 = _mm256_setzero_ps(),
|
||||
vs6 = _mm256_setzero_ps(), vs7 = _mm256_setzero_ps();
|
||||
|
||||
for( int k = 0; k < vecsize; k += 8, wptr += 8 )
|
||||
{
|
||||
__m256 v = _mm256_load_ps(vec + k);
|
||||
|
||||
vs0 = _mm256_fmadd_ps(_mm256_load_ps(wptr), v, vs0);
|
||||
vs1 = _mm256_fmadd_ps(_mm256_load_ps(wptr + wstep), v, vs1);
|
||||
vs2 = _mm256_fmadd_ps(_mm256_load_ps(wptr + wstep*2), v, vs2);
|
||||
vs3 = _mm256_fmadd_ps(_mm256_load_ps(wptr + wstep*3), v, vs3);
|
||||
vs4 = _mm256_fmadd_ps(_mm256_load_ps(wptr + wstep*4), v, vs4);
|
||||
vs5 = _mm256_fmadd_ps(_mm256_load_ps(wptr + wstep*5), v, vs5);
|
||||
vs6 = _mm256_fmadd_ps(_mm256_load_ps(wptr + wstep*6), v, vs6);
|
||||
vs7 = _mm256_fmadd_ps(_mm256_load_ps(wptr + wstep*7), v, vs7);
|
||||
}
|
||||
|
||||
__m256 s0 = _mm256_hadd_ps(_mm256_hadd_ps(vs0, vs1), _mm256_hadd_ps(vs2, vs3));
|
||||
__m256 s1 = _mm256_hadd_ps(_mm256_hadd_ps(vs4, vs5), _mm256_hadd_ps(vs6, vs7));
|
||||
|
||||
s0 = _mm256_add_ps(s0, _mm256_permute2f128_ps(s0, s0, 1));
|
||||
s1 = _mm256_add_ps(s1, _mm256_permute2f128_ps(s1, s1, 1));
|
||||
|
||||
s0 = _mm256_add_ps(s0, _mm256_castps128_ps256(_mm_loadu_ps(bias + i)));
|
||||
s1 = _mm256_add_ps(s1, _mm256_castps128_ps256(_mm_loadu_ps(bias + i + 4)));
|
||||
|
||||
_mm_storeu_ps(dst + i, _mm256_castps256_ps128(s0));
|
||||
_mm_storeu_ps(dst + i + 4, _mm256_castps256_ps128(s1));
|
||||
}
|
||||
|
||||
float temp = 0.f;
|
||||
for( ; i < nvecs; i++ )
|
||||
{
|
||||
const float* wptr = weights + i*wstep;
|
||||
__m256 vs0 = _mm256_setzero_ps();
|
||||
|
||||
for( int k = 0; k < vecsize; k += 8, wptr += 8 )
|
||||
{
|
||||
__m256 v = _mm256_load_ps(vec + k);
|
||||
vs0 = _mm256_fmadd_ps(_mm256_load_ps(wptr), v, vs0);
|
||||
}
|
||||
|
||||
__m256 s0 = _mm256_hadd_ps(_mm256_hadd_ps(vs0, vs0), vs0);
|
||||
s0 = _mm256_add_ps(s0, _mm256_permute2f128_ps(s0, s0, 1));
|
||||
_mm_store_ss(&temp, _mm256_castps256_ps128(s0));
|
||||
dst[i] = temp + bias[i];
|
||||
}
|
||||
|
||||
_mm256_zeroupper();
|
||||
}
|
||||
|
||||
void fastGEMM_avx2( const float* aptr, size_t astep, const float* bptr,
|
||||
size_t bstep, float* cptr, size_t cstep,
|
||||
int ma, int na, int nb )
|
||||
{
|
||||
int n = 0;
|
||||
for( ; n <= nb - 16; n += 16 )
|
||||
{
|
||||
for( int m = 0; m < ma; m += 4 )
|
||||
{
|
||||
const float* aptr0 = aptr + astep*m;
|
||||
const float* aptr1 = aptr + astep*std::min(m+1, ma-1);
|
||||
const float* aptr2 = aptr + astep*std::min(m+2, ma-1);
|
||||
const float* aptr3 = aptr + astep*std::min(m+3, ma-1);
|
||||
|
||||
float* cptr0 = cptr + cstep*m;
|
||||
float* cptr1 = cptr + cstep*std::min(m+1, ma-1);
|
||||
float* cptr2 = cptr + cstep*std::min(m+2, ma-1);
|
||||
float* cptr3 = cptr + cstep*std::min(m+3, ma-1);
|
||||
|
||||
__m256 d00 = _mm256_setzero_ps(), d01 = _mm256_setzero_ps();
|
||||
__m256 d10 = _mm256_setzero_ps(), d11 = _mm256_setzero_ps();
|
||||
__m256 d20 = _mm256_setzero_ps(), d21 = _mm256_setzero_ps();
|
||||
__m256 d30 = _mm256_setzero_ps(), d31 = _mm256_setzero_ps();
|
||||
|
||||
for( int k = 0; k < na; k++ )
|
||||
{
|
||||
__m256 a0 = _mm256_set1_ps(aptr0[k]);
|
||||
__m256 a1 = _mm256_set1_ps(aptr1[k]);
|
||||
__m256 a2 = _mm256_set1_ps(aptr2[k]);
|
||||
__m256 a3 = _mm256_set1_ps(aptr3[k]);
|
||||
__m256 b0 = _mm256_loadu_ps(bptr + k*bstep + n);
|
||||
__m256 b1 = _mm256_loadu_ps(bptr + k*bstep + n + 8);
|
||||
d00 = _mm256_fmadd_ps(a0, b0, d00);
|
||||
d01 = _mm256_fmadd_ps(a0, b1, d01);
|
||||
d10 = _mm256_fmadd_ps(a1, b0, d10);
|
||||
d11 = _mm256_fmadd_ps(a1, b1, d11);
|
||||
d20 = _mm256_fmadd_ps(a2, b0, d20);
|
||||
d21 = _mm256_fmadd_ps(a2, b1, d21);
|
||||
d30 = _mm256_fmadd_ps(a3, b0, d30);
|
||||
d31 = _mm256_fmadd_ps(a3, b1, d31);
|
||||
}
|
||||
|
||||
_mm256_storeu_ps(cptr0 + n, d00);
|
||||
_mm256_storeu_ps(cptr0 + n + 8, d01);
|
||||
_mm256_storeu_ps(cptr1 + n, d10);
|
||||
_mm256_storeu_ps(cptr1 + n + 8, d11);
|
||||
_mm256_storeu_ps(cptr2 + n, d20);
|
||||
_mm256_storeu_ps(cptr2 + n + 8, d21);
|
||||
_mm256_storeu_ps(cptr3 + n, d30);
|
||||
_mm256_storeu_ps(cptr3 + n + 8, d31);
|
||||
}
|
||||
}
|
||||
_mm256_zeroupper();
|
||||
|
||||
for( ; n < nb; n++ )
|
||||
{
|
||||
for( int m = 0; m < ma; m++ )
|
||||
{
|
||||
const float* aptr0 = aptr + astep*m;
|
||||
float* cptr0 = cptr + cstep*m;
|
||||
float d0 = 0.f;
|
||||
|
||||
for( int k = 0; k < na; k++ )
|
||||
d0 += aptr0[k]*bptr[k*bstep + n];
|
||||
|
||||
cptr0[n] = d0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
205
modules/dnn/src/layers/layers_common.cpp
Normal file
205
modules/dnn/src/layers/layers_common.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "layers_common.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
namespace util
|
||||
{
|
||||
|
||||
std::string makeName(const std::string& str1, const std::string& str2)
|
||||
{
|
||||
return str1 + str2;
|
||||
}
|
||||
|
||||
bool getParameter(const LayerParams ¶ms, const std::string& nameBase, const std::string& nameAll,
|
||||
int ¶meterH, int ¶meterW, bool hasDefault = false, const int& defaultValue = 0)
|
||||
{
|
||||
std::string nameH = makeName(nameBase, std::string("_h"));
|
||||
std::string nameW = makeName(nameBase, std::string("_w"));
|
||||
std::string nameAll_ = nameAll;
|
||||
if(nameAll_ == "")
|
||||
{
|
||||
nameAll_ = nameBase;
|
||||
}
|
||||
|
||||
if (params.has(nameH) && params.has(nameW))
|
||||
{
|
||||
parameterH = params.get<int>(nameH);
|
||||
parameterW = params.get<int>(nameW);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (params.has(nameAll_))
|
||||
{
|
||||
parameterH = parameterW = params.get<int>(nameAll_);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(hasDefault)
|
||||
{
|
||||
parameterH = parameterW = defaultValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getKernelSize(const LayerParams ¶ms, int &kernelH, int &kernelW)
|
||||
{
|
||||
if(!util::getParameter(params, "kernel", "kernel_size", kernelH, kernelW))
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, "kernel_size (or kernel_h and kernel_w) not specified");
|
||||
}
|
||||
|
||||
CV_Assert(kernelH > 0 && kernelW > 0);
|
||||
}
|
||||
|
||||
void getStrideAndPadding(const LayerParams ¶ms, int &padH, int &padW, int &strideH, int &strideW, cv::String& padMode)
|
||||
{
|
||||
util::getParameter(params, "pad", "pad", padH, padW, true, 0);
|
||||
util::getParameter(params, "stride", "stride", strideH, strideW, true, 1);
|
||||
|
||||
padMode = "";
|
||||
if (params.has("pad_mode"))
|
||||
{
|
||||
padMode = params.get<String>("pad_mode");
|
||||
}
|
||||
|
||||
CV_Assert(padH >= 0 && padW >= 0 && strideH > 0 && strideW > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void getPoolingKernelParams(const LayerParams ¶ms, int &kernelH, int &kernelW, bool &globalPooling,
|
||||
int &padH, int &padW, int &strideH, int &strideW, cv::String &padMode)
|
||||
{
|
||||
util::getStrideAndPadding(params, padH, padW, strideH, strideW, padMode);
|
||||
|
||||
globalPooling = params.has("global_pooling");
|
||||
|
||||
if (globalPooling)
|
||||
{
|
||||
if(params.has("kernel_h") || params.has("kernel_w") || params.has("kernel_size"))
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, "In global_pooling mode, kernel_size (or kernel_h and kernel_w) cannot be specified");
|
||||
}
|
||||
if(padH != 0 || padW != 0 || strideH != 1 || strideW != 1)
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, "In global_pooling mode, pad_h and pad_w must be = 0, and stride_h and stride_w must be = 1");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
util::getKernelSize(params, kernelH, kernelW);
|
||||
}
|
||||
}
|
||||
|
||||
void getConvolutionKernelParams(const LayerParams ¶ms, int &kernelH, int &kernelW, int &padH, int &padW,
|
||||
int &strideH, int &strideW, int &dilationH, int &dilationW, cv::String &padMode)
|
||||
{
|
||||
util::getKernelSize(params, kernelH, kernelW);
|
||||
util::getStrideAndPadding(params, padH, padW, strideH, strideW, padMode);
|
||||
|
||||
util::getParameter(params, "dilation", "dilation", dilationH, dilationW, true, 1);
|
||||
|
||||
CV_Assert(dilationH > 0 && dilationW > 0);
|
||||
}
|
||||
|
||||
// From TensorFlow code:
|
||||
// Total padding on rows and cols is
|
||||
// Pr = (R' - 1) * S + Kr - R
|
||||
// Pc = (C' - 1) * S + Kc - C
|
||||
// where (R', C') are output dimensions, (R, C) are input dimensions, S
|
||||
// is stride, (Kr, Kc) are filter dimensions.
|
||||
// We pad Pr/2 on the left and Pr - Pr/2 on the right, Pc/2 on the top
|
||||
// and Pc - Pc/2 on the bottom. When Pr or Pc is odd, this means
|
||||
// we pad more on the right and bottom than on the top and left.
|
||||
void getConvPoolOutParams(const Size& inp, const Size &kernel,
|
||||
const Size &stride, const String &padMode,
|
||||
Size& out)
|
||||
{
|
||||
if (padMode == "VALID")
|
||||
{
|
||||
out.height = (inp.height - kernel.height + stride.height) / stride.height;
|
||||
out.width = (inp.width- kernel.width + stride.width) / stride.width;
|
||||
}
|
||||
else if (padMode == "SAME")
|
||||
{
|
||||
out.height = (inp.height - 1 + stride.height) / stride.height;
|
||||
out.width = (inp.width - 1 + stride.width) / stride.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Error(Error::StsError, "Unsupported padding mode");
|
||||
}
|
||||
}
|
||||
|
||||
void getConvPoolPaddings(const Size& inp, const Size& out,
|
||||
const Size &kernel, const Size &stride,
|
||||
const String &padMode, Size &pad)
|
||||
{
|
||||
if (padMode == "VALID")
|
||||
{
|
||||
pad = cv::Size(0,0);
|
||||
}
|
||||
else if (padMode == "SAME")
|
||||
{
|
||||
int Ph = std::max(0, (out.height - 1) * stride.height + kernel.height - inp.height);
|
||||
int Pw = std::max(0, (out.width - 1) * stride.width + kernel.width - inp.width);
|
||||
// For odd values of total padding, add more padding at the 'right'
|
||||
// side of the given dimension.
|
||||
pad = cv::Size(Pw / 2, Ph / 2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
87
modules/dnn/src/layers/layers_common.hpp
Normal file
87
modules/dnn/src/layers/layers_common.hpp
Normal file
@ -0,0 +1,87 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_DNN_LAYERS_LAYERS_COMMON_HPP__
|
||||
#define __OPENCV_DNN_LAYERS_LAYERS_COMMON_HPP__
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
void getConvolutionKernelParams(const LayerParams ¶ms, int &kernelH, int &kernelW, int &padH, int &padW,
|
||||
int &strideH, int &strideW, int &dilationH, int &dilationW, cv::String& padMode);
|
||||
|
||||
void getPoolingKernelParams(const LayerParams ¶ms, int &kernelH, int &kernelW, bool &globalPooling,
|
||||
int &padH, int &padW, int &strideH, int &strideW, cv::String& padMode);
|
||||
|
||||
void getConvPoolOutParams(const Size& inp, const Size &kernel,
|
||||
const Size &stride, const String &padMode,
|
||||
Size& out);
|
||||
|
||||
void getConvPoolPaddings(const Size& inp, const Size& out,
|
||||
const Size &kernel, const Size &stride,
|
||||
const String &padMode, Size &pad);
|
||||
|
||||
#if CV_SSE2
|
||||
#define CV_DNN_TRY_AVX2 1
|
||||
|
||||
void fastConv_avx2(const float* weights, size_t wstep, const float* bias,
|
||||
const float* rowbuf, float* output, const int* outShape,
|
||||
int blockSize, int vecsize, int vecsize_aligned,
|
||||
const float* relu, bool initOutput);
|
||||
void fastGEMM1T_avx2( const float* vec, const float* weights,
|
||||
size_t wstep, const float* bias,
|
||||
float* dst, int nvecs, int vecsize );
|
||||
void fastGEMM_avx2( const float* aptr, size_t astep, const float* bptr0,
|
||||
size_t bstep, float* cptr, size_t cstep,
|
||||
int ma, int na, int nb );
|
||||
|
||||
#else
|
||||
#define CV_DNN_TRY_AVX2 0
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
341
modules/dnn/src/layers/lrn_layer.cpp
Normal file
341
modules/dnn/src/layers/lrn_layer.cpp
Normal file
@ -0,0 +1,341 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/dnn/shape_utils.hpp"
|
||||
#include "opencv2/core/hal/hal.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class LRNLayerImpl : public LRNLayer
|
||||
{
|
||||
public:
|
||||
LRNLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
type = -1;
|
||||
String nrmType = params.get<String>("norm_region", "ACROSS_CHANNELS");
|
||||
if (nrmType == "ACROSS_CHANNELS")
|
||||
type = LRNLayer::CHANNEL_NRM;
|
||||
else if (nrmType == "WITHIN_CHANNEL")
|
||||
type = LRNLayer::SPATIAL_NRM;
|
||||
else
|
||||
CV_Error(Error::StsBadArg, "Unknown region type \"" + nrmType + "\"");
|
||||
|
||||
size = params.get<int>("local_size", 5);
|
||||
if (size % 2 != 1 || size <= 0)
|
||||
CV_Error(Error::StsBadArg, "LRN layer supports only positive odd values for local_size");
|
||||
|
||||
alpha = params.get<double>("alpha", 1);
|
||||
beta = params.get<double>("beta", 0.75);
|
||||
bias = params.get<double>("bias", 1);
|
||||
normBySize = params.get<bool>("norm_by_size", true);
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide();
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
CV_Assert(inputs.size() == outputs.size());
|
||||
for (int i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
CV_Assert(inputs[i]->dims == 4);
|
||||
|
||||
Mat &src = *inputs[i];
|
||||
Mat &dst = outputs[i];
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CHANNEL_NRM:
|
||||
channelNormalization(src, dst);
|
||||
break;
|
||||
case SPATIAL_NRM:
|
||||
spatialNormalization(src, dst);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsNotImplemented, "Unimplemented mode of LRN layer");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ChannelLRN : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
ChannelLRN(const float* src, float* dst, int channels, int ksize,
|
||||
float alpha1, float bias1, float beta1,
|
||||
size_t planeSize, int nsamples, int nstripes)
|
||||
{
|
||||
src_ = src; dst_ = dst;
|
||||
channels_ = channels;
|
||||
ksize_ = ksize;
|
||||
alpha1_ = alpha1; bias1_ = bias1; beta1_ = beta1;
|
||||
planeSize_ = planeSize; nsamples_ = nsamples; nstripes_ = nstripes;
|
||||
}
|
||||
|
||||
void operator()(const Range& r) const
|
||||
{
|
||||
int nsamples = nsamples_, nstripes = nstripes_;
|
||||
size_t planeSize = planeSize_, planeSize_n = planeSize * nsamples;
|
||||
size_t elemsPerStripe = (planeSize_n + nstripes - 1)/nstripes;
|
||||
size_t rstart = r.start*elemsPerStripe;
|
||||
size_t rend = r.end == nstripes ? planeSize_n : r.end*elemsPerStripe;
|
||||
rstart = std::min(rstart, planeSize_n);
|
||||
rend = std::min(rend, planeSize_n);
|
||||
float alpha1 = alpha1_, bias1 = bias1_, beta1 = beta1_;
|
||||
int k, channels = channels_, ksize = ksize_;
|
||||
|
||||
AutoBuffer<float> buf_((channels + ksize*2 + 4)*2);
|
||||
float* acc = (float*)buf_;
|
||||
float* buf = acc + channels + ksize + 1;
|
||||
for( k = 0; k <= ksize; k++ )
|
||||
buf[-k-1] = buf[channels + k] = 0.f;
|
||||
|
||||
for( size_t ofs = rstart; ofs < rend; )
|
||||
{
|
||||
int sampleIdx = (int)(ofs/planeSize);
|
||||
if( sampleIdx >= nsamples )
|
||||
break;
|
||||
size_t ofs0 = ofs - sampleIdx*planeSize;
|
||||
size_t ofs1 = std::min(planeSize - ofs0, rend - ofs) + ofs;
|
||||
const float* src = src_ + sampleIdx*planeSize*channels + ofs0;
|
||||
float* dst = dst_ + sampleIdx*planeSize*channels + ofs0;
|
||||
|
||||
for( ; ofs < ofs1; ofs++, src++, dst++ )
|
||||
{
|
||||
for( k = 0; k < channels; k++ )
|
||||
buf[k] = src[k*planeSize];
|
||||
float s = 0;
|
||||
for( k = 0; k < ksize; k++ )
|
||||
s += buf[k]*buf[k];
|
||||
for( k = 0; k < channels; k++ )
|
||||
{
|
||||
float x1 = buf[k + ksize];
|
||||
float x0 = buf[k - ksize - 1];
|
||||
s = std::max(s + (x1 + x0)*(x1 - x0), 0.f);
|
||||
acc[k] = (float)(alpha1*s + bias1);
|
||||
}
|
||||
|
||||
hal::log32f(acc, acc, channels);
|
||||
for( k = 0; k < channels; k++ )
|
||||
acc[k] *= beta1;
|
||||
hal::exp32f(acc, acc, channels);
|
||||
|
||||
for( k = 0; k < channels; k++ )
|
||||
dst[k*planeSize] = buf[k]*acc[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const float* src_;
|
||||
float* dst_;
|
||||
float alpha1_, bias1_, beta1_;
|
||||
size_t planeSize_;
|
||||
int channels_, ksize_, nsamples_, nstripes_;
|
||||
};
|
||||
|
||||
void channelNormalization(Mat &srcBlob, Mat &dstBlob)
|
||||
{
|
||||
int num = srcBlob.size[0];
|
||||
int channels = srcBlob.size[1];
|
||||
int ksize = (size - 1) / 2;
|
||||
int sizeNormFactor = normBySize ? size : 1;
|
||||
size_t planeSize = srcBlob.size[2]*srcBlob.size[3];
|
||||
|
||||
int nstripes = std::max(getNumThreads(), 1);
|
||||
|
||||
ChannelLRN clrn(srcBlob.ptr<float>(), dstBlob.ptr<float>(), channels,
|
||||
ksize, alpha/sizeNormFactor, bias, -beta, planeSize, num, nstripes);
|
||||
parallel_for_(Range(0, nstripes), clrn, nstripes);
|
||||
}
|
||||
|
||||
void sqrBoxFilter_(const Mat &src, Mat &dst)
|
||||
{
|
||||
Mat srcRawWrapper(src.rows, src.cols, src.type(), src.data, src.step[0]);
|
||||
cv::sqrBoxFilter(srcRawWrapper, dst, dst.depth(), Size(size, size), Point(-1, -1), false, BORDER_CONSTANT);
|
||||
}
|
||||
|
||||
void spatialNormalization(Mat &srcBlob, Mat &dstBlob)
|
||||
{
|
||||
int num = srcBlob.size[0];
|
||||
int channels = srcBlob.size[1];
|
||||
int sizeNormFactor = normBySize ? size*size : 1;
|
||||
|
||||
Mat srcMat = srcBlob;
|
||||
Mat dstMat = dstBlob;
|
||||
|
||||
for (int n = 0; n < num; n++)
|
||||
{
|
||||
for (int cn = 0; cn < channels; cn++)
|
||||
{
|
||||
Mat src = getPlane(srcMat, n, cn);
|
||||
Mat dst = getPlane(dstMat, n, cn);
|
||||
|
||||
sqrBoxFilter_(src, dst);
|
||||
|
||||
dst.convertTo(dst, dst.type(), alpha/sizeNormFactor, bias);
|
||||
cv::pow(dst, beta, dst);
|
||||
cv::divide(src, dst, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
float alphaSize = alpha;
|
||||
if (normBySize)
|
||||
alphaSize /= (type == CHANNEL_NRM ? size : size * size);
|
||||
int width, height, channels, numImgs;
|
||||
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
|
||||
getCanonicalSize(inputBuffer, &width, &height, &channels, &numImgs);
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::Func padded_sq(name + "_padded_sq");
|
||||
Halide::Func sq("sq");
|
||||
sq(x, y, c, n) = inputBuffer(x, y, c, n) * inputBuffer(x, y, c, n);
|
||||
|
||||
Halide::Func bounded =
|
||||
Halide::BoundaryConditions::constant_exterior(sq, 0, 0, width,
|
||||
0, height,
|
||||
0, channels,
|
||||
0, numImgs);
|
||||
padded_sq(x, y, c, n) = bounded(x, y, c, n);
|
||||
|
||||
Halide::Expr base;
|
||||
if (type == CHANNEL_NRM)
|
||||
{
|
||||
Halide::RDom r((1 - size) / 2, size);
|
||||
base = alphaSize * sum(padded_sq(x, y, c + r, n));
|
||||
}
|
||||
else // SPATIAL_NRM
|
||||
{
|
||||
Halide::RDom r((1 - size) / 2, size, (1 - size) / 2, size);
|
||||
base = alphaSize * sum(padded_sq(x + r.x, y + r.y, c, n));
|
||||
}
|
||||
base += static_cast<float>(bias);
|
||||
top(x, y, c, n) = inputBuffer(x, y, c, n) / pow(base, beta);
|
||||
return Ptr<BackendNode>(new HalideBackendNode({ padded_sq, top }));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
virtual void applyHalideScheduler(Ptr<BackendNode>& node,
|
||||
const std::vector<Mat*> &inputs,
|
||||
const std::vector<Mat> &outputs,
|
||||
int targetId) const
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
if (targetId != DNN_TARGET_CPU)
|
||||
{
|
||||
Layer::applyHalideScheduler(node, inputs, outputs, targetId);
|
||||
return;
|
||||
}
|
||||
int outW, outH, outC, outN;
|
||||
getCanonicalSize(outputs[0].size, &outW, &outH, &outC, &outN);
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n"), yo("yo"), yi("yi"), tile("tile");
|
||||
Halide::Func& top = node.dynamicCast<HalideBackendNode>()->funcs[1];
|
||||
Halide::Func& padded_sq = node.dynamicCast<HalideBackendNode>()->funcs[0];
|
||||
|
||||
if (outW < 8 || outH <= 2)
|
||||
return;
|
||||
|
||||
top.reorder(x, c, y, n)
|
||||
.split(y, yo, yi, 2)
|
||||
.fuse(yo, n, tile)
|
||||
.parallel(tile)
|
||||
.unroll(yi)
|
||||
.vectorize(x, 8);
|
||||
padded_sq.store_at(top, tile)
|
||||
.compute_at(top, yi);
|
||||
#endif // HAVE_HALIDE
|
||||
}
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)outputs; // suppress unused variable warning
|
||||
CV_Assert(inputs.size() > 0);
|
||||
long flops = 0;
|
||||
|
||||
for(int i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
if (type == CHANNEL_NRM)
|
||||
{
|
||||
int channels = inputs[i][1];
|
||||
int ksize = (size - 1) / 2;
|
||||
|
||||
flops += inputs[i][0]*(std::min(ksize, channels)*2*total(inputs[i], 2) + channels*4*total(inputs[i], 2));
|
||||
|
||||
if (ksize < channels)
|
||||
{
|
||||
flops += (size + 2*(channels - size))*total(inputs[i], 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flops += total(inputs[i])*(2*size*size + 2);
|
||||
}
|
||||
}
|
||||
return flops;
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<LRNLayer> LRNLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<LRNLayer>(new LRNLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
128
modules/dnn/src/layers/max_unpooling_layer.cpp
Normal file
128
modules/dnn/src/layers/max_unpooling_layer.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2016, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
/*
|
||||
Implementation of Batch Normalization layer.
|
||||
*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class MaxUnpoolLayerImpl : public MaxUnpoolLayer
|
||||
{
|
||||
public:
|
||||
MaxUnpoolLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
poolKernel = Size(params.get<int>("pool_k_w"), params.get<int>("pool_k_h"));
|
||||
poolPad = Size(params.get<int>("pool_pad_w"), params.get<int>("pool_pad_h"));
|
||||
poolStride = Size(params.get<int>("pool_stride_w"), params.get<int>("pool_stride_h"));
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide() &&
|
||||
!poolPad.width && !poolPad.height;
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() == 2);
|
||||
CV_Assert(total(inputs[0]) == total(inputs[1]));
|
||||
|
||||
MatShape outShape = inputs[0];
|
||||
outShape[2] = (outShape[2] - 1) * poolStride.height + poolKernel.height - 2 * poolPad.height;
|
||||
outShape[3] = (outShape[3] - 1) * poolStride.width + poolKernel.width - 2 * poolPad.width;
|
||||
|
||||
outputs.clear();
|
||||
outputs.push_back(outShape);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
CV_Assert(inputs.size() == 2);
|
||||
Mat& input = *inputs[0];
|
||||
Mat& indices = *inputs[1];
|
||||
|
||||
CV_Assert(input.total() == indices.total());
|
||||
CV_Assert(input.size[0] == 1);
|
||||
CV_Assert(input.isContinuous());
|
||||
|
||||
for(int i_n = 0; i_n < outputs.size(); i_n++)
|
||||
{
|
||||
Mat& outBlob = outputs[i_n];
|
||||
outBlob.setTo(0);
|
||||
CV_Assert(input.size[1] == outBlob.size[1]);
|
||||
int outPlaneTotal = outBlob.size[2]*outBlob.size[3];
|
||||
|
||||
for (int i_c = 0; i_c < input.size[1]; i_c++)
|
||||
{
|
||||
Mat outPlane = getPlane(outBlob, 0, i_c);
|
||||
int wh_area = input.size[2]*input.size[3];
|
||||
const float* inptr = input.ptr<float>(0, i_c);
|
||||
const float* idxptr = indices.ptr<float>(0, i_c);
|
||||
float* outptr = outPlane.ptr<float>();
|
||||
|
||||
for(int i_wh = 0; i_wh < wh_area; i_wh++)
|
||||
{
|
||||
int index = idxptr[i_wh];
|
||||
CV_Assert(0 <= index && index < outPlaneTotal);
|
||||
outptr[index] = inptr[i_wh];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &input)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
// Meaningless operation if false because if kernel > stride
|
||||
// it is not deterministic and if kernel < stride we just
|
||||
// skip a part of input data (you'd better change your model).
|
||||
if (poolKernel.width != poolStride.width ||
|
||||
poolKernel.height != poolStride.height)
|
||||
CV_Error(cv::Error::StsNotImplemented,
|
||||
"Halide backend for maximum unpooling "
|
||||
"is not support cases when kernel != stride");
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::Buffer<float> inputBuffer = halideBuffer(input[0]);
|
||||
Halide::Buffer<float> indices = halideBuffer(input[1]);
|
||||
|
||||
Halide::Expr pooledX = x / poolKernel.width;
|
||||
Halide::Expr pooledY = y / poolKernel.height;
|
||||
|
||||
const int outW = inputBuffer.width() * poolKernel.width;
|
||||
top(x, y, c, n) = select(y * outW + x == indices(pooledX, pooledY, c, n),
|
||||
inputBuffer(pooledX, pooledY, c, n), 0.0f);
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<MaxUnpoolLayer> MaxUnpoolLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<MaxUnpoolLayer>(new MaxUnpoolLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
108
modules/dnn/src/layers/mvn_layer.cpp
Normal file
108
modules/dnn/src/layers/mvn_layer.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class MVNLayerImpl : public MVNLayer
|
||||
{
|
||||
public:
|
||||
MVNLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
normVariance = params.get<bool>("normalize_variance", true);
|
||||
acrossChannels = params.get<bool>("across_channels", false);
|
||||
eps = params.get<double>("eps", 1e-9);
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat *> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
for (size_t inpIdx = 0; inpIdx < inputs.size(); inpIdx++)
|
||||
{
|
||||
Mat &inpBlob = *inputs[inpIdx];
|
||||
Mat &outBlob = outputs[inpIdx];
|
||||
|
||||
int splitDim = (acrossChannels) ? 1 : 2;
|
||||
int i, newRows = 1;
|
||||
for( i = 0; i < splitDim; i++ )
|
||||
newRows *= inpBlob.size[i];
|
||||
Mat inpMat = inpBlob.reshape(1, newRows);
|
||||
Mat outMat = outBlob.reshape(1, newRows);
|
||||
|
||||
Scalar mean, dev;
|
||||
for ( i = 0; i < newRows; i++)
|
||||
{
|
||||
Mat inpRow = inpMat.row(i);
|
||||
Mat outRow = outMat.row(i);
|
||||
|
||||
cv::meanStdDev(inpRow, mean, (normVariance) ? dev : noArray());
|
||||
double alpha = (normVariance) ? 1/(eps + dev[0]) : 1;
|
||||
inpRow.convertTo(outRow, outRow.type(), alpha, -mean[0] * alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)outputs; // suppress unused variable warning
|
||||
long flops = 0;
|
||||
for(int i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
flops += 6*total(inputs[i]) + 3*total(inputs[i], 0, normVariance ? 2 : 1);
|
||||
}
|
||||
return flops;
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<MVNLayer> MVNLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<MVNLayer>(new MVNLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
223
modules/dnn/src/layers/normalize_bbox_layer.cpp
Normal file
223
modules/dnn/src/layers/normalize_bbox_layer.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
|
||||
#include <float.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
const std::string layerName = "NormalizeBBox";
|
||||
}
|
||||
|
||||
class NormalizeBBoxLayerImpl : public NormalizeBBoxLayer
|
||||
{
|
||||
float _eps;
|
||||
bool _across_spatial;
|
||||
bool _channel_shared;
|
||||
public:
|
||||
bool getParameterDict(const LayerParams ¶ms,
|
||||
const std::string ¶meterName,
|
||||
DictValue& result)
|
||||
{
|
||||
if (!params.has(parameterName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result = params.get(parameterName);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T getParameter(const LayerParams ¶ms,
|
||||
const std::string ¶meterName,
|
||||
const size_t &idx=0,
|
||||
const bool required=true,
|
||||
const T& defaultValue=T())
|
||||
{
|
||||
DictValue dictValue;
|
||||
bool success = getParameterDict(params, parameterName, dictValue);
|
||||
if(!success)
|
||||
{
|
||||
if(required)
|
||||
{
|
||||
std::string message = layerName;
|
||||
message += " layer parameter does not contain ";
|
||||
message += parameterName;
|
||||
message += " parameter.";
|
||||
CV_Error(Error::StsBadArg, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return dictValue.get<T>(idx);
|
||||
}
|
||||
|
||||
NormalizeBBoxLayerImpl(const LayerParams ¶ms)
|
||||
{
|
||||
_eps = getParameter<float>(params, "eps", 0, false, 1e-10f);
|
||||
_across_spatial = getParameter<bool>(params, "across_spatial");
|
||||
_channel_shared = getParameter<bool>(params, "channel_shared");
|
||||
setParamsFrom(params);
|
||||
}
|
||||
|
||||
void checkInputs(const std::vector<Mat*> &inputs)
|
||||
{
|
||||
CV_Assert(inputs.size() > 0);
|
||||
CV_Assert(inputs[0]->dims == 4 && inputs[0]->type() == CV_32F);
|
||||
for (size_t i = 1; i < inputs.size(); i++)
|
||||
{
|
||||
CV_Assert(inputs[i]->dims == 4 && inputs[i]->type() == CV_32F);
|
||||
CV_Assert(inputs[i]->size == inputs[0]->size);
|
||||
}
|
||||
CV_Assert(inputs[0]->dims > 2);
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
bool inplace = Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
|
||||
size_t channels = inputs[0][1];
|
||||
size_t rows = inputs[0][2];
|
||||
size_t cols = inputs[0][3];
|
||||
size_t channelSize = rows * cols;
|
||||
|
||||
internals.assign(1, shape(channels, channelSize));
|
||||
internals.push_back(shape(channels, 1));
|
||||
internals.push_back(shape(1, channelSize));
|
||||
|
||||
return inplace;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
checkInputs(inputs);
|
||||
|
||||
Mat& buffer = internals[0], sumChannelMultiplier = internals[1],
|
||||
sumSpatialMultiplier = internals[2];
|
||||
|
||||
sumChannelMultiplier.setTo(1.0);
|
||||
sumSpatialMultiplier.setTo(1.0);
|
||||
|
||||
const Mat& inp0 = *inputs[0];
|
||||
size_t num = inp0.size[0];
|
||||
size_t channels = inp0.size[1];
|
||||
size_t channelSize = inp0.size[2] * inp0.size[3];
|
||||
|
||||
Mat zeroBuffer(channels, channelSize, CV_32F, Scalar(0));
|
||||
Mat absDiff;
|
||||
Mat scale = blobs[0];
|
||||
for (size_t j = 0; j < inputs.size(); j++)
|
||||
{
|
||||
for (size_t n = 0; n < num; ++n)
|
||||
{
|
||||
Mat src = Mat(channels, channelSize, CV_32F, inputs[j]->ptr<float>(n));
|
||||
Mat dst = Mat(channels, channelSize, CV_32F, outputs[j].ptr<float>(n));
|
||||
|
||||
buffer = src.mul(src);
|
||||
|
||||
if (_across_spatial)
|
||||
{
|
||||
absdiff(buffer, zeroBuffer, absDiff);
|
||||
|
||||
// add eps to avoid overflow
|
||||
double absSum = sum(absDiff)[0] + _eps;
|
||||
|
||||
float norm = sqrt(absSum);
|
||||
dst = src / norm;
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat norm(channelSize, 1, buffer.type()); // 1 x channelSize
|
||||
|
||||
// (_channels x channelSize)T * _channels x 1 -> channelSize x 1
|
||||
gemm(buffer, sumChannelMultiplier, 1, norm, 0, norm, GEMM_1_T);
|
||||
|
||||
// compute norm
|
||||
pow(norm, 0.5f, norm);
|
||||
|
||||
// scale the layer
|
||||
// _channels x 1 * (channelSize x 1)T -> _channels x channelSize
|
||||
gemm(sumChannelMultiplier, norm, 1, buffer, 0, buffer, GEMM_2_T);
|
||||
|
||||
dst = src / buffer;
|
||||
}
|
||||
|
||||
// scale the output
|
||||
if (_channel_shared)
|
||||
{
|
||||
// _scale: 1 x 1
|
||||
dst *= scale.at<float>(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// _scale: _channels x 1
|
||||
// _channels x 1 * 1 x channelSize -> _channels x channelSize
|
||||
gemm(scale, sumSpatialMultiplier, 1, buffer, 0, buffer);
|
||||
|
||||
dst = dst.mul(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
Ptr<NormalizeBBoxLayer> NormalizeBBoxLayer::create(const LayerParams ¶ms)
|
||||
{
|
||||
return Ptr<NormalizeBBoxLayer>(new NormalizeBBoxLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
131
modules/dnn/src/layers/padding_layer.cpp
Normal file
131
modules/dnn/src/layers/padding_layer.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2016, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
/*
|
||||
Implementation of padding layer, which adds paddings to input blob.
|
||||
*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class PaddingLayerImpl : public PaddingLayer
|
||||
{
|
||||
public:
|
||||
PaddingLayerImpl(const LayerParams ¶ms)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
paddingDim = params.get<int>("padding_dim");
|
||||
padding = abs(params.get<int>("padding"));
|
||||
inputDims = params.get<int>("input_dims", 0);
|
||||
index = params.get<int>("index", 0);
|
||||
paddingValue = params.get<double>("value", 0);
|
||||
|
||||
if(paddingDim < 0 || padding < 0)
|
||||
CV_Error(cv::Error::StsNotImplemented, "Negative padding and dim aren't supported");
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
outputs.clear();
|
||||
for(int i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
MatShape shape = inputs[i];
|
||||
int dim = getPadDim(shape);
|
||||
CV_Assert(dim < shape.size());
|
||||
|
||||
shape[dim] += padding;
|
||||
outputs.push_back(shape);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide();
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
for(int i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
outputs[i] = paddingValue;
|
||||
const Mat& inp = *inputs[i];
|
||||
Mat& out = outputs[i];
|
||||
int dims = inp.dims;
|
||||
MatShape inShape(inp.size.p, inp.size.p + dims);
|
||||
MatShape outShape(out.size.p, out.size.p + dims);
|
||||
int dim = getPadDim(inShape);
|
||||
|
||||
int actualIndex = index;
|
||||
if(index == 0)
|
||||
actualIndex = inShape[dim];
|
||||
|
||||
std::vector<std::pair<Range, Range> > srcDstRanges;
|
||||
srcDstRanges.push_back(std::make_pair(Range(0, actualIndex), Range(0, actualIndex)));
|
||||
srcDstRanges.push_back(std::make_pair(Range(actualIndex, inShape[dim]),
|
||||
Range(actualIndex + padding, outShape[dim])));
|
||||
|
||||
std::vector<Range> srcRanges(dims, Range::all()), dstRanges = srcRanges;
|
||||
|
||||
for(int j = 0; j < srcDstRanges.size(); j++)
|
||||
{
|
||||
if(!srcDstRanges[j].first.empty())
|
||||
{
|
||||
srcRanges[dim] = srcDstRanges[j].first;
|
||||
dstRanges[dim] = srcDstRanges[j].second;
|
||||
Mat dst = out(&dstRanges[0]);
|
||||
Mat src = inp(&srcRanges[0]).clone();
|
||||
src.copyTo(dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int getPadDim(const MatShape& shape) const
|
||||
{
|
||||
return inputDims > 0 && (int)shape.size() > inputDims ? paddingDim + 1 : paddingDim;
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
int inW, inH, inC, inN;
|
||||
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
|
||||
getCanonicalSize(inputBuffer, &inW, &inH, &inC, &inN);
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::Func padded =
|
||||
Halide::BoundaryConditions::constant_exterior(inputBuffer, paddingValue);
|
||||
top(x, y, c, n) = padded(x, y, c, n);
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
int paddingDim, padding, inputDims, index;
|
||||
float paddingValue;
|
||||
};
|
||||
|
||||
Ptr<PaddingLayer> PaddingLayer::create(const LayerParams ¶ms)
|
||||
{
|
||||
return Ptr<PaddingLayer>(new PaddingLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
243
modules/dnn/src/layers/permute_layer.cpp
Normal file
243
modules/dnn/src/layers/permute_layer.cpp
Normal file
@ -0,0 +1,243 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include <float.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
class PermuteLayerImpl : public PermuteLayer
|
||||
{
|
||||
public:
|
||||
void checkCurrentOrder(int currentOrder)
|
||||
{
|
||||
if(currentOrder < 0 || currentOrder > 3)
|
||||
{
|
||||
CV_Error(
|
||||
Error::StsBadArg,
|
||||
"Orders of dimensions in Permute layer parameter"
|
||||
"must be in [0...3] interval");
|
||||
}
|
||||
|
||||
if(std::find(_order.begin(), _order.end(), currentOrder) != _order.end())
|
||||
{
|
||||
CV_Error(Error::StsBadArg,
|
||||
"Permute layer parameter contains duplicated orders.");
|
||||
}
|
||||
}
|
||||
|
||||
void checkNeedForPermutation()
|
||||
{
|
||||
_needsPermute = false;
|
||||
for (size_t i = 0; i < _numAxes; ++i)
|
||||
{
|
||||
if (_order[i] != i)
|
||||
{
|
||||
_needsPermute = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PermuteLayerImpl(const LayerParams ¶ms)
|
||||
{
|
||||
if (!params.has("order"))
|
||||
{
|
||||
_needsPermute = false;
|
||||
return;
|
||||
}
|
||||
|
||||
DictValue paramOrder = params.get("order");
|
||||
if(paramOrder.size() > 4)
|
||||
{
|
||||
CV_Error(
|
||||
Error::StsBadArg,
|
||||
"Too many (> 4) orders of dimensions in Permute layer");
|
||||
}
|
||||
|
||||
_numAxes = paramOrder.size();
|
||||
|
||||
for (size_t i = 0; i < _numAxes; i++)
|
||||
{
|
||||
int currentOrder = paramOrder.get<int>(i);
|
||||
checkCurrentOrder(currentOrder);
|
||||
_order.push_back(currentOrder);
|
||||
}
|
||||
|
||||
setParamsFrom(params);
|
||||
checkNeedForPermutation();
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
if(!_needsPermute)
|
||||
return true;
|
||||
|
||||
CV_Assert(inputs.size() > 0);
|
||||
CV_Assert((int)_numAxes == inputs[0].size());
|
||||
|
||||
MatShape shapeBefore = inputs[0], shapeAfter;
|
||||
for (size_t i = 0; i < _numAxes; i++)
|
||||
{
|
||||
shapeAfter.push_back(shapeBefore[_order[i]]);
|
||||
}
|
||||
|
||||
outputs.clear();
|
||||
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
CV_Assert(inputs[i][2] == shapeBefore[2] && inputs[i][3] == shapeBefore[3]);
|
||||
CV_Assert(total(inputs[i]) == total(shapeAfter));
|
||||
outputs.push_back(shapeAfter);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void computeStrides(const MatShape &shapeBefore, const MatShape &shapeAfter)
|
||||
{
|
||||
_oldStride.resize(_numAxes);
|
||||
_newStride.resize(_numAxes);
|
||||
|
||||
_oldStride[_numAxes - 1] = 1;
|
||||
_newStride[_numAxes - 1] = 1;
|
||||
|
||||
for(int i = _numAxes - 2; i >= 0; i--)
|
||||
{
|
||||
_oldStride[i] = _oldStride[i + 1] * shapeBefore[i + 1];
|
||||
_newStride[i] = _newStride[i + 1] * shapeAfter[i + 1];
|
||||
}
|
||||
|
||||
_count = _oldStride[0] * shapeBefore[0];
|
||||
}
|
||||
|
||||
void finalize(const std::vector<Mat*> &inputs, std::vector<Mat> &outputs)
|
||||
{
|
||||
if(!_needsPermute)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CV_Assert(inputs.size() > 0);
|
||||
const Mat& inp0 = *inputs[0];
|
||||
CV_Assert((int)_numAxes == inp0.dims);
|
||||
|
||||
computeStrides(shape(*inputs[0]), shape(outputs[0]));
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
size_t k, ninputs = inputs.size();
|
||||
if(!_needsPermute)
|
||||
{
|
||||
for (k = 0; k < ninputs; k++)
|
||||
outputs[k] = *inputs[k];
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i, j, count = _count, numAxes = _numAxes;
|
||||
const size_t* newStride = &_newStride[0];
|
||||
const size_t* oldStride = &_oldStride[0];
|
||||
const size_t* order = &_order[0];
|
||||
|
||||
for (k = 0; k < ninputs; k++)
|
||||
{
|
||||
const Mat& inp = *inputs[k];
|
||||
Mat& out = outputs[k];
|
||||
|
||||
CV_Assert(inp.dims == numAxes && inp.size == inputs[0]->size);
|
||||
CV_Assert(out.dims == numAxes && out.size == outputs[0].size);
|
||||
|
||||
// for( i = 0; i < numAxes; i++ )
|
||||
// {
|
||||
// CV_Assert(inp.size[i] == _oldDimensionSize[i]);
|
||||
// CV_Assert(out.size[i] == _newDimensionSize[i]);
|
||||
// }
|
||||
|
||||
CV_Assert(inp.isContinuous() && out.isContinuous());
|
||||
CV_Assert(inp.type() == CV_32F && out.type() == CV_32F);
|
||||
|
||||
const float *srcData = inp.ptr<float>();
|
||||
float *dstData = out.ptr<float>();
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
size_t oldPosition = 0;
|
||||
size_t newPosition = i;
|
||||
|
||||
for (j = 0; j < numAxes; ++j)
|
||||
{
|
||||
oldPosition += (newPosition / newStride[j]) * oldStride[order[j]];
|
||||
newPosition %= newStride[j];
|
||||
}
|
||||
dstData[i] = srcData[oldPosition];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t _count;
|
||||
std::vector<size_t> _order;
|
||||
|
||||
std::vector<int> _oldDimensionSize;
|
||||
std::vector<int> _newDimensionSize;
|
||||
|
||||
std::vector<size_t> _oldStride;
|
||||
std::vector<size_t> _newStride;
|
||||
bool _needsPermute;
|
||||
|
||||
size_t _numAxes;
|
||||
};
|
||||
|
||||
Ptr<PermuteLayer> PermuteLayer::create(const LayerParams ¶ms)
|
||||
{
|
||||
return Ptr<PermuteLayer>(new PermuteLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
566
modules/dnn/src/layers/pooling_layer.cpp
Normal file
566
modules/dnn/src/layers/pooling_layer.cpp
Normal file
@ -0,0 +1,566 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "opencv2/core/hal/intrin.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include <float.h>
|
||||
#include <algorithm>
|
||||
using std::max;
|
||||
using std::min;
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
//TODO: add ceil_mode param
|
||||
class PoolingLayerImpl : public PoolingLayer
|
||||
{
|
||||
public:
|
||||
PoolingLayerImpl(const LayerParams& params)
|
||||
{
|
||||
type = PoolingLayer::MAX;
|
||||
computeMaxIdx = true;
|
||||
|
||||
if (params.has("pool"))
|
||||
{
|
||||
String pool = params.get<String>("pool").toLowerCase();
|
||||
if (pool == "max")
|
||||
type = PoolingLayer::MAX;
|
||||
else if (pool == "ave")
|
||||
type = PoolingLayer::AVE;
|
||||
else if (pool == "stochastic")
|
||||
type = PoolingLayer::STOCHASTIC;
|
||||
else
|
||||
CV_Error(Error::StsBadArg, "Unknown pooling type \"" + pool + "\"");
|
||||
}
|
||||
|
||||
getPoolingKernelParams(params, kernel.height, kernel.width, globalPooling,
|
||||
pad.height, pad.width, stride.height, stride.width, padMode);
|
||||
setParamsFrom(params);
|
||||
}
|
||||
|
||||
void finalize(const std::vector<Mat*> &inputs, std::vector<Mat> &outputs)
|
||||
{
|
||||
CV_Assert(inputs.size() == 1);
|
||||
|
||||
cv::Size inp(inputs[0]->size[3], inputs[0]->size[2]),
|
||||
out(outputs[0].size[3], outputs[0].size[2]);
|
||||
|
||||
if(globalPooling)
|
||||
{
|
||||
kernel = inp;
|
||||
}
|
||||
|
||||
getConvPoolPaddings(inp, out, kernel, stride, padMode, pad);
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide() &&
|
||||
(type == PoolingLayer::MAX ||
|
||||
type == PoolingLayer::AVE && !pad.width && !pad.height);
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
for (size_t ii = 0; ii < inputs.size(); ii++)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MAX:
|
||||
maxPooling(*inputs[ii], outputs[2 * ii], outputs[2 * ii + 1]);
|
||||
break;
|
||||
case AVE:
|
||||
avePooling(*inputs[ii], outputs[ii]);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsNotImplemented, "Not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
if (type == PoolingLayer::MAX)
|
||||
return initMaxPoolingHalide(inputs);
|
||||
else if (type == PoolingLayer::AVE)
|
||||
return initAvePoolingHalide(inputs);
|
||||
else
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
class MaxPoolingInvoker : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
const Mat* src_;
|
||||
Mat *dst_, *mask_;
|
||||
Size kernel_, stride_, pad_;
|
||||
int nstripes_;
|
||||
bool computeMaxIdx_;
|
||||
|
||||
MaxPoolingInvoker(const Mat& src, Mat& dst, Mat& mask, Size kernel,
|
||||
Size stride, Size pad, int nstripes, bool computeMaxIdx)
|
||||
{
|
||||
src_ = &src;
|
||||
dst_ = &dst;
|
||||
mask_ = &mask;
|
||||
kernel_ = kernel;
|
||||
stride_ = stride;
|
||||
pad_ = pad;
|
||||
nstripes_ = nstripes;
|
||||
computeMaxIdx_ = computeMaxIdx;
|
||||
|
||||
CV_Assert(src.isContinuous() && dst.isContinuous() &&
|
||||
src.type() == CV_32F && src.type() == dst.type() &&
|
||||
mask.type() == src.type() && src.dims == 4 && dst.dims == 4 &&
|
||||
src.size[0] == dst.size[0] && src.size[1] == dst.size[1] &&
|
||||
mask.size == dst.size);
|
||||
}
|
||||
|
||||
void operator()(const Range& r) const
|
||||
{
|
||||
int nimgs = dst_->size[0], channels = dst_->size[1];
|
||||
int width = dst_->size[3], height = dst_->size[2];
|
||||
int inp_width = src_->size[3], inp_height = src_->size[2];
|
||||
size_t total = dst_->total();
|
||||
size_t stripeSize = (total + nstripes_ - 1)/nstripes_;
|
||||
size_t stripeStart = r.start*stripeSize;
|
||||
size_t stripeEnd = std::min(r.end*stripeSize, total);
|
||||
size_t ofs = stripeStart;
|
||||
int x0 = (int)(ofs % width);
|
||||
ofs /= width;
|
||||
int y0 = (int)(ofs % height);
|
||||
ofs /= height;
|
||||
int c = (int)(ofs % channels);
|
||||
int n = (int)(ofs / channels);
|
||||
const float *srcData = src_->ptr<float>(n, c);
|
||||
float *dstData = dst_->ptr<float>(n, c, y0) + x0;
|
||||
float *dstMaskData = mask_->ptr<float>(n, c, y0) + x0;
|
||||
int kernel_w = kernel_.width, kernel_h = kernel_.height;
|
||||
int pad_w = pad_.width, pad_h = pad_.height;
|
||||
int stride_w = stride_.width, stride_h = stride_.height;
|
||||
bool compMaxIdx = computeMaxIdx_;
|
||||
#if CV_SIMD128
|
||||
v_float32x4 idx00(0.f, (float)stride_w, (float)(stride_w*2), (float)(stride_w*3));
|
||||
v_float32x4 ones = v_setall_f32(1.f);
|
||||
v_float32x4 delta = v_setall_f32((float)(inp_width - kernel_w));
|
||||
#endif
|
||||
|
||||
for( ofs = stripeStart; ofs < stripeEnd; ofs++ )
|
||||
{
|
||||
int ystart = y0 * stride_h - pad_h;
|
||||
int xstart = x0 * stride_w - pad_w;
|
||||
int yend = min(ystart + kernel_h, inp_height);
|
||||
int xend = min(xstart + kernel_w, inp_width);
|
||||
ystart = max(ystart, 0);
|
||||
xstart = max(xstart, 0);
|
||||
float max_val = -FLT_MAX;
|
||||
int max_index = -1;
|
||||
|
||||
#if CV_SIMD128
|
||||
if( xstart > 0 && (x0 + 7) * stride_w - pad_w + kernel_w < inp_width )
|
||||
{
|
||||
if( compMaxIdx )
|
||||
{
|
||||
v_float32x4 max_val0 = v_setall_f32(max_val);
|
||||
v_float32x4 max_val1 = max_val0;
|
||||
v_float32x4 max_idx0 = v_setall_f32(-1.f);
|
||||
v_float32x4 max_idx1 = max_idx0;
|
||||
int index0 = ystart * inp_width + xstart;
|
||||
v_float32x4 idx0 = idx00 + v_setall_f32((float)index0);
|
||||
v_float32x4 idx1 = idx0 + v_setall_f32((float)(stride_w*4));
|
||||
|
||||
for (int y = ystart; y < yend; ++y)
|
||||
{
|
||||
for (int x = xstart; x < xend; ++x, idx0 += ones, idx1 += ones)
|
||||
{
|
||||
const int index = y * inp_width + x;
|
||||
v_float32x4 v0(srcData[index], srcData[index + stride_w],
|
||||
srcData[index + stride_w*2], srcData[index + stride_w*3]);
|
||||
v_float32x4 v1(srcData[index + stride_w*4], srcData[index + stride_w*5],
|
||||
srcData[index + stride_w*6], srcData[index + stride_w*7]);
|
||||
max_idx0 = v_select(v0 > max_val0, idx0, max_idx0);
|
||||
max_idx1 = v_select(v1 > max_val1, idx1, max_idx1);
|
||||
max_val0 = v_max(max_val0, v0);
|
||||
max_val1 = v_max(max_val1, v1);
|
||||
}
|
||||
idx0 += delta;
|
||||
idx1 += delta;
|
||||
}
|
||||
v_store(dstData, max_val0);
|
||||
v_store(dstData + 4, max_val1);
|
||||
v_store(dstMaskData, max_idx0);
|
||||
v_store(dstMaskData + 4, max_idx1);
|
||||
ofs += 7;
|
||||
dstData += 8;
|
||||
dstMaskData += 8;
|
||||
x0 += 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
v_float32x4 max_val0 = v_setall_f32(max_val);
|
||||
v_float32x4 max_val1 = max_val0;
|
||||
|
||||
for (int y = ystart; y < yend; ++y)
|
||||
{
|
||||
for (int x = xstart; x < xend; ++x)
|
||||
{
|
||||
const int index = y * inp_width + x;
|
||||
v_float32x4 v0(srcData[index], srcData[index + stride_w],
|
||||
srcData[index + stride_w*2], srcData[index + stride_w*3]);
|
||||
v_float32x4 v1(srcData[index + stride_w*4], srcData[index + stride_w*5],
|
||||
srcData[index + stride_w*6], srcData[index + stride_w*7]);
|
||||
max_val0 = v_max(max_val0, v0);
|
||||
max_val1 = v_max(max_val1, v1);
|
||||
}
|
||||
}
|
||||
v_store(dstData, max_val0);
|
||||
v_store(dstData + 4, max_val1);
|
||||
ofs += 7;
|
||||
dstData += 8;
|
||||
x0 += 7;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if( compMaxIdx )
|
||||
{
|
||||
for (int y = ystart; y < yend; ++y)
|
||||
for (int x = xstart; x < xend; ++x)
|
||||
{
|
||||
const int index = y * inp_width + x;
|
||||
float val = srcData[index];
|
||||
if (val > max_val)
|
||||
{
|
||||
max_val = val;
|
||||
max_index = index;
|
||||
}
|
||||
}
|
||||
|
||||
*dstData++ = max_val;
|
||||
*dstMaskData++ = max_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = ystart; y < yend; ++y)
|
||||
for (int x = xstart; x < xend; ++x)
|
||||
{
|
||||
const int index = y * inp_width + x;
|
||||
float val = srcData[index];
|
||||
max_val = std::max(max_val, val);
|
||||
}
|
||||
|
||||
*dstData++ = max_val;
|
||||
}
|
||||
}
|
||||
|
||||
if( ++x0 >= width )
|
||||
{
|
||||
x0 = 0;
|
||||
if( ++y0 >= height )
|
||||
{
|
||||
y0 = 0;
|
||||
if( ++c >= channels )
|
||||
{
|
||||
c = 0;
|
||||
if( ++n >= nimgs )
|
||||
break;
|
||||
}
|
||||
srcData = src_->ptr<float>(n, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void maxPooling(Mat &src, Mat &dst, Mat &mask)
|
||||
{
|
||||
const int nstripes = getNumThreads();
|
||||
MaxPoolingInvoker mp(src, dst, mask, kernel, stride, pad, nstripes, computeMaxIdx);
|
||||
parallel_for_(Range(0, nstripes), mp, nstripes);
|
||||
}
|
||||
|
||||
void avePooling(Mat &src, Mat &dst)
|
||||
{
|
||||
Size inp(src.size[3], src.size[2]),
|
||||
out(dst.size[3], dst.size[2]);
|
||||
for (int n = 0; n < src.size[0]; ++n)
|
||||
{
|
||||
for (int c = 0; c < src.size[1]; ++c)
|
||||
{
|
||||
const float *srcData = src.ptr<float>(n, c);
|
||||
float *dstData = dst.ptr<float>(n, c);
|
||||
|
||||
for (int ph = 0; ph < out.height; ++ph)
|
||||
{
|
||||
for (int pw = 0; pw < out.width; ++pw)
|
||||
{
|
||||
int hstart = ph * stride.height - pad.height;
|
||||
int wstart = pw * stride.width - pad.width;
|
||||
int hend = min(hstart + kernel.height, inp.height + pad.height);
|
||||
int wend = min(wstart + kernel.width, inp.width + pad.width);
|
||||
int poolSize = (hend - hstart) * (wend - wstart);
|
||||
hstart = max(hstart, 0);
|
||||
wstart = max(wstart, 0);
|
||||
hend = min(hend, inp.height);
|
||||
wend = min(wend, inp.width);
|
||||
|
||||
dstData[ph * out.width + pw] = 0.f;
|
||||
|
||||
for (int h = hstart; h < hend; ++h)
|
||||
for (int w = wstart; w < wend; ++w)
|
||||
dstData[ph * out.width + pw] += srcData[h * inp.width + w];
|
||||
|
||||
dstData[ph * out.width + pw] /= poolSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initMaxPoolingHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
|
||||
const int inWidth = inputBuffer.width();
|
||||
const int inHeight = inputBuffer.height();
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::RDom r(0, kernel.width, 0, kernel.height);
|
||||
Halide::Expr kx, ky;
|
||||
if (pad.width || pad.height)
|
||||
{
|
||||
kx = clamp(x * stride.width + r.x - pad.width, 0, inWidth - 1);
|
||||
ky = clamp(y * stride.height + r.y - pad.height, 0, inHeight - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
kx = min(x * stride.width + r.x, inWidth - 1);
|
||||
ky = min(y * stride.height + r.y, inHeight - 1);
|
||||
}
|
||||
|
||||
// Halide::argmax returns tuple (r.x, r.y, max).
|
||||
Halide::Tuple res = argmax(inputBuffer(kx, ky, c, n));
|
||||
|
||||
// Compute offset from argmax in range [0, kernel_size).
|
||||
Halide::Expr max_index;
|
||||
if (pad.width || pad.height)
|
||||
{
|
||||
max_index = clamp(y * stride.height + res[1] - pad.height,
|
||||
0, inHeight - 1) * inWidth +
|
||||
clamp(x * stride.width + res[0] - pad.width,
|
||||
0, inWidth - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
max_index = min(y * stride.height + res[1], inHeight - 1) * inWidth +
|
||||
min(x * stride.width + res[0], inWidth - 1);
|
||||
}
|
||||
top(x, y, c, n) = { res[2], Halide::cast<float>(max_index) };
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initAvePoolingHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
|
||||
|
||||
const int inW = inputBuffer.width(), inH = inputBuffer.height();
|
||||
if ((inW - kernel.width) % stride.width || (inH - kernel.height) % stride.height)
|
||||
{
|
||||
CV_Error(cv::Error::StsNotImplemented,
|
||||
"Halide backend for average pooling with partial "
|
||||
"kernels is not implemented");
|
||||
}
|
||||
|
||||
const float norm = 1.0f / (kernel.width * kernel.height);
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::RDom r(0, kernel.width, 0, kernel.height);
|
||||
top(x, y, c, n) = sum(
|
||||
inputBuffer(x * stride.width + r.x,
|
||||
y * stride.height + r.y, c, n)) * norm;
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
virtual void applyHalideScheduler(Ptr<BackendNode>& node,
|
||||
const std::vector<Mat*> &inputs,
|
||||
const std::vector<Mat> &outputs,
|
||||
int targetId) const
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
if (targetId != DNN_TARGET_CPU)
|
||||
{
|
||||
Layer::applyHalideScheduler(node, inputs, outputs, targetId);
|
||||
return;
|
||||
}
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n"), tile("tile"),
|
||||
xi("xi"), yi("yi"), ci("ci"), xo("xo"), yo("yo"), co("co");
|
||||
Halide::Func& top = node.dynamicCast<HalideBackendNode>()->funcs.back();
|
||||
|
||||
int outW, outH, outC, outN;
|
||||
getCanonicalSize(outputs[0].size, &outW, &outH, &outC, &outN);
|
||||
|
||||
if (outW < 8 || outH < 8)
|
||||
{
|
||||
if (outC > 8)
|
||||
top.split(c, co, ci, 8)
|
||||
.fuse(x, y, tile).fuse(co, tile, tile).fuse(n, tile, tile)
|
||||
.parallel(tile)
|
||||
.vectorize(ci);
|
||||
else
|
||||
{
|
||||
top.fuse(y, c, tile).fuse(n, tile, tile)
|
||||
.parallel(tile);
|
||||
if (outW > 1)
|
||||
top.vectorize(x);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outC > 8)
|
||||
top.split(x, xo, xi, 8).split(y, yo, yi, 8).split(c, co, ci, 8)
|
||||
.fuse(xo, yo, tile).fuse(co, tile, tile).fuse(n, tile, tile)
|
||||
.parallel(tile)
|
||||
.vectorize(xi);
|
||||
else
|
||||
top.split(x, xo, xi, 8).split(y, yo, yi, 8)
|
||||
.fuse(xo, yo, tile).fuse(c, tile, tile).fuse(n, tile, tile)
|
||||
.parallel(tile)
|
||||
.vectorize(xi);
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() != 0);
|
||||
Size in(inputs[0][3], inputs[0][2]), out;
|
||||
|
||||
if (globalPooling)
|
||||
{
|
||||
out.height = 1;
|
||||
out.width = 1;
|
||||
}
|
||||
else if (padMode.empty())
|
||||
{
|
||||
//Yeah, something strange Caffe scheme-)
|
||||
out.height = static_cast<int>(ceil(static_cast<float>(in.height + 2 * pad.height -
|
||||
kernel.height) / stride.height)) + 1;
|
||||
out.width = static_cast<int>(ceil(static_cast<float>(in.width + 2 * pad.width -
|
||||
kernel.width) / stride.width)) + 1;
|
||||
|
||||
if (pad.height || pad.width)
|
||||
{
|
||||
// If we have padding, ensure that the last pooling starts strictly
|
||||
// inside the image (instead of at the padding); otherwise clip the last.
|
||||
if ((out.height - 1) * stride.height >= in.height + pad.height)
|
||||
--out.height;
|
||||
if ((out.width - 1) * stride.width >= in.width + pad.width)
|
||||
--out.width;
|
||||
CV_Assert((out.height - 1) * stride.height < in.height + pad.height);
|
||||
CV_Assert((out.width - 1) * stride.width < in.width + pad.width);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getConvPoolOutParams(in, kernel, stride,
|
||||
padMode, out);
|
||||
}
|
||||
|
||||
outputs.resize(type == MAX ? 2 * inputs.size() : inputs.size());
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
size_t index = type == MAX ? 2*i : i;
|
||||
int dims[] = {inputs[i][0], inputs[i][1], out.height, out.width};
|
||||
outputs[index] = shape(dims);
|
||||
|
||||
if (type == MAX)
|
||||
outputs[index + 1] = shape(dims);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)inputs; // suppress unused variable warning
|
||||
long flops = 0;
|
||||
|
||||
for(int i = 0; i < outputs.size(); i++)
|
||||
{
|
||||
if (type == MAX)
|
||||
{
|
||||
if (i%2 == 0)
|
||||
flops += total(outputs[i])*kernel.area();
|
||||
}
|
||||
else
|
||||
{
|
||||
flops += total(outputs[i])*(kernel.area() + 1);
|
||||
}
|
||||
}
|
||||
return flops;
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<PoolingLayer> PoolingLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<PoolingLayer>(new PoolingLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
379
modules/dnn/src/layers/prior_box_layer.cpp
Normal file
379
modules/dnn/src/layers/prior_box_layer.cpp
Normal file
@ -0,0 +1,379 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include <float.h>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class PriorBoxLayerImpl : public PriorBoxLayer
|
||||
{
|
||||
public:
|
||||
bool getParameterDict(const LayerParams ¶ms,
|
||||
const std::string ¶meterName,
|
||||
DictValue& result)
|
||||
{
|
||||
if (!params.has(parameterName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result = params.get(parameterName);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T getParameter(const LayerParams ¶ms,
|
||||
const std::string ¶meterName,
|
||||
const size_t &idx=0,
|
||||
const bool required=true,
|
||||
const T& defaultValue=T())
|
||||
{
|
||||
DictValue dictValue;
|
||||
bool success = getParameterDict(params, parameterName, dictValue);
|
||||
if(!success)
|
||||
{
|
||||
if(required)
|
||||
{
|
||||
std::string message = _layerName;
|
||||
message += " layer parameter does not contain ";
|
||||
message += parameterName;
|
||||
message += " parameter.";
|
||||
CV_Error(Error::StsBadArg, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return dictValue.get<T>(idx);
|
||||
}
|
||||
|
||||
void getAspectRatios(const LayerParams ¶ms)
|
||||
{
|
||||
DictValue aspectRatioParameter;
|
||||
bool aspectRatioRetieved = getParameterDict(params, "aspect_ratio", aspectRatioParameter);
|
||||
CV_Assert(aspectRatioRetieved);
|
||||
|
||||
for (int i = 0; i < aspectRatioParameter.size(); ++i)
|
||||
{
|
||||
float aspectRatio = aspectRatioParameter.get<float>(i);
|
||||
bool alreadyExists = false;
|
||||
|
||||
for (size_t j = 0; j < _aspectRatios.size(); ++j)
|
||||
{
|
||||
if (fabs(aspectRatio - _aspectRatios[j]) < 1e-6)
|
||||
{
|
||||
alreadyExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyExists)
|
||||
{
|
||||
_aspectRatios.push_back(aspectRatio);
|
||||
if (_flip)
|
||||
{
|
||||
_aspectRatios.push_back(1./aspectRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getVariance(const LayerParams ¶ms)
|
||||
{
|
||||
DictValue varianceParameter;
|
||||
bool varianceParameterRetrieved = getParameterDict(params, "variance", varianceParameter);
|
||||
CV_Assert(varianceParameterRetrieved);
|
||||
|
||||
int varianceSize = varianceParameter.size();
|
||||
if (varianceSize > 1)
|
||||
{
|
||||
// Must and only provide 4 variance.
|
||||
CV_Assert(varianceSize == 4);
|
||||
|
||||
for (int i = 0; i < varianceSize; ++i)
|
||||
{
|
||||
float variance = varianceParameter.get<float>(i);
|
||||
CV_Assert(variance > 0);
|
||||
_variance.push_back(variance);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (varianceSize == 1)
|
||||
{
|
||||
float variance = varianceParameter.get<float>(0);
|
||||
CV_Assert(variance > 0);
|
||||
_variance.push_back(variance);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set default to 0.1.
|
||||
_variance.push_back(0.1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PriorBoxLayerImpl(const LayerParams ¶ms)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
_minSize = getParameter<unsigned>(params, "min_size");
|
||||
CV_Assert(_minSize > 0);
|
||||
|
||||
_flip = getParameter<bool>(params, "flip");
|
||||
_clip = getParameter<bool>(params, "clip");
|
||||
|
||||
_aspectRatios.clear();
|
||||
_aspectRatios.push_back(1.);
|
||||
|
||||
getAspectRatios(params);
|
||||
getVariance(params);
|
||||
|
||||
_numPriors = _aspectRatios.size();
|
||||
|
||||
_maxSize = -1;
|
||||
if (params.has("max_size"))
|
||||
{
|
||||
_maxSize = params.get("max_size").get<float>(0);
|
||||
CV_Assert(_maxSize > _minSize);
|
||||
|
||||
_numPriors += 1;
|
||||
}
|
||||
|
||||
if (params.has("step_h") || params.has("step_w")) {
|
||||
CV_Assert(!params.has("step"));
|
||||
_stepY = getParameter<float>(params, "step_h");
|
||||
CV_Assert(_stepY > 0.);
|
||||
_stepX = getParameter<float>(params, "step_w");
|
||||
CV_Assert(_stepX > 0.);
|
||||
} else if (params.has("step")) {
|
||||
const float step = getParameter<float>(params, "step");
|
||||
CV_Assert(step > 0);
|
||||
_stepY = step;
|
||||
_stepX = step;
|
||||
} else {
|
||||
_stepY = 0;
|
||||
_stepX = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() == 2);
|
||||
|
||||
int layerHeight = inputs[0][2];
|
||||
int layerWidth = inputs[0][3];
|
||||
|
||||
// Since all images in a batch has same height and width, we only need to
|
||||
// generate one set of priors which can be shared across all images.
|
||||
size_t outNum = 1;
|
||||
// 2 channels. First channel stores the mean of each prior coordinate.
|
||||
// Second channel stores the variance of each prior coordinate.
|
||||
size_t outChannels = 2;
|
||||
|
||||
outputs.resize(1, shape(outNum, outChannels,
|
||||
layerHeight * layerWidth * _numPriors * 4));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
int _layerWidth = inputs[0]->size[3];
|
||||
int _layerHeight = inputs[0]->size[2];
|
||||
|
||||
int _imageWidth = inputs[1]->size[3];
|
||||
int _imageHeight = inputs[1]->size[2];
|
||||
|
||||
float stepX, stepY;
|
||||
if (_stepX == 0 || _stepY == 0) {
|
||||
stepX = static_cast<float>(_imageWidth) / _layerWidth;
|
||||
stepY = static_cast<float>(_imageHeight) / _layerHeight;
|
||||
} else {
|
||||
stepX = _stepX;
|
||||
stepY = _stepY;
|
||||
}
|
||||
|
||||
int _outChannelSize = _layerHeight * _layerWidth * _numPriors * 4;
|
||||
|
||||
float* outputPtr = outputs[0].ptr<float>();
|
||||
|
||||
// first prior: aspect_ratio = 1, size = min_size
|
||||
int idx = 0;
|
||||
for (size_t h = 0; h < _layerHeight; ++h)
|
||||
{
|
||||
for (size_t w = 0; w < _layerWidth; ++w)
|
||||
{
|
||||
_boxWidth = _boxHeight = _minSize;
|
||||
|
||||
float center_x = (w + 0.5) * stepX;
|
||||
float center_y = (h + 0.5) * stepY;
|
||||
// xmin
|
||||
outputPtr[idx++] = (center_x - _boxWidth / 2.) / _imageWidth;
|
||||
// ymin
|
||||
outputPtr[idx++] = (center_y - _boxHeight / 2.) / _imageHeight;
|
||||
// xmax
|
||||
outputPtr[idx++] = (center_x + _boxWidth / 2.) / _imageWidth;
|
||||
// ymax
|
||||
outputPtr[idx++] = (center_y + _boxHeight / 2.) / _imageHeight;
|
||||
|
||||
if (_maxSize > 0)
|
||||
{
|
||||
// second prior: aspect_ratio = 1, size = sqrt(min_size * max_size)
|
||||
_boxWidth = _boxHeight = sqrt(_minSize * _maxSize);
|
||||
// xmin
|
||||
outputPtr[idx++] = (center_x - _boxWidth / 2.) / _imageWidth;
|
||||
// ymin
|
||||
outputPtr[idx++] = (center_y - _boxHeight / 2.) / _imageHeight;
|
||||
// xmax
|
||||
outputPtr[idx++] = (center_x + _boxWidth / 2.) / _imageWidth;
|
||||
// ymax
|
||||
outputPtr[idx++] = (center_y + _boxHeight / 2.) / _imageHeight;
|
||||
}
|
||||
|
||||
// rest of priors
|
||||
for (size_t r = 0; r < _aspectRatios.size(); ++r)
|
||||
{
|
||||
float ar = _aspectRatios[r];
|
||||
if (fabs(ar - 1.) < 1e-6)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
_boxWidth = _minSize * sqrt(ar);
|
||||
_boxHeight = _minSize / sqrt(ar);
|
||||
// xmin
|
||||
outputPtr[idx++] = (center_x - _boxWidth / 2.) / _imageWidth;
|
||||
// ymin
|
||||
outputPtr[idx++] = (center_y - _boxHeight / 2.) / _imageHeight;
|
||||
// xmax
|
||||
outputPtr[idx++] = (center_x + _boxWidth / 2.) / _imageWidth;
|
||||
// ymax
|
||||
outputPtr[idx++] = (center_y + _boxHeight / 2.) / _imageHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
// clip the prior's coordidate such that it is within [0, 1]
|
||||
if (_clip)
|
||||
{
|
||||
for (size_t d = 0; d < _outChannelSize; ++d)
|
||||
{
|
||||
outputPtr[d] = std::min<float>(std::max<float>(outputPtr[d], 0.), 1.);
|
||||
}
|
||||
}
|
||||
// set the variance.
|
||||
outputPtr = outputs[0].ptr<float>(0, 1);
|
||||
if(_variance.size() == 1)
|
||||
{
|
||||
Mat secondChannel(outputs[0].size[2], outputs[0].size[3], CV_32F, outputPtr);
|
||||
secondChannel.setTo(Scalar(_variance[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = 0;
|
||||
for (size_t h = 0; h < _layerHeight; ++h)
|
||||
{
|
||||
for (size_t w = 0; w < _layerWidth; ++w)
|
||||
{
|
||||
for (size_t i = 0; i < _numPriors; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
outputPtr[count] = _variance[j];
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)outputs; // suppress unused variable warning
|
||||
long flops = 0;
|
||||
|
||||
for (int i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
flops += total(inputs[i], 2) * _numPriors * 4;
|
||||
}
|
||||
|
||||
return flops;
|
||||
}
|
||||
|
||||
float _minSize;
|
||||
float _maxSize;
|
||||
|
||||
float _boxWidth;
|
||||
float _boxHeight;
|
||||
|
||||
float _stepX, _stepY;
|
||||
|
||||
std::vector<float> _aspectRatios;
|
||||
std::vector<float> _variance;
|
||||
|
||||
bool _flip;
|
||||
bool _clip;
|
||||
|
||||
size_t _numPriors;
|
||||
|
||||
static const size_t _numAxes = 4;
|
||||
static const std::string _layerName;
|
||||
};
|
||||
|
||||
const std::string PriorBoxLayerImpl::_layerName = std::string("PriorBox");
|
||||
|
||||
Ptr<PriorBoxLayer> PriorBoxLayer::create(const LayerParams ¶ms)
|
||||
{
|
||||
return Ptr<PriorBoxLayer>(new PriorBoxLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
443
modules/dnn/src/layers/recurrent_layers.cpp
Normal file
443
modules/dnn/src/layers/recurrent_layers.cpp
Normal file
@ -0,0 +1,443 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <cmath>
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
template<typename Dtype>
|
||||
static void tanh(const Mat &src, Mat &dst)
|
||||
{
|
||||
MatConstIterator_<Dtype> itSrc = src.begin<Dtype>();
|
||||
MatIterator_<Dtype> itDst = dst.begin<Dtype>();
|
||||
|
||||
for (; itSrc != src.end<Dtype>(); itSrc++, itDst++)
|
||||
*itDst = std::tanh(*itSrc);
|
||||
}
|
||||
|
||||
//TODO: make utils method
|
||||
static void tanh(const Mat &src, Mat &dst)
|
||||
{
|
||||
dst.create(src.dims, (const int*)src.size, src.type());
|
||||
|
||||
if (src.type() == CV_32F)
|
||||
tanh<float>(src, dst);
|
||||
else if (src.type() == CV_64F)
|
||||
tanh<double>(src, dst);
|
||||
else
|
||||
CV_Error(Error::StsUnsupportedFormat, "Function supports only floating point types");
|
||||
}
|
||||
|
||||
static void sigmoid(const Mat &src, Mat &dst)
|
||||
{
|
||||
cv::exp(-src, dst);
|
||||
cv::pow(1 + dst, -1, dst);
|
||||
}
|
||||
|
||||
class LSTMLayerImpl : public LSTMLayer
|
||||
{
|
||||
int numTimeStamps, numSamples;
|
||||
bool allocated;
|
||||
|
||||
MatShape outTailShape; //shape of single output sample
|
||||
MatShape outTsShape; //shape of N output samples
|
||||
|
||||
bool useTimestampDim;
|
||||
bool produceCellOutput;
|
||||
|
||||
public:
|
||||
|
||||
LSTMLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
type = "LSTM";
|
||||
useTimestampDim = true;
|
||||
produceCellOutput = false;
|
||||
allocated = false;
|
||||
outTailShape.clear();
|
||||
}
|
||||
|
||||
void setUseTimstampsDim(bool use)
|
||||
{
|
||||
CV_Assert(!allocated);
|
||||
useTimestampDim = use;
|
||||
}
|
||||
|
||||
void setProduceCellOutput(bool produce)
|
||||
{
|
||||
CV_Assert(!allocated);
|
||||
produceCellOutput = produce;
|
||||
}
|
||||
|
||||
void setOutShape(const MatShape &outTailShape_)
|
||||
{
|
||||
CV_Assert(!allocated || total(outTailShape) == total(outTailShape_));
|
||||
outTailShape = outTailShape_;
|
||||
}
|
||||
|
||||
void setWeights(const Mat &Wh, const Mat &Wx, const Mat &bias)
|
||||
{
|
||||
CV_Assert(Wh.dims == 2 && Wx.dims == 2);
|
||||
CV_Assert(Wh.rows == Wx.rows);
|
||||
CV_Assert(Wh.rows == 4*Wh.cols);
|
||||
CV_Assert(Wh.rows == (int)bias.total());
|
||||
CV_Assert(Wh.type() == Wx.type() && Wx.type() == bias.type());
|
||||
|
||||
blobs.resize(3);
|
||||
blobs[0] = Mat(Wh.clone());
|
||||
blobs[1] = Mat(Wx.clone());
|
||||
blobs[2] = Mat(bias.clone()).reshape(1, 1);
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(blobs.size() == 3);
|
||||
CV_Assert(inputs.size() == 1);
|
||||
const MatShape& inp0 = inputs[0];
|
||||
|
||||
const Mat &Wh = blobs[0], &Wx = blobs[1];
|
||||
int _numOut = Wh.size[1];
|
||||
int _numInp = Wx.size[1];
|
||||
MatShape outTailShape_(outTailShape), outResShape;
|
||||
|
||||
if (!outTailShape_.empty())
|
||||
CV_Assert(total(outTailShape_) == _numOut);
|
||||
else
|
||||
outTailShape_.assign(1, _numOut);
|
||||
|
||||
int _numTimeStamps, _numSamples;
|
||||
if (useTimestampDim)
|
||||
{
|
||||
CV_Assert(inp0.size() >= 2 && total(inp0, 2) == _numInp);
|
||||
_numTimeStamps = inp0[0];
|
||||
_numSamples = inp0[1];
|
||||
outResShape.push_back(_numTimeStamps);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(inp0.size() >= 2 && total(inp0, 1) == _numInp);
|
||||
_numTimeStamps = 1;
|
||||
_numSamples = inp0[0];
|
||||
}
|
||||
|
||||
outResShape.push_back(_numSamples);
|
||||
outResShape.insert(outResShape.end(), outTailShape_.begin(), outTailShape_.end());
|
||||
|
||||
size_t noutputs = produceCellOutput ? 2 : 1;
|
||||
outputs.assign(noutputs, outResShape);
|
||||
|
||||
internals.assign(1, shape(_numSamples, _numOut)); // hInternal
|
||||
internals.push_back(shape(_numSamples, _numOut)); // cInternal
|
||||
internals.push_back(shape(_numSamples, 1)); // dummyOnes
|
||||
internals.push_back(shape(_numSamples, 4*_numOut)); // gates
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void finalize(const std::vector<Mat*> &input, std::vector<Mat> &output)
|
||||
{
|
||||
CV_Assert(blobs.size() == 3);
|
||||
CV_Assert(input.size() == 1);
|
||||
const Mat& inp0 = *input[0];
|
||||
|
||||
Mat &Wh = blobs[0], &Wx = blobs[1];
|
||||
int numOut = Wh.size[1];
|
||||
int numInp = Wx.size[1];
|
||||
|
||||
if (!outTailShape.empty())
|
||||
CV_Assert(total(outTailShape) == numOut);
|
||||
else
|
||||
outTailShape.assign(1, numOut);
|
||||
|
||||
if (useTimestampDim)
|
||||
{
|
||||
CV_Assert(inp0.dims >= 2 && (int)inp0.total(2) == numInp);
|
||||
numTimeStamps = inp0.size[0];
|
||||
numSamples = inp0.size[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(inp0.dims >= 2 && (int)inp0.total(1) == numInp);
|
||||
numTimeStamps = 1;
|
||||
numSamples = inp0.size[0];
|
||||
}
|
||||
|
||||
outTsShape.clear();
|
||||
outTsShape.push_back(numSamples);
|
||||
outTsShape.insert(outTsShape.end(), outTailShape.begin(), outTailShape.end());
|
||||
|
||||
allocated = true;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &input, std::vector<Mat> &output, std::vector<Mat> &internals)
|
||||
{
|
||||
const Mat &Wh = blobs[0];
|
||||
const Mat &Wx = blobs[1];
|
||||
const Mat &bias = blobs[2];
|
||||
|
||||
int numOut = Wh.size[1];
|
||||
|
||||
Mat hInternal = internals[0], cInternal = internals[1],
|
||||
dummyOnes = internals[2], gates = internals[3];
|
||||
hInternal.setTo(0.);
|
||||
cInternal.setTo(0.);
|
||||
dummyOnes.setTo(1.);
|
||||
|
||||
int numSamplesTotal = numTimeStamps*numSamples;
|
||||
Mat xTs = input[0]->reshape(1, numSamplesTotal);
|
||||
|
||||
Mat hOutTs = output[0].reshape(1, numSamplesTotal);
|
||||
Mat cOutTs = produceCellOutput ? output[1].reshape(1, numSamplesTotal) : Mat();
|
||||
|
||||
for (int ts = 0; ts < numTimeStamps; ts++)
|
||||
{
|
||||
Range curRowRange(ts*numSamples, (ts + 1)*numSamples);
|
||||
Mat xCurr = xTs.rowRange(curRowRange);
|
||||
|
||||
gemm(xCurr, Wx, 1, gates, 0, gates, GEMM_2_T); // Wx * x_t
|
||||
gemm(hInternal, Wh, 1, gates, 1, gates, GEMM_2_T); //+Wh * h_{t-1}
|
||||
gemm(dummyOnes, bias, 1, gates, 1, gates); //+b
|
||||
|
||||
Mat getesIFO = gates.colRange(0, 3*numOut);
|
||||
Mat gateI = gates.colRange(0*numOut, 1*numOut);
|
||||
Mat gateF = gates.colRange(1*numOut, 2*numOut);
|
||||
Mat gateO = gates.colRange(2*numOut, 3*numOut);
|
||||
Mat gateG = gates.colRange(3*numOut, 4*numOut);
|
||||
|
||||
sigmoid(getesIFO, getesIFO);
|
||||
tanh(gateG, gateG);
|
||||
|
||||
//compute c_t
|
||||
multiply(gateF, cInternal, gateF); // f_t (*) c_{t-1}
|
||||
multiply(gateI, gateG, gateI); // i_t (*) g_t
|
||||
add(gateF, gateI, cInternal); // c_t = f_t (*) c_{t-1} + i_t (*) g_t
|
||||
|
||||
//compute h_t
|
||||
tanh(cInternal, hInternal);
|
||||
multiply(gateO, hInternal, hInternal);
|
||||
|
||||
//save results in output blobs
|
||||
hInternal.copyTo(hOutTs.rowRange(curRowRange));
|
||||
if (produceCellOutput)
|
||||
cInternal.copyTo(cOutTs.rowRange(curRowRange));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<LSTMLayer> LSTMLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<LSTMLayer>(new LSTMLayerImpl(params));
|
||||
}
|
||||
|
||||
int LSTMLayer::inputNameToIndex(String inputName)
|
||||
{
|
||||
if (inputName.toLowerCase() == "x")
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int LSTMLayer::outputNameToIndex(String outputName)
|
||||
{
|
||||
if (outputName.toLowerCase() == "h")
|
||||
return 0;
|
||||
else if (outputName.toLowerCase() == "c")
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
class RNNLayerImpl : public RNNLayer
|
||||
{
|
||||
int numX, numH, numO;
|
||||
int numSamples, numTimestamps, numSamplesTotal;
|
||||
int dtype;
|
||||
Mat Whh, Wxh, bh;
|
||||
Mat Who, bo;
|
||||
bool produceH;
|
||||
|
||||
public:
|
||||
|
||||
RNNLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
type = "RNN";
|
||||
produceH = false;
|
||||
}
|
||||
|
||||
void setProduceHiddenOutput(bool produce = false)
|
||||
{
|
||||
produceH = produce;
|
||||
}
|
||||
|
||||
void setWeights(const Mat &W_xh, const Mat &b_h, const Mat &W_hh, const Mat &W_ho, const Mat &b_o)
|
||||
{
|
||||
CV_Assert(W_hh.dims == 2 && W_xh.dims == 2);
|
||||
CV_Assert(W_hh.size[0] == W_xh.size[0] && W_hh.size[0] == W_hh.size[1] && (int)b_h.total() == W_xh.size[0]);
|
||||
CV_Assert(W_ho.size[0] == (int)b_o.total());
|
||||
CV_Assert(W_ho.size[1] == W_hh.size[1]);
|
||||
|
||||
blobs.resize(5);
|
||||
blobs[0] = Mat(W_xh.clone());
|
||||
blobs[1] = Mat(b_h.clone());
|
||||
blobs[2] = Mat(W_hh.clone());
|
||||
blobs[3] = Mat(W_ho.clone());
|
||||
blobs[4] = Mat(b_o.clone());
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() >= 1 && inputs.size() <= 2);
|
||||
|
||||
Mat Who_ = blobs[3];
|
||||
Mat Wxh_ = blobs[0];
|
||||
|
||||
int numTimestamps_ = inputs[0][0];
|
||||
int numSamples_ = inputs[0][1];
|
||||
|
||||
int numO_ = Who_.rows;
|
||||
int numH_ = Wxh_.rows;
|
||||
|
||||
outputs.clear();
|
||||
int dims[] = {numTimestamps_, numSamples_, numO_};
|
||||
outputs.push_back(shape(dims, 3));
|
||||
dims[2] = numH_;
|
||||
if (produceH)
|
||||
outputs.push_back(shape(dims, 3));
|
||||
|
||||
internals.assign(2, shape(numSamples_, numH_));
|
||||
internals.push_back(shape(numSamples_, 1));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void finalize(const std::vector<Mat*> &input, std::vector<Mat> &output)
|
||||
{
|
||||
CV_Assert(input.size() >= 1 && input.size() <= 2);
|
||||
|
||||
Wxh = blobs[0];
|
||||
bh = blobs[1];
|
||||
Whh = blobs[2];
|
||||
Who = blobs[3];
|
||||
bo = blobs[4];
|
||||
|
||||
numH = Wxh.rows;
|
||||
numX = Wxh.cols;
|
||||
numO = Who.rows;
|
||||
|
||||
const Mat& inp0 = *input[0];
|
||||
|
||||
CV_Assert(inp0.dims >= 2);
|
||||
CV_Assert(inp0.total(2) == numX);
|
||||
dtype = CV_32F;
|
||||
CV_Assert(inp0.type() == dtype);
|
||||
numTimestamps = inp0.size[0];
|
||||
numSamples = inp0.size[1];
|
||||
numSamplesTotal = numTimestamps * numSamples;
|
||||
|
||||
bh = bh.reshape(1, 1); //is 1 x numH Mat
|
||||
bo = bo.reshape(1, 1); //is 1 x numO Mat
|
||||
}
|
||||
|
||||
void reshapeOutput(std::vector<Mat> &output)
|
||||
{
|
||||
output.resize(produceH ? 2 : 1);
|
||||
int sz0[] = { numTimestamps, numSamples, numO };
|
||||
output[0].create(3, sz0, dtype);
|
||||
if (produceH)
|
||||
{
|
||||
int sz1[] = { numTimestamps, numSamples, numH };
|
||||
output[1].create(3, sz1, dtype);
|
||||
}
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &input, std::vector<Mat> &output, std::vector<Mat> &internals)
|
||||
{
|
||||
Mat xTs = input[0]->reshape(1, numSamplesTotal);
|
||||
Mat oTs = output[0].reshape(1, numSamplesTotal);
|
||||
Mat hTs = produceH ? output[1].reshape(1, numSamplesTotal) : Mat();
|
||||
Mat hCurr = internals[0];
|
||||
Mat hPrev = internals[1];
|
||||
Mat dummyBiasOnes = internals[2];
|
||||
|
||||
hPrev.setTo(0.);
|
||||
dummyBiasOnes.setTo(1.);
|
||||
|
||||
for (int ts = 0; ts < numTimestamps; ts++)
|
||||
{
|
||||
Range curRowRange = Range(ts * numSamples, (ts + 1) * numSamples);
|
||||
Mat xCurr = xTs.rowRange(curRowRange);
|
||||
|
||||
gemm(hPrev, Whh, 1, hCurr, 0, hCurr, GEMM_2_T); // W_{hh} * h_{prev}
|
||||
gemm(xCurr, Wxh, 1, hCurr, 1, hCurr, GEMM_2_T); //+W_{xh} * x_{curr}
|
||||
gemm(dummyBiasOnes, bh, 1, hCurr, 1, hCurr); //+bh
|
||||
tanh(hCurr, hPrev);
|
||||
|
||||
Mat oCurr = oTs.rowRange(curRowRange);
|
||||
gemm(hPrev, Who, 1, oCurr, 0, oCurr, GEMM_2_T); // W_{ho} * h_{prev}
|
||||
gemm(dummyBiasOnes, bo, 1, oCurr, 1, oCurr); //+b_o
|
||||
tanh(oCurr, oCurr);
|
||||
|
||||
if (produceH)
|
||||
hPrev.copyTo(hTs.rowRange(curRowRange));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CV_EXPORTS_W Ptr<RNNLayer> RNNLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<RNNLayer>(new RNNLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
247
modules/dnn/src/layers/reshape_layer.cpp
Normal file
247
modules/dnn/src/layers/reshape_layer.cpp
Normal file
@ -0,0 +1,247 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
static void computeShapeByReshapeMask(const MatShape &srcShape,
|
||||
const MatShape &maskShape,
|
||||
Range srcRange /*= Range::all()*/,
|
||||
MatShape& dstShape)
|
||||
{
|
||||
int srcShapeSize = (int)srcShape.size();
|
||||
int maskShapeSize = (int)maskShape.size();
|
||||
|
||||
if (srcRange == Range::all())
|
||||
srcRange = Range(0, srcShapeSize);
|
||||
else
|
||||
{
|
||||
int sz = srcRange.size();
|
||||
srcRange.start = clamp(srcRange.start, srcShapeSize);
|
||||
srcRange.end = srcRange.end == INT_MAX ? srcShapeSize : srcRange.start + sz;
|
||||
}
|
||||
|
||||
bool explicitMask = !maskShape.empty(); // All mask values are positive.
|
||||
for (int i = 0, n = maskShape.size(); i < n && explicitMask; ++i)
|
||||
{
|
||||
explicitMask = maskShape[i] > 0;
|
||||
}
|
||||
// Working range of source shape is a range where area(src) == area(mask).
|
||||
if (explicitMask)
|
||||
{
|
||||
int maskTotal = total(maskShape);
|
||||
for (int i = srcRange.start + 1; i < srcRange.end; ++i)
|
||||
{
|
||||
if (total(srcShape, i, srcRange.end) != maskTotal)
|
||||
{
|
||||
srcRange.start = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CV_Assert(total(srcShape, srcRange.start, srcRange.end) == maskTotal);
|
||||
}
|
||||
|
||||
CV_Assert(0 <= srcRange.start && srcRange.start <= srcRange.end && srcRange.end <= srcShapeSize);
|
||||
int dstShapeSize = srcShapeSize - srcRange.size() + maskShapeSize;
|
||||
dstShape.resize(dstShapeSize);
|
||||
|
||||
std::copy(srcShape.begin(), srcShape.begin() + srcRange.start, dstShape.begin());
|
||||
std::copy(srcShape.begin() + srcRange.end, srcShape.begin() + srcShapeSize, dstShape.begin() + srcRange.start + maskShapeSize);
|
||||
|
||||
int inferDim = -1;
|
||||
for (int i = 0; i < maskShapeSize; i++)
|
||||
{
|
||||
if (maskShape[i] > 0)
|
||||
{
|
||||
dstShape[srcRange.start + i] = maskShape[i];
|
||||
}
|
||||
else if (maskShape[i] == 0)
|
||||
{
|
||||
if (srcRange.start + i >= srcShapeSize)
|
||||
CV_Error(Error::StsBadArg, format("Copy dim[%d] (which has zero size) is out of the source shape bounds", srcRange.start + i));
|
||||
dstShape[srcRange.start + i] = srcShape[srcRange.start + i];
|
||||
}
|
||||
else if (maskShape[i] == -1)
|
||||
{
|
||||
if (inferDim != -1)
|
||||
CV_Error(Error::StsAssert, "Duplicate of inferred dim (which is denoted by -1)");
|
||||
inferDim = srcRange.start + i;
|
||||
dstShape[inferDim] = 1;
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsBadArg, "maskShape[i] >= -1");
|
||||
}
|
||||
|
||||
size_t srcTotal = total(srcShape);
|
||||
size_t dstTotal = total(dstShape);
|
||||
|
||||
if (inferDim != -1)
|
||||
{
|
||||
if (srcTotal % dstTotal != 0)
|
||||
CV_Error(Error::StsBackTrace, "Can't infer a dim denoted by -1");
|
||||
|
||||
dstShape[inferDim] = (int)(srcTotal / dstTotal);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(srcTotal == dstTotal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ReshapeLayerImpl : public ReshapeLayer
|
||||
{
|
||||
public:
|
||||
ReshapeLayerImpl(const LayerParams& params):
|
||||
performReordering(false)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
int axis = params.get<int>("axis", 0);
|
||||
int numAxes = params.get<int>("num_axes", -1);
|
||||
enableReordering = params.get<bool>("reorder_dims", false);
|
||||
CV_Assert(numAxes >= -1);
|
||||
newShapeRange = (numAxes == -1) ? Range(axis, INT_MAX) : Range(axis, axis + numAxes);
|
||||
|
||||
newShapeDesc.clear();
|
||||
if (params.has("dim"))
|
||||
{
|
||||
const DictValue ¶mShape = params.get("dim");
|
||||
int i, dims = paramShape.size();
|
||||
newShapeDesc.resize(dims);
|
||||
for (i = 0; i < dims; i++)
|
||||
newShapeDesc[i] = paramShape.get<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
outputs.clear();
|
||||
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
outputs.push_back(MatShape());
|
||||
computeShapeByReshapeMask(inputs[i], newShapeDesc, newShapeRange, outputs.back());
|
||||
}
|
||||
internals = outputs;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void finalize(const std::vector<Mat*> &inputs, std::vector<Mat> &outputs)
|
||||
{
|
||||
CV_Assert(inputs.size());
|
||||
CV_Assert(outputs.size());
|
||||
Mat srcBlob = *inputs[0];
|
||||
int dims = srcBlob.dims;
|
||||
MatShape inputShape = shape(srcBlob), outShape = shape(outputs[0]);
|
||||
|
||||
// input.total() == output.total(). So if reordering is require,
|
||||
// one of the sizes will be are not equal.
|
||||
// Example where reordering is require: from 1x128x4x4 to 1x2048
|
||||
// Example where reordering is NOT require: from 1x1024x1x1 to 1x1024.
|
||||
bool reorderingRequire = false;
|
||||
const int minDims = min(dims, (int)outShape.size());
|
||||
for (int i = 0; !reorderingRequire && i < minDims; ++i)
|
||||
reorderingRequire = inputShape[i] != outShape[i];
|
||||
performReordering = enableReordering && reorderingRequire;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
Mat srcBlob = *inputs[i];
|
||||
MatShape inputShape = shape(srcBlob), outShape = shape(outputs[i]);
|
||||
|
||||
if (performReordering)
|
||||
{
|
||||
float *dstData = internals[i].ptr<float>();
|
||||
const float *srcData = srcBlob.ptr<float>();
|
||||
|
||||
int num = inputShape[0], channels = inputShape[1], height = inputShape[2], width = inputShape[3];
|
||||
int total = num*channels*height*width;
|
||||
for(int i_n = 0; i_n < num; i_n++) {
|
||||
for(int i_c = 0; i_c < channels; i_c++) {
|
||||
for(int i_h = 0; i_h < height; i_h++) {
|
||||
for(int i_w = 0; i_w < width; i_w++) {
|
||||
int src_i = channels*height*width*i_n + height*width*i_c + width*i_h + i_w;
|
||||
int dst_i = channels*height*width*i_n + i_c + channels*width*i_h + channels*i_w;
|
||||
|
||||
CV_Assert(dst_i < total);
|
||||
CV_Assert(src_i < total);
|
||||
|
||||
dstData[dst_i] = srcData[src_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
internals[i].copyTo(outputs[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outputs[i].data != srcBlob.data)
|
||||
srcBlob.reshape(1, outShape).copyTo(outputs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::vector<int> > outShapes;
|
||||
bool enableReordering, performReordering;
|
||||
};
|
||||
|
||||
Ptr<ReshapeLayer> ReshapeLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<ReshapeLayer>(new ReshapeLayerImpl(params));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
147
modules/dnn/src/layers/scale_layer.cpp
Normal file
147
modules/dnn/src/layers/scale_layer.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2016, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
/*
|
||||
Implementation of Scale layer.
|
||||
*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class ScaleLayerImpl : public ScaleLayer
|
||||
{
|
||||
public:
|
||||
ScaleLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
hasBias = params.get<bool>("bias_term", false);
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide();
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
CV_Assert(blobs.size() == 1 + hasBias);
|
||||
|
||||
for (size_t ii = 0; ii < outputs.size(); ii++)
|
||||
{
|
||||
Mat &inpBlob = *inputs[ii];
|
||||
Mat &outBlob = outputs[ii];
|
||||
|
||||
CV_Assert(inpBlob.size[1] == blobs[0].total());
|
||||
if (hasBias)
|
||||
CV_Assert(inpBlob.size[1] == blobs[1].total());
|
||||
|
||||
CV_Assert(inpBlob.type() == CV_32F && outBlob.type() == CV_32F);
|
||||
|
||||
for( int cn = 0; cn < inpBlob.size[0]; cn++ )
|
||||
{
|
||||
for (int n = 0; n < inpBlob.size[1]; n++)
|
||||
{
|
||||
float w = blobs[0].at<float>(n);
|
||||
float b = hasBias ? blobs[1].at<float>(n) : 0;
|
||||
Mat outBlobPlane = getPlane(outBlob, cn, n);
|
||||
Mat inpBlobPlane = getPlane(inpBlob, cn, n);
|
||||
inpBlobPlane.convertTo(outBlobPlane, CV_32F, w, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> tryAttach(const Ptr<BackendNode>& node)
|
||||
{
|
||||
switch (node->backendId)
|
||||
{
|
||||
case DNN_BACKEND_HALIDE:
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
auto base = node.dynamicCast<HalideBackendNode>();
|
||||
Halide::Func& input = base->funcs.back();
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = attachHalide(input(x, y, c, n));
|
||||
return Ptr<BackendNode>(new HalideBackendNode(base, top));
|
||||
#endif // HAVE_HALIDE
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
Halide::Buffer<float> input = halideBuffer(inputs[0]);
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = attachHalide(input(x, y, c, n));
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
// attachHalide can work both with Halide::Buffer and Halide::Func. In the
|
||||
// second case it will be a fusion.
|
||||
Halide::Func attachHalide(const Halide::Expr& input)
|
||||
{
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
|
||||
const int numChannels = blobs[0].total();
|
||||
|
||||
auto weights = wrapToHalideBuffer(blobs[0], {numChannels});
|
||||
Halide::Expr topExpr = input * weights(c);
|
||||
if (hasBias)
|
||||
{
|
||||
auto bias = wrapToHalideBuffer(blobs[1], {numChannels});
|
||||
topExpr += bias(c);
|
||||
}
|
||||
top(x, y, c, n) = topExpr;
|
||||
return top;
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)outputs; // suppress unused variable warning
|
||||
long flops = 0;
|
||||
for(int i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
flops += 2*total(inputs[i]);
|
||||
}
|
||||
return flops;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Ptr<ScaleLayer> ScaleLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<ScaleLayer>(new ScaleLayerImpl(params));
|
||||
}
|
||||
|
||||
} // namespace dnn
|
||||
} // namespace cv
|
96
modules/dnn/src/layers/shift_layer.cpp
Normal file
96
modules/dnn/src/layers/shift_layer.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2016, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
/*
|
||||
Implementation of shift layer, which adds up const values to blob.
|
||||
*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class ShiftLayerImpl : public ShiftLayer
|
||||
{
|
||||
public:
|
||||
ShiftLayerImpl(const LayerParams ¶ms)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
CV_Assert(blobs.size() == 1);
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
|
||||
internals.assign(1, shape(1, total(inputs[0], 2)));
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
CV_Assert(inputs.size() > 0);
|
||||
CV_Assert(blobs.size() > 0);
|
||||
|
||||
if(inputs[0]->dims == blobs[0].dims)
|
||||
{
|
||||
for (size_t ii = 0; ii < outputs.size(); ii++)
|
||||
{
|
||||
Mat &inpBlob = *inputs[ii];
|
||||
Mat &outBlob = outputs[ii];
|
||||
|
||||
outBlob = inpBlob + blobs[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat biasOnesMat = internals[0];
|
||||
biasOnesMat.setTo(1);
|
||||
for (size_t ii = 0; ii < outputs.size(); ii++)
|
||||
{
|
||||
Mat &inpBlob = *inputs[ii];
|
||||
Mat &outBlob = outputs[ii];
|
||||
|
||||
inpBlob.copyTo(outBlob);
|
||||
|
||||
for (int n = 0; n < inpBlob.size[0]; n++)
|
||||
{
|
||||
Mat dstMat(inpBlob.size[1], inpBlob.size[2] * inpBlob.size[3],
|
||||
outBlob.type(), outBlob.ptr(n));
|
||||
gemm(blobs[0], biasOnesMat, 1, dstMat, 1, dstMat); //TODO: gemv
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)outputs; // suppress unused variable warning
|
||||
long flops = 0;
|
||||
|
||||
for(int i= 0; i < inputs.size(); i++)
|
||||
{
|
||||
flops += total(inputs[i]);
|
||||
}
|
||||
|
||||
return flops;
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<ShiftLayer> ShiftLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<ShiftLayer>(new ShiftLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
140
modules/dnn/src/layers/slice_layer.cpp
Normal file
140
modules/dnn/src/layers/slice_layer.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class SliceLayerImpl : public SliceLayer
|
||||
{
|
||||
public:
|
||||
SliceLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
axis = params.get<int>("axis", 1);
|
||||
|
||||
if (params.has("slice_point"))
|
||||
{
|
||||
const DictValue &indicesValue = params.get("slice_point");
|
||||
int i, n = indicesValue.size();
|
||||
sliceIndices.resize(n);
|
||||
for (i = 0; i < n; i++)
|
||||
sliceIndices[i] = indicesValue.get<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() == 1);
|
||||
|
||||
outputs.clear();
|
||||
|
||||
MatShape inpShape = inputs[0];
|
||||
int cAxis = clamp(axis, inpShape.size());
|
||||
int axisSize = inpShape[cAxis];
|
||||
|
||||
if (sliceIndices.size()) //divide blob with respect to passed parameters
|
||||
{
|
||||
std::vector<int> outAxisSize;
|
||||
int prevSlice = 0;
|
||||
|
||||
for (size_t i = 0; i < sliceIndices.size(); i++)
|
||||
{
|
||||
if (!(prevSlice < sliceIndices[i] && sliceIndices[i] < axisSize))
|
||||
CV_Error(Error::StsBadArg, "Slice indices should be positive, increased and don't exceed size of sliced dimension");
|
||||
|
||||
outAxisSize.push_back(sliceIndices[i] - prevSlice);
|
||||
prevSlice = sliceIndices[i];
|
||||
}
|
||||
outAxisSize.push_back(axisSize - prevSlice);
|
||||
|
||||
for (size_t i = 0; i < outAxisSize.size(); i++)
|
||||
{
|
||||
inpShape[cAxis] = outAxisSize[i];
|
||||
outputs.push_back(inpShape);
|
||||
}
|
||||
}
|
||||
else //divide blob with respect to count of output blobs
|
||||
{
|
||||
CV_Assert(requiredOutputs > 0 && axisSize % requiredOutputs == 0);
|
||||
int outAxisSize = axisSize / (int)requiredOutputs;
|
||||
|
||||
for (size_t i = 0; i < requiredOutputs; i++)
|
||||
{
|
||||
inpShape[cAxis] = outAxisSize;
|
||||
outputs.push_back(inpShape);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
const Mat& inpMat = *inputs[0];
|
||||
std::vector<Range> ranges(inpMat.dims, Range::all());
|
||||
int cAxis = clamp(axis, inpMat.dims);
|
||||
|
||||
ranges[cAxis].start = 0;
|
||||
for (size_t i = 0; i < outputs.size(); i++)
|
||||
{
|
||||
ranges[cAxis].end = ranges[cAxis].start + outputs[i].size[cAxis];
|
||||
inpMat(&ranges[0]).copyTo(outputs[i]);
|
||||
ranges[cAxis].start = ranges[cAxis].end;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<SliceLayer> SliceLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<SliceLayer>(new SliceLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
213
modules/dnn/src/layers/softmax_layer.cpp
Normal file
213
modules/dnn/src/layers/softmax_layer.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include <algorithm>
|
||||
#include <stdlib.h>
|
||||
using std::max;
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class SoftMaxLayerImpl : public SoftmaxLayer
|
||||
{
|
||||
public:
|
||||
|
||||
SoftMaxLayerImpl(const LayerParams& params)
|
||||
{
|
||||
axisRaw = params.get<int>("axis", 1);
|
||||
logSoftMax = params.get<int>("log_softmax", false);
|
||||
setParamsFrom(params);
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
bool inplace = Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
|
||||
MatShape shape = inputs[0];
|
||||
int cAxis = clamp(axisRaw, shape.size());
|
||||
shape[cAxis] = 1;
|
||||
internals.assign(1, shape);
|
||||
return inplace;
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId)
|
||||
{
|
||||
return backendId == DNN_BACKEND_DEFAULT ||
|
||||
backendId == DNN_BACKEND_HALIDE && haveHalide() && axisRaw == 1;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
const Mat &src = *inputs[0];
|
||||
Mat &dst = outputs[0];
|
||||
|
||||
int axis = clamp(axisRaw, src.dims);
|
||||
size_t outerSize = src.total(0, axis), channels = src.size[axis],
|
||||
innerSize = src.total(axis + 1);
|
||||
|
||||
CV_Assert(src.type() == CV_32F);
|
||||
CV_Assert(src.isContinuous() && dst.isContinuous());
|
||||
|
||||
const float *srcPtr = src.ptr<float>();
|
||||
float *dstPtr = dst.ptr<float>();
|
||||
float *bufPtr = internals[0].ptr<float>();
|
||||
|
||||
size_t outerStep = src.total(axis);
|
||||
size_t cnStep = src.total(axis + 1);
|
||||
|
||||
//compute max along axis
|
||||
for (size_t outerDim = 0; outerDim < outerSize; outerDim++)
|
||||
{
|
||||
size_t srcOffset = outerDim * outerStep;
|
||||
size_t bufOffset = outerDim * cnStep;
|
||||
|
||||
memcpy(bufPtr + bufOffset, srcPtr + srcOffset, innerSize * sizeof(float));
|
||||
|
||||
for (size_t cnDim = 1; cnDim < channels; cnDim++)
|
||||
{
|
||||
for (size_t i = 0; i < innerSize; i++)
|
||||
bufPtr[bufOffset + i] = std::max(bufPtr[bufOffset + i], srcPtr[srcOffset + cnDim * cnStep + i]);
|
||||
}
|
||||
}
|
||||
|
||||
//subtract max
|
||||
for (size_t outerDim = 0; outerDim < outerSize; outerDim++)
|
||||
{
|
||||
size_t srcOffset = outerDim * outerStep;
|
||||
size_t bufOffset = outerDim * cnStep;
|
||||
|
||||
for (size_t cnDim = 0; cnDim < channels; cnDim++)
|
||||
{
|
||||
for (size_t i = 0; i < innerSize; i++)
|
||||
dstPtr[srcOffset + cnDim * cnStep + i] = srcPtr[srcOffset + cnDim * cnStep + i] - bufPtr[bufOffset + i];
|
||||
}
|
||||
}
|
||||
|
||||
cv::exp(dst, dst);
|
||||
|
||||
for (size_t outerDim = 0; outerDim < outerSize; outerDim++)
|
||||
{
|
||||
size_t srcOffset = outerDim * outerStep;
|
||||
size_t bufOffset = outerDim * cnStep;
|
||||
|
||||
//sum exp along axis
|
||||
for (size_t i = 0; i < innerSize; i++)
|
||||
bufPtr[bufOffset + i] = 0.f;
|
||||
|
||||
for (size_t cnDim = 0; cnDim < channels; cnDim++)
|
||||
{
|
||||
for (size_t i = 0; i < innerSize; i++)
|
||||
bufPtr[bufOffset + i] += dstPtr[srcOffset + cnDim * cnStep + i];
|
||||
}
|
||||
|
||||
//divide by computed sum
|
||||
for (size_t cnDim = 0; cnDim < channels; cnDim++)
|
||||
{
|
||||
for (size_t i = 0; i < innerSize; i++)
|
||||
dstPtr[srcOffset + cnDim * cnStep + i] /= bufPtr[bufOffset + i];
|
||||
}
|
||||
if (logSoftMax)
|
||||
{
|
||||
for (size_t cnDim = 0; cnDim < channels; cnDim++)
|
||||
{
|
||||
for (size_t i = 0; i < innerSize; i++)
|
||||
dstPtr[srcOffset + cnDim * cnStep + i] = log(dstPtr[srcOffset + cnDim * cnStep + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
|
||||
int inW, inH, inC, inN;
|
||||
getCanonicalSize(inputBuffer, &inW, &inH, &inC, &inN);
|
||||
|
||||
if (inW != 1 || inH != 1)
|
||||
CV_Error(cv::Error::StsNotImplemented,
|
||||
"Halide backend for SoftMax with spatial size "
|
||||
"more than 1x1 is not implemented");
|
||||
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
|
||||
|
||||
Halide::Func expInput("expInput");
|
||||
Halide::RDom r(0, inW, 0, inH, 0, inC);
|
||||
expInput(x, y, c, n) = exp(inputBuffer(x, y, c, n));
|
||||
Halide::Expr globalSum = sum(expInput(r.x, r.y, r.z, n));
|
||||
top(x, y, c, n) = expInput(x, y, c, n) / globalSum;
|
||||
return Ptr<BackendNode>(new HalideBackendNode(top));
|
||||
#endif // HAVE_HALIDE
|
||||
return Ptr<BackendNode>();
|
||||
}
|
||||
|
||||
int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const
|
||||
{
|
||||
(void)outputs; // suppress unused variable warning
|
||||
int64 flops = 0;
|
||||
|
||||
for (int i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
flops += 4*total(inputs[i]);
|
||||
}
|
||||
|
||||
return flops;
|
||||
}
|
||||
|
||||
int axisRaw;
|
||||
};
|
||||
|
||||
Ptr<SoftmaxLayer> SoftmaxLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<SoftmaxLayer>(new SoftMaxLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
97
modules/dnn/src/layers/split_layer.cpp
Normal file
97
modules/dnn/src/layers/split_layer.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
class SplitLayerImpl : public SplitLayer
|
||||
{
|
||||
public:
|
||||
SplitLayerImpl(const LayerParams ¶ms)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
//TODO: maybe "top_count" param is useless because it can be determined by output connections number
|
||||
if (params.has("top_count"))
|
||||
{
|
||||
outputsCount = params.get<int>("top_count");
|
||||
CV_Assert(outputsCount >= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputsCount = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape> &inputs,
|
||||
const int requiredOutputs,
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const
|
||||
{
|
||||
CV_Assert(inputs.size() == 1);
|
||||
|
||||
Layer::getMemoryShapes(inputs, max(1, outputsCount >= 0 ? outputsCount : requiredOutputs),
|
||||
outputs, internals);
|
||||
return true;
|
||||
}
|
||||
|
||||
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
|
||||
{
|
||||
for (size_t i = 0; i < outputs.size(); i++)
|
||||
{
|
||||
CV_Assert(inputs[0]->total() == outputs[i].total());
|
||||
if (outputs[i].data != inputs[0]->data)
|
||||
inputs[0]->copyTo(outputs[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<SplitLayer> SplitLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<SplitLayer>(new SplitLayerImpl(params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
206
modules/dnn/src/op_halide.cpp
Normal file
206
modules/dnn/src/op_halide.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "op_halide.hpp"
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
#include <HalideRuntimeOpenCL.h>
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
Halide::Buffer<float> wrapToHalideBuffer(const Mat& mat)
|
||||
{
|
||||
int n, c, w, h;
|
||||
getCanonicalSize(mat.size, &w, &h, &c, &n);
|
||||
return wrapToHalideBuffer(mat, {w, h, c, n});
|
||||
}
|
||||
|
||||
Halide::Buffer<float> wrapToHalideBuffer(const Mat& mat,
|
||||
const std::vector<int>& sizes)
|
||||
{
|
||||
Halide::Buffer<float> buffer((float*)mat.data, sizes);
|
||||
buffer.set_host_dirty(); // Indicate that data is on CPU.
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Halide::Buffer<> halideBuffer(const Ptr<BackendWrapper>& ptr)
|
||||
{
|
||||
CV_Assert(!ptr.empty());
|
||||
return ptr.dynamicCast<HalideBackendWrapper>()->buffer;
|
||||
}
|
||||
|
||||
std::vector<Halide::Buffer<> > halideBuffers(const std::vector<Ptr<BackendWrapper> >& ptrs)
|
||||
{
|
||||
std::vector<Halide::Buffer<> > vec;
|
||||
vec.reserve(ptrs.size());
|
||||
for (const Ptr<BackendWrapper>& ptr : ptrs)
|
||||
{
|
||||
vec.push_back(halideBuffer(ptr));
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
void getCanonicalSize(const Halide::Buffer<>& buffer, int* width, int* height,
|
||||
int* channels, int* batch)
|
||||
{
|
||||
CV_Assert(buffer.dimensions() == 4);
|
||||
*width = buffer.extent(0);
|
||||
*height = buffer.extent(1);
|
||||
*channels = buffer.extent(2);
|
||||
*batch = buffer.extent(3);
|
||||
}
|
||||
|
||||
HalideBackendNode::HalideBackendNode(const Halide::Func& func)
|
||||
: BackendNode(DNN_BACKEND_HALIDE), funcs(1, func) {}
|
||||
|
||||
HalideBackendNode::HalideBackendNode(const std::vector<Halide::Func>& funcs)
|
||||
: BackendNode(DNN_BACKEND_HALIDE), funcs(funcs) {}
|
||||
|
||||
HalideBackendNode::HalideBackendNode(const Ptr<HalideBackendNode>& base,
|
||||
const Halide::Func& top)
|
||||
: BackendNode(DNN_BACKEND_HALIDE), funcs(base->funcs)
|
||||
{
|
||||
funcs.back() = top;
|
||||
}
|
||||
|
||||
HalideBackendWrapper::HalideBackendWrapper(int targetId, const cv::Mat& m)
|
||||
: BackendWrapper(DNN_BACKEND_HALIDE, targetId)
|
||||
{
|
||||
buffer = wrapToHalideBuffer(m);
|
||||
if (targetId == DNN_TARGET_CPU)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (targetId == DNN_TARGET_OPENCL)
|
||||
{
|
||||
buffer.copy_to_device(halide_opencl_device_interface());
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsNotImplemented, "Unknown target identifier");
|
||||
}
|
||||
|
||||
HalideBackendWrapper::HalideBackendWrapper(const Ptr<BackendWrapper>& base,
|
||||
const MatShape& shape)
|
||||
: BackendWrapper(DNN_BACKEND_HALIDE, base->targetId)
|
||||
{
|
||||
int w, h, c, n;
|
||||
getCanonicalSize(shape, &w, &h, &c, &n);
|
||||
Halide::Buffer<float> baseBuffer = halideBuffer(base);
|
||||
buffer = Halide::Buffer<float>((float*)baseBuffer.raw_buffer()->host,
|
||||
{w, h, c, n});
|
||||
if (baseBuffer.has_device_allocation())
|
||||
{
|
||||
buffer.raw_buffer()->device = baseBuffer.raw_buffer()->device;
|
||||
buffer.raw_buffer()->device_interface = baseBuffer.raw_buffer()->device_interface;
|
||||
buffer.set_device_dirty();
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.set_host_dirty(); // Indicate that data is on CPU.
|
||||
CV_Assert(targetId == DNN_TARGET_CPU);
|
||||
}
|
||||
}
|
||||
|
||||
void HalideBackendWrapper::copyToHost()
|
||||
{
|
||||
CV_Assert(targetId == DNN_TARGET_CPU || buffer.device_dirty());
|
||||
if (buffer.device_dirty())
|
||||
{
|
||||
buffer.device_sync();
|
||||
buffer.copy_to_host();
|
||||
}
|
||||
}
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
void getCanonicalSize(const MatSize& size, int* width, int* height,
|
||||
int* channels, int* batch)
|
||||
{
|
||||
const int dims = size.p[-1];
|
||||
CV_Assert(dims == 2 || dims == 4);
|
||||
*batch = size[0];
|
||||
*channels = size[1];
|
||||
if (dims == 4)
|
||||
{
|
||||
*width = size[3];
|
||||
*height = size[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
*width = 1;
|
||||
*height = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void getCanonicalSize(const MatShape& shape, int* width, int* height,
|
||||
int* channels, int* batch)
|
||||
{
|
||||
const int dims = shape.size();
|
||||
CV_Assert(dims == 2 || dims == 4);
|
||||
*batch = shape[0];
|
||||
*channels = shape[1];
|
||||
if (dims == 4)
|
||||
{
|
||||
*width = shape[3];
|
||||
*height = shape[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
*width = 1;
|
||||
*height = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void compileHalide(std::vector<Mat> &outputs, Ptr<BackendNode>& node, int targetId)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
CV_Assert(!node.empty());
|
||||
Halide::Func& top = node.dynamicCast<HalideBackendNode>()->funcs.back();
|
||||
|
||||
int outW, outH, outC, outN;
|
||||
Halide::Var x("x"), y("y"), c("c"), n("n");
|
||||
getCanonicalSize(outputs[0].size, &outW, &outH, &outC, &outN);
|
||||
top.bound(x, 0, outW).bound(y, 0, outH)
|
||||
.bound(c, 0, outC).bound(n, 0, outN);
|
||||
|
||||
Halide::Target target = Halide::get_host_target();
|
||||
target.set_feature(Halide::Target::NoAsserts);
|
||||
if (targetId == DNN_TARGET_OPENCL)
|
||||
{
|
||||
target.set_feature(Halide::Target::OpenCL);
|
||||
}
|
||||
CV_Assert(target.supported());
|
||||
top.compile_jit(target);
|
||||
#endif // HAVE_HALIDE
|
||||
}
|
||||
|
||||
void forwardHalide(std::vector<Ptr<BackendWrapper> > &outputs,
|
||||
const Ptr<BackendNode>& node)
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
CV_Assert(!node.empty());
|
||||
Halide::Func& top = node.dynamicCast<HalideBackendNode>()->funcs.back();
|
||||
auto outputBuffers = halideBuffers(outputs);
|
||||
top.realize(Halide::Realization(outputBuffers));
|
||||
#endif // HAVE_HALIDE
|
||||
}
|
||||
|
||||
bool haveHalide()
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif // HAVE_HALIDE
|
||||
}
|
||||
|
||||
} // namespace dnn
|
||||
} // namespace cv
|
84
modules/dnn/src/op_halide.hpp
Normal file
84
modules/dnn/src/op_halide.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#ifndef __OPENCV_DNN_OP_HALIDE_HPP__
|
||||
#define __OPENCV_DNN_OP_HALIDE_HPP__
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#ifdef HAVE_HALIDE
|
||||
#include <Halide.h>
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace dnn
|
||||
{
|
||||
#ifdef HAVE_HALIDE
|
||||
// Returns four-dimensional buffer with float32 type that wrap cv::Mat data.
|
||||
// No data copy here.
|
||||
Halide::Buffer<float> wrapToHalideBuffer(const Mat& mat);
|
||||
|
||||
Halide::Buffer<float> wrapToHalideBuffer(const Mat& mat,
|
||||
const std::vector<int>& shape);
|
||||
|
||||
// Extract batch size, number of channels, width and height from buffer.
|
||||
void getCanonicalSize(const Halide::Buffer<>& buffer, int* width, int* height,
|
||||
int* channels, int* batch);
|
||||
|
||||
// Cast pointer and create copy of Halide buffer. No data copy.
|
||||
Halide::Buffer<> halideBuffer(const Ptr<BackendWrapper>& ptr);
|
||||
|
||||
std::vector<Halide::Buffer<> > halideBuffers(const std::vector<Ptr<BackendWrapper> >& ptrs);
|
||||
|
||||
class HalideBackendNode : public BackendNode
|
||||
{
|
||||
public:
|
||||
HalideBackendNode(const Halide::Func& func);
|
||||
|
||||
HalideBackendNode(const std::vector<Halide::Func>& funcs);
|
||||
|
||||
// Initialize from the <base> node but replace last function to <top>.
|
||||
// It's using in case of layers fusing when we want to keep functions of
|
||||
// root layer but replace top by fused one (i.e. conv+padding to relu+padding).
|
||||
HalideBackendNode(const Ptr<HalideBackendNode>& base, const Halide::Func& top);
|
||||
|
||||
std::vector<Halide::Func> funcs;
|
||||
};
|
||||
|
||||
class HalideBackendWrapper : public BackendWrapper
|
||||
{
|
||||
public:
|
||||
HalideBackendWrapper(int targetId, const cv::Mat& m);
|
||||
|
||||
HalideBackendWrapper(const Ptr<BackendWrapper>& base, const MatShape& shape);
|
||||
|
||||
virtual void copyToHost();
|
||||
|
||||
Halide::Buffer<float> buffer;
|
||||
};
|
||||
#endif // HAVE_HALIDE
|
||||
|
||||
// Extract batch size, number of channels, width and height from MatSize.
|
||||
void getCanonicalSize(const MatSize& size, int* width, int* height,
|
||||
int* channels, int* batch);
|
||||
|
||||
void getCanonicalSize(const MatShape& shape, int* width, int* height,
|
||||
int* channels, int* batch);
|
||||
|
||||
// Realize Halide pipeline into output blobs.
|
||||
void forwardHalide(std::vector<Ptr<BackendWrapper> > &outputs,
|
||||
const Ptr<BackendNode>& node);
|
||||
|
||||
// Compile Halide pipeline to specific target. Use outputs to set bounds of functions.
|
||||
void compileHalide(std::vector<Mat> &outputs, Ptr<BackendNode>& node, int targetId);
|
||||
|
||||
bool haveHalide();
|
||||
} // namespace dnn
|
||||
} // namespace cv
|
||||
|
||||
#endif // __OPENCV_DNN_OP_HALIDE_HPP__
|
44
modules/dnn/src/opencl/activations.cl
Normal file
44
modules/dnn/src/opencl/activations.cl
Normal file
@ -0,0 +1,44 @@
|
||||
__kernel void ReLUForward(const int count, __global const T* in, __global T* out
|
||||
#ifndef RELU_NO_SLOPE
|
||||
, T negative_slope
|
||||
#endif
|
||||
) {
|
||||
int index = get_global_id(0);
|
||||
if(index < count)
|
||||
#ifndef RELU_NO_SLOPE
|
||||
out[index] = in[index] > 0 ? in[index] : in[index] * negative_slope;
|
||||
#else
|
||||
out[index] = in[index] > 0 ? in[index] : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
__kernel void TanHForward(const int count, __global T* in, __global T* out) {
|
||||
int index = get_global_id(0);
|
||||
if(index < count)
|
||||
out[index] = tanh(in[index]);
|
||||
}
|
||||
|
||||
__kernel void SigmoidForward(const int count, __global const T* in, __global T* out) {
|
||||
int index = get_global_id(0);
|
||||
if(index < count)
|
||||
out[index] = 1. / (1. + exp(-in[index]));
|
||||
}
|
||||
|
||||
__kernel void BNLLForward(const int n, __global const T* in, __global T* out) {
|
||||
int index = get_global_id(0);
|
||||
if (index < n) {
|
||||
out[index] = in[index] > 0 ? in[index] + log(1. + exp(-in[index])) : log(1. + exp(in[index]));
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void AbsValForward(const int n, __global const T* in, __global T* out) {
|
||||
int index = get_global_id(0);
|
||||
if (index < n)
|
||||
out[index] = fabs(in[index]);
|
||||
}
|
||||
|
||||
__kernel void PowForward(const int n, __global const T* in, __global T* out, const T power, const T scale, const T shift) {
|
||||
int index = get_global_id(0);
|
||||
if (index < n)
|
||||
out[index] = pow(shift + scale * in[index], power);
|
||||
}
|
62
modules/dnn/src/opencl/col2im.cl
Normal file
62
modules/dnn/src/opencl/col2im.cl
Normal file
@ -0,0 +1,62 @@
|
||||
/*************************************************************************************
|
||||
* Copyright (c) 2015, Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
**************************************************************************************/
|
||||
|
||||
__kernel void col2im(const int n, __global const T* data_col, const int col_offset,
|
||||
const int height, const int width, const int channels,
|
||||
const int patch_h, const int patch_w,
|
||||
const int pad_h, const int pad_w,
|
||||
const int stride_h, const int stride_w,
|
||||
const int height_col, const int width_col,
|
||||
__global T* data_im, const int img_offset)
|
||||
{
|
||||
data_col = data_col + col_offset;
|
||||
data_im = data_im + img_offset;
|
||||
int index = get_global_id(0);
|
||||
if(index < n) {
|
||||
T val = 0;
|
||||
int w = index % width + pad_w;
|
||||
int h = (index / width) % height + pad_h;
|
||||
int c = index / (width * height);
|
||||
|
||||
// compute the start and end of the output
|
||||
int w_col_start = (w < patch_w) ? 0 : (w - patch_w) / stride_w + 1;
|
||||
int w_col_end = min(w / stride_w + 1, width_col);
|
||||
int h_col_start = (h < patch_h) ? 0 : (h - patch_h) / stride_h + 1;
|
||||
int h_col_end = min(h / stride_h + 1, height_col);
|
||||
|
||||
// equivalent implementation
|
||||
int offset =
|
||||
(c * patch_h * patch_w + h * patch_w + w) * height_col * width_col;
|
||||
int coeff_h_col = (1 - stride_h * patch_w * height_col) * width_col;
|
||||
int coeff_w_col = (1 - stride_w * height_col * width_col);
|
||||
for (int h_col = h_col_start; h_col < h_col_end; ++h_col) {
|
||||
for (int w_col = w_col_start; w_col < w_col_end; ++w_col) {
|
||||
val += data_col[offset + h_col * coeff_h_col + w_col * coeff_w_col];
|
||||
}
|
||||
}
|
||||
data_im[index] = val;
|
||||
}
|
||||
}
|
71
modules/dnn/src/opencl/im2col.cl
Normal file
71
modules/dnn/src/opencl/im2col.cl
Normal file
@ -0,0 +1,71 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
__kernel void im2col(__global const T *im_src, int im_src_offset,
|
||||
int channels, int height_inp, int width_inp,
|
||||
int kernel_h, int kernel_w, int pad_h, int pad_w, int stride_h, int stride_w,
|
||||
int height_out, int width_out,
|
||||
__global T *im_col, int im_col_offset
|
||||
)
|
||||
{
|
||||
int index = get_global_id(0);
|
||||
if (index >= height_out * width_out * channels)
|
||||
return;
|
||||
int j_out = index % width_out;
|
||||
int i_out = (index / width_out) % height_out;
|
||||
int c_inp = (index / width_out) / height_out;
|
||||
|
||||
int c_out = c_inp * kernel_h * kernel_w;
|
||||
int i_inp = i_out * stride_h - pad_h;
|
||||
int j_inp = j_out * stride_w - pad_w;
|
||||
|
||||
im_src += (c_inp * height_inp + i_inp) * width_inp + j_inp + im_src_offset;
|
||||
im_col += (c_out * height_out + i_out) * width_out + j_out + im_col_offset;
|
||||
|
||||
for (int ki = 0; ki < kernel_h; ++ki)
|
||||
for (int kj = 0; kj < kernel_w; ++kj) {
|
||||
int i = i_inp + ki;
|
||||
int j = j_inp + kj;
|
||||
*im_col = (i >= 0 && j >= 0 && i < height_inp && j < width_inp) ?
|
||||
im_src[ki * width_inp + kj] : 0;
|
||||
im_col += height_out * width_out;
|
||||
}
|
||||
}
|
76
modules/dnn/src/opencl/lrn.cl
Normal file
76
modules/dnn/src/opencl/lrn.cl
Normal file
@ -0,0 +1,76 @@
|
||||
/*************************************************************************************
|
||||
* Copyright (c) 2015, Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
**************************************************************************************/
|
||||
|
||||
__kernel void LRNComputeOutput(const int nthreads, __global T* in, __global T* scale, const T negative_beta, __global T* out) {
|
||||
int index = get_global_id(0);
|
||||
int tmp = get_global_size(0);
|
||||
for(index; index < nthreads; index += tmp)
|
||||
out[index] = in[index] * pow(scale[index], negative_beta);
|
||||
}
|
||||
|
||||
__kernel void LRNFillScale(const int nthreads, __global T* in, const int num, const int channels, const int height, const int width, const int size, const T alpha_over_size, const T k, __global T* scale) {
|
||||
int index = get_global_id(0);
|
||||
int tmp = get_global_size(0);
|
||||
for(index; index < nthreads; index += tmp) {
|
||||
// find out the local offset
|
||||
const int w = index % width;
|
||||
const int h = (index / width) % height;
|
||||
const int n = index / width / height;
|
||||
const int offset = (n * channels * height + h) * width + w;
|
||||
const int step = height * width;
|
||||
in = in + offset;
|
||||
scale = scale + offset;
|
||||
int head = 0;
|
||||
const int pre_pad = (size - 1) / 2;
|
||||
const int post_pad = size - pre_pad - 1;
|
||||
T accum_scale = 0;
|
||||
// fill the scale at [n, :, h, w]
|
||||
// accumulate values
|
||||
while (head < post_pad && head < channels) {
|
||||
accum_scale += in[head * step] * in[head * step];
|
||||
++head;
|
||||
}
|
||||
// both add and subtract
|
||||
while (head < channels) {
|
||||
accum_scale += in[head * step] * in[head * step];
|
||||
if (head - size >= 0) {
|
||||
accum_scale -= in[(head - size) * step]
|
||||
* in[(head - size) * step];
|
||||
}
|
||||
scale[(head - post_pad) * step] = k + accum_scale * alpha_over_size;
|
||||
++head;
|
||||
}
|
||||
// subtract only
|
||||
while (head < channels + post_pad) {
|
||||
if (head - size >= 0) {
|
||||
accum_scale -= in[(head - size) * step]
|
||||
* in[(head - size) * step];
|
||||
}
|
||||
scale[(head - post_pad) * step] = k + accum_scale * alpha_over_size;
|
||||
++head;
|
||||
}
|
||||
}
|
||||
}
|
106
modules/dnn/src/opencl/pooling.cl
Normal file
106
modules/dnn/src/opencl/pooling.cl
Normal file
@ -0,0 +1,106 @@
|
||||
/*************************************************************************************
|
||||
* Copyright (c) 2015, Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
**************************************************************************************/
|
||||
|
||||
__kernel void MaxPoolForward(const int nthreads,
|
||||
__global T* bottom_data, const int num, const int channels, const int height, const int width,
|
||||
const int pooled_height, const int pooled_width, const int kernel_h, const int kernel_w,
|
||||
const int stride_h, const int stride_w, const int pad_h, const int pad_w,
|
||||
__global T* top_data
|
||||
#ifdef MASK
|
||||
, __global float* mask
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int index = get_global_id(0);
|
||||
int tmp = get_global_size(0);
|
||||
for(index; index < nthreads; index += tmp) {
|
||||
int pw = index % pooled_width;
|
||||
int ph = (index / pooled_width) % pooled_height;
|
||||
int c = (index / pooled_width / pooled_height) % channels;
|
||||
int n = index / pooled_width / pooled_height / channels;
|
||||
int hstart = ph * stride_h - pad_h;
|
||||
int wstart = pw * stride_w - pad_w;
|
||||
const int hend = min(hstart + kernel_h, height);
|
||||
const int wend = min(wstart + kernel_w, width);
|
||||
hstart = max(hstart, 0);
|
||||
wstart = max(wstart, 0);
|
||||
T maxval = -FLT_MAX;
|
||||
int maxidx = -1;
|
||||
bottom_data =
|
||||
bottom_data + (n * channels + c) * height * width;
|
||||
for (int h = hstart; h < hend; ++h) {
|
||||
for (int w = wstart; w < wend; ++w) {
|
||||
if (bottom_data[h * width + w] > maxval) {
|
||||
maxidx = h * width + w;
|
||||
maxval = bottom_data[maxidx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
top_data[index] = maxval;
|
||||
|
||||
#ifdef MASK
|
||||
mask[index] = maxidx;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void AvePoolForward(const int nthreads,
|
||||
__global T* bottom_data, const int num, const int channels, const int height, const int width,
|
||||
const int pooled_height, const int pooled_width, const int kernel_h, const int kernel_w,
|
||||
const int stride_h, const int stride_w, const int pad_h, const int pad_w,
|
||||
__global T* top_data
|
||||
#ifdef MASK
|
||||
, __global float* mask // NOT USED
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int index = get_global_id(0);
|
||||
int tmp = get_global_size(0);
|
||||
for(index; index < nthreads; index+=tmp) {
|
||||
int pw = index % pooled_width;
|
||||
int ph = (index / pooled_width) % pooled_height;
|
||||
int c = (index / pooled_width / pooled_height) % channels;
|
||||
int n = index / pooled_width / pooled_height / channels; int hstart = ph * stride_h - pad_h; int wstart = pw * stride_w - pad_w;
|
||||
int hend = min(hstart + kernel_h, height + pad_h);
|
||||
int wend = min(wstart + kernel_w, width + pad_w);
|
||||
const int pool_size = (hend - hstart) * (wend - wstart);
|
||||
hstart = max(hstart, 0);
|
||||
wstart = max(wstart, 0);
|
||||
hend = min(hend, height);
|
||||
wend = min(wend, width);
|
||||
T aveval = 0;
|
||||
bottom_data =
|
||||
bottom_data + (n * channels + c) * height * width;
|
||||
for (int h = hstart; h < hend; ++h) {
|
||||
for (int w = wstart; w < wend; ++w) {
|
||||
aveval += bottom_data[h * width + w];
|
||||
}
|
||||
}
|
||||
top_data[index] = aveval / pool_size;
|
||||
}
|
||||
|
||||
}
|
75
modules/dnn/src/opencl/softmax.cl
Normal file
75
modules/dnn/src/opencl/softmax.cl
Normal file
@ -0,0 +1,75 @@
|
||||
/*************************************************************************************
|
||||
* Copyright (c) 2015, Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
**************************************************************************************/
|
||||
|
||||
__kernel void kernel_channel_max(const int num, const int channels,
|
||||
const int spatial_dim, __global const T* data, __global T* out) {
|
||||
int index = get_global_id(0);
|
||||
if(index < num * spatial_dim) {
|
||||
int n = index / spatial_dim;
|
||||
int s = index % spatial_dim;
|
||||
T maxval = -FLT_MAX;
|
||||
for (int c = 0; c < channels; ++c) {
|
||||
maxval = max(data[(n * channels + c) * spatial_dim + s], maxval);
|
||||
}
|
||||
out[index] = maxval;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void kernel_channel_subtract(const int count,
|
||||
const int num, const int channels,
|
||||
const int spatial_dim, __global const T* channel_max, __global T* data) {
|
||||
int index = get_global_id(0);
|
||||
if(index < count) {
|
||||
int n = index / channels / spatial_dim;
|
||||
int s = index % spatial_dim;
|
||||
data[index] -= channel_max[n * spatial_dim + s];
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void kernel_channel_sum(const int num, const int channels,
|
||||
const int spatial_dim, __global const T* data, __global T* channel_sum) {
|
||||
int index = get_global_id(0);
|
||||
if(index < num * spatial_dim) {
|
||||
int n = index / spatial_dim;
|
||||
int s = index % spatial_dim;
|
||||
T sum = 0;
|
||||
for (int c = 0; c < channels; ++c) {
|
||||
sum += data[(n * channels + c) * spatial_dim + s];
|
||||
}
|
||||
channel_sum[index] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void kernel_channel_div(const int count,
|
||||
const int num, const int channels,
|
||||
const int spatial_dim, __global const T* channel_sum, __global T* data) {
|
||||
int index = get_global_id(0);
|
||||
if(index < count) {
|
||||
int n = index / channels / spatial_dim;
|
||||
int s = index % spatial_dim;
|
||||
data[index] /= channel_sum[n * spatial_dim + s];
|
||||
}
|
||||
}
|
45
modules/dnn/src/precomp.hpp
Normal file
45
modules/dnn/src/precomp.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include "cvconfig.h"
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <opencv2/dnn/all_layers.hpp>
|
60
modules/dnn/src/tensorflow/attr_value.proto
Normal file
60
modules/dnn/src/tensorflow/attr_value.proto
Normal file
@ -0,0 +1,60 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package tensorflow;
|
||||
option cc_enable_arenas = true;
|
||||
option java_outer_classname = "AttrValueProtos";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "org.tensorflow.framework";
|
||||
|
||||
import "tensor.proto";
|
||||
import "tensor_shape.proto";
|
||||
import "types.proto";
|
||||
|
||||
// Protocol buffer representing the value for an attr used to configure an Op.
|
||||
// Comment indicates the corresponding attr type. Only the field matching the
|
||||
// attr type may be filled.
|
||||
message AttrValue {
|
||||
message ListValue {
|
||||
repeated bytes s = 2; // "list(string)"
|
||||
repeated int64 i = 3 [packed = true]; // "list(int)"
|
||||
repeated float f = 4 [packed = true]; // "list(float)"
|
||||
repeated bool b = 5 [packed = true]; // "list(bool)"
|
||||
repeated DataType type = 6 [packed = true]; // "list(type)"
|
||||
repeated TensorShapeProto shape = 7; // "list(shape)"
|
||||
repeated TensorProto tensor = 8; // "list(tensor)"
|
||||
// TODO(zhifengc/josh11b): implements list(func) if needed.
|
||||
}
|
||||
|
||||
oneof value {
|
||||
bytes s = 2; // "string"
|
||||
int64 i = 3; // "int"
|
||||
float f = 4; // "float"
|
||||
bool b = 5; // "bool"
|
||||
DataType type = 6; // "type"
|
||||
TensorShapeProto shape = 7; // "shape"
|
||||
TensorProto tensor = 8; // "tensor"
|
||||
ListValue list = 1; // any "list(...)"
|
||||
|
||||
// "func" represents a function. func.name is a function's name or
|
||||
// a primitive op's name. func.attr.first is the name of an attr
|
||||
// defined for that function. func.attr.second is the value for
|
||||
// that attr in the instantiation.
|
||||
NameAttrList func = 10;
|
||||
|
||||
// This is a placeholder only used in nodes defined inside a
|
||||
// function. It indicates the attr value will be supplied when
|
||||
// the function is instantiated. For example, let us suppose a
|
||||
// node "N" in function "FN". "N" has an attr "A" with value
|
||||
// placeholder = "foo". When FN is instantiated with attr "foo"
|
||||
// set to "bar", the instantiated node N's attr A will have been
|
||||
// given the value "bar".
|
||||
string placeholder = 9;
|
||||
}
|
||||
}
|
||||
|
||||
// A list of attr names and their values. The whole list is attached
|
||||
// with a string name. E.g., MatMul[T=float].
|
||||
message NameAttrList {
|
||||
string name = 1;
|
||||
map<string, AttrValue> attr = 2;
|
||||
}
|
95
modules/dnn/src/tensorflow/function.proto
Normal file
95
modules/dnn/src/tensorflow/function.proto
Normal file
@ -0,0 +1,95 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package tensorflow;
|
||||
option cc_enable_arenas = true;
|
||||
option java_outer_classname = "FunctionProtos";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "org.tensorflow.framework";
|
||||
|
||||
import "attr_value.proto";
|
||||
import "op_def.proto";
|
||||
|
||||
// A library is a set of named functions.
|
||||
message FunctionDefLibrary {
|
||||
repeated FunctionDef function = 1;
|
||||
repeated GradientDef gradient = 2;
|
||||
}
|
||||
|
||||
// A function can be instantiated when the runtime can bind every attr
|
||||
// with a value. When a GraphDef has a call to a function, it must
|
||||
// have binding for every attr defined in the signature.
|
||||
//
|
||||
// TODO(zhifengc):
|
||||
// * device spec, etc.
|
||||
message FunctionDef {
|
||||
// The definition of the function's name, arguments, return values,
|
||||
// attrs etc.
|
||||
OpDef signature = 1;
|
||||
|
||||
// The body of the function.
|
||||
repeated Node node = 2; // function.node.ret[*] are unique.
|
||||
|
||||
// A node is a multi-value assignment:
|
||||
// (ret[0], ret[1], ...) = func(arg[0], arg[1], ...)
|
||||
//
|
||||
// By convention, "func" is resolved by consulting with a user-defined
|
||||
// library first. If not resolved, "func" is assumed to be a builtin op.
|
||||
message Node {
|
||||
// This node produces multiple outputs. They are named ret[0],
|
||||
// ret[1], ..., etc.
|
||||
//
|
||||
// REQUIRES: function.node.ret[*] are unique across all nodes.
|
||||
// REQUIRES: ret.size == func/op def's number of output args.
|
||||
repeated string ret = 1;
|
||||
|
||||
// The op/function name.
|
||||
string op = 2;
|
||||
|
||||
// Arguments passed to this func/op.
|
||||
//
|
||||
// arg[i] must be either one of
|
||||
// function.signature.input_args[*].name or one of
|
||||
// function.node[*].ret[*].
|
||||
//
|
||||
// REQUIRES: arg.size == func/op def's number of input args.
|
||||
repeated string arg = 3;
|
||||
|
||||
// Control dependencies.
|
||||
//
|
||||
// dep[i] must be one of function.node[*].ret[*] or one of
|
||||
// function.signature.input_args[*].name.
|
||||
repeated string dep = 4;
|
||||
|
||||
// Attrs.
|
||||
//
|
||||
// 'attr' maps names defined by 'func's attr defs to attr values.
|
||||
// attr values may have placeholders which are substituted
|
||||
// recursively by concrete values when this node is instantiated.
|
||||
// These placeholders must name an attr listed in the FunctionDef's
|
||||
// signature.
|
||||
map<string, AttrValue> attr = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// GradientDef defines the gradient function of a function defined in
|
||||
// a function library.
|
||||
//
|
||||
// A gradient function g (specified by gradient_func) for a function f
|
||||
// (specified by function_name) must follow the following:
|
||||
//
|
||||
// The function 'f' must be a numerical function which takes N inputs
|
||||
// and produces M outputs. Its gradient function 'g', which is a
|
||||
// function taking N + M inputs and produces N outputs.
|
||||
//
|
||||
// I.e. if we have
|
||||
// (y1, y2, ..., y_M) = f(x1, x2, ..., x_N),
|
||||
// then, g is
|
||||
// (dL/dx1, dL/dx2, ..., dL/dx_N) = g(x1, x2, ..., x_N,
|
||||
// dL/dy1, dL/dy2, ..., dL/dy_M),
|
||||
// where L is a scalar-value function of (x1, x2, ..., xN) (e.g., the
|
||||
// loss function). dL/dx_i is the partial derivative of L with respect
|
||||
// to x_i.
|
||||
message GradientDef {
|
||||
string function_name = 1; // The function name.
|
||||
string gradient_func = 2; // The gradient function's name.
|
||||
}
|
112
modules/dnn/src/tensorflow/graph.proto
Normal file
112
modules/dnn/src/tensorflow/graph.proto
Normal file
@ -0,0 +1,112 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package tensorflow;
|
||||
option cc_enable_arenas = true;
|
||||
option java_outer_classname = "GraphProtos";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "org.tensorflow.framework";
|
||||
|
||||
import "attr_value.proto";
|
||||
import "function.proto";
|
||||
import "versions.proto";
|
||||
|
||||
// Represents the graph of operations
|
||||
message GraphDef {
|
||||
repeated NodeDef node = 1;
|
||||
|
||||
// Compatibility versions of the graph. See core/public/version.h for version
|
||||
// history. The GraphDef version is distinct from the TensorFlow version, and
|
||||
// each release of TensorFlow will support a range of GraphDef versions.
|
||||
VersionDef versions = 4;
|
||||
|
||||
// Deprecated single version field; use versions above instead. Since all
|
||||
// GraphDef changes before "versions" was introduced were forward
|
||||
// compatible, this field is entirely ignored.
|
||||
int32 version = 3 [deprecated = true];
|
||||
|
||||
// EXPERIMENTAL. DO NOT USE OR DEPEND ON THIS YET.
|
||||
//
|
||||
// "library" provides user-defined functions.
|
||||
//
|
||||
// Naming:
|
||||
// * library.function.name are in a flat namespace.
|
||||
// NOTE: We may need to change it to be hierarchical to support
|
||||
// different orgs. E.g.,
|
||||
// { "/google/nn", { ... }},
|
||||
// { "/google/vision", { ... }}
|
||||
// { "/org_foo/module_bar", {...}}
|
||||
// map<string, FunctionDefLib> named_lib;
|
||||
// * If node[i].op is the name of one function in "library",
|
||||
// node[i] is deemed as a function call. Otherwise, node[i].op
|
||||
// must be a primitive operation supported by the runtime.
|
||||
//
|
||||
//
|
||||
// Function call semantics:
|
||||
//
|
||||
// * The callee may start execution as soon as some of its inputs
|
||||
// are ready. The caller may want to use Tuple() mechanism to
|
||||
// ensure all inputs are ready in the same time.
|
||||
//
|
||||
// * The consumer of return values may start executing as soon as
|
||||
// the return values the consumer depends on are ready. The
|
||||
// consumer may want to use Tuple() mechanism to ensure the
|
||||
// consumer does not start until all return values of the callee
|
||||
// function are ready.
|
||||
FunctionDefLibrary library = 2;
|
||||
};
|
||||
|
||||
message NodeDef {
|
||||
// The name given to this operator. Used for naming inputs,
|
||||
// logging, visualization, etc. Unique within a single GraphDef.
|
||||
// Must match the regexp "[A-Za-z0-9.][A-Za-z0-9_./]*".
|
||||
string name = 1;
|
||||
|
||||
// The operation name. There may be custom parameters in attrs.
|
||||
// Op names starting with an underscore are reserved for internal use.
|
||||
string op = 2;
|
||||
|
||||
// Each input is "node:src_output" with "node" being a string name and
|
||||
// "src_output" indicating which output tensor to use from "node". If
|
||||
// "src_output" is 0 the ":0" suffix can be omitted. Regular inputs
|
||||
// may optionally be followed by control inputs that have the format
|
||||
// "^node".
|
||||
repeated string input = 3;
|
||||
|
||||
// A (possibly partial) specification for the device on which this
|
||||
// node should be placed.
|
||||
// The expected syntax for this string is as follows:
|
||||
//
|
||||
// DEVICE_SPEC ::= COLOCATED_NODE | PARTIAL_SPEC
|
||||
//
|
||||
// COLOCATED_NODE ::= "@" NODE_NAME // See NodeDef.name above.
|
||||
// PARTIAL_SPEC ::= ("/" CONSTRAINT) *
|
||||
// CONSTRAINT ::= ("job:" JOB_NAME)
|
||||
// | ("replica:" [1-9][0-9]*)
|
||||
// | ("task:" [1-9][0-9]*)
|
||||
// | ( ("gpu" | "cpu") ":" ([1-9][0-9]* | "*") )
|
||||
//
|
||||
// Valid values for this string include:
|
||||
// * "@other/node" (colocate with "other/node")
|
||||
// * "/job:worker/replica:0/task:1/gpu:3" (full specification)
|
||||
// * "/job:worker/gpu:3" (partial specification)
|
||||
// * "" (no specification)
|
||||
//
|
||||
// If the constraints do not resolve to a single device (or if this
|
||||
// field is empty or not present), the runtime will attempt to
|
||||
// choose a device automatically.
|
||||
string device = 4;
|
||||
|
||||
// Operation-specific graph-construction-time configuration.
|
||||
// Note that this should include all attrs defined in the
|
||||
// corresponding OpDef, including those with a value matching
|
||||
// the default -- this allows the default to change and makes
|
||||
// NodeDefs easier to interpret on their own. However, if
|
||||
// an attr with a default is not specified in this list, the
|
||||
// default will be used.
|
||||
// The "names" (keys) must match the regexp "[a-z][a-z0-9_]+" (and
|
||||
// one of the names from the corresponding OpDef's attr field).
|
||||
// The values must have a type matching the corresponding OpDef
|
||||
// attr's type field.
|
||||
// TODO(josh11b): Add some examples here showing best practices.
|
||||
map<string, AttrValue> attr = 5;
|
||||
};
|
157
modules/dnn/src/tensorflow/op_def.proto
Normal file
157
modules/dnn/src/tensorflow/op_def.proto
Normal file
@ -0,0 +1,157 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package tensorflow;
|
||||
option cc_enable_arenas = true;
|
||||
option java_outer_classname = "OpDefProtos";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "org.tensorflow.framework";
|
||||
|
||||
import "attr_value.proto";
|
||||
import "types.proto";
|
||||
|
||||
// Defines an operation. A NodeDef in a GraphDef specifies an Op by
|
||||
// using the "op" field which should match the name of a OpDef.
|
||||
message OpDef {
|
||||
// Op names starting with an underscore are reserved for internal use.
|
||||
// Names should be CamelCase and match the regexp "[A-Z][a-zA-Z0-9_]*".
|
||||
string name = 1;
|
||||
|
||||
// For describing inputs and outputs.
|
||||
message ArgDef {
|
||||
// Name for the input/output. Should match the regexp "[a-z][a-z0-9_]*".
|
||||
string name = 1;
|
||||
|
||||
// Human readable description.
|
||||
string description = 2;
|
||||
|
||||
// Describes the type of one or more tensors that are accepted/produced
|
||||
// by this input/output arg. The only legal combinations are:
|
||||
// * For a single tensor: either the "type" field is set or the
|
||||
// "type_attr" field is set to the name of an attr with type "type".
|
||||
// * For a sequence of tensors with the same type: the "number_attr"
|
||||
// field will be set to the name of an attr with type "int", and
|
||||
// either the "type" or "type_attr" field will be set as for
|
||||
// single tensors.
|
||||
// * For a sequence of tensors, the "type_list_attr" field will be set
|
||||
// to the name of an attr with type "list(type)".
|
||||
DataType type = 3;
|
||||
string type_attr = 4; // if specified, attr must have type "type"
|
||||
string number_attr = 5; // if specified, attr must have type "int"
|
||||
// If specified, attr must have type "list(type)", and none of
|
||||
// type, type_attr, and number_attr may be specified.
|
||||
string type_list_attr = 6;
|
||||
|
||||
// For inputs: if true, the inputs are required to be refs.
|
||||
// By default, inputs can be either refs or non-refs.
|
||||
// For outputs: if true, outputs are refs, otherwise they are not.
|
||||
bool is_ref = 16;
|
||||
};
|
||||
|
||||
// Description of the input(s).
|
||||
repeated ArgDef input_arg = 2;
|
||||
|
||||
// Description of the output(s).
|
||||
repeated ArgDef output_arg = 3;
|
||||
|
||||
// Description of the graph-construction-time configuration of this
|
||||
// Op. That is to say, this describes the attr fields that will
|
||||
// be specified in the NodeDef.
|
||||
message AttrDef {
|
||||
// A descriptive name for the argument. May be used, e.g. by the
|
||||
// Python client, as a keyword argument name, and so should match
|
||||
// the regexp "[a-z][a-z0-9_]+".
|
||||
string name = 1;
|
||||
|
||||
// One of the type names from attr_value.proto ("string", "list(string)",
|
||||
// "int", etc.).
|
||||
string type = 2;
|
||||
|
||||
// A reasonable default for this attribute if the user does not supply
|
||||
// a value. If not specified, the user must supply a value.
|
||||
AttrValue default_value = 3;
|
||||
|
||||
// Human-readable description.
|
||||
string description = 4;
|
||||
|
||||
// TODO(josh11b): bool is_optional?
|
||||
|
||||
// --- Constraints ---
|
||||
// These constraints are only in effect if specified. Default is no
|
||||
// constraints.
|
||||
|
||||
// For type == "int", this is a minimum value. For "list(___)"
|
||||
// types, this is the minimum length.
|
||||
bool has_minimum = 5;
|
||||
int64 minimum = 6;
|
||||
|
||||
// The set of allowed values. Has type that is the "list" version
|
||||
// of the "type" field above (uses the "list" field of AttrValue).
|
||||
// If type == "type" or "list(type)" above, then the "type" field
|
||||
// of "allowed_values.list" has the set of allowed DataTypes.
|
||||
// If type == "string" or "list(string)", then the "s" field of
|
||||
// "allowed_values.list" has the set of allowed strings.
|
||||
AttrValue allowed_values = 7;
|
||||
}
|
||||
repeated AttrDef attr = 4;
|
||||
|
||||
// Optional deprecation based on GraphDef versions.
|
||||
OpDeprecation deprecation = 8;
|
||||
|
||||
// One-line human-readable description of what the Op does.
|
||||
string summary = 5;
|
||||
|
||||
// Additional, longer human-readable description of what the Op does.
|
||||
string description = 6;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Which optimizations this operation can participate in.
|
||||
|
||||
// True if the operation is commutative ("op(a,b) == op(b,a)" for all inputs)
|
||||
bool is_commutative = 18;
|
||||
|
||||
// If is_aggregate is true, then this operation accepts N >= 2
|
||||
// inputs and produces 1 output all of the same type. Should be
|
||||
// associative and commutative, and produce output with the same
|
||||
// shape as the input. The optimizer may replace an aggregate op
|
||||
// taking input from multiple devices with a tree of aggregate ops
|
||||
// that aggregate locally within each device (and possibly within
|
||||
// groups of nearby devices) before communicating.
|
||||
// TODO(josh11b): Implement that optimization.
|
||||
bool is_aggregate = 16; // for things like add
|
||||
|
||||
// Other optimizations go here, like
|
||||
// can_alias_input, rewrite_when_output_unused, partitioning_strategy, etc.
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Optimization constraints.
|
||||
|
||||
// By default Ops may be moved between devices. Stateful ops should
|
||||
// either not be moved, or should only be moved if that state can also
|
||||
// be moved (e.g. via some sort of save / restore).
|
||||
// Stateful ops are guaranteed to never be optimized away by Common
|
||||
// Subexpression Elimination (CSE).
|
||||
bool is_stateful = 17; // for things like variables, queue
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Non-standard options.
|
||||
|
||||
// By default, all inputs to an Op must be initialized Tensors. Ops
|
||||
// that may initialize tensors for the first time should set this
|
||||
// field to true, to allow the Op to take an uninitialized Tensor as
|
||||
// input.
|
||||
bool allows_uninitialized_input = 19; // for Assign, etc.
|
||||
};
|
||||
|
||||
// Information about version-dependent deprecation of an op
|
||||
message OpDeprecation {
|
||||
// First GraphDef version at which the op is disallowed.
|
||||
int32 version = 1;
|
||||
|
||||
// Explanation of why it was deprecated and what to use instead.
|
||||
string explanation = 2;
|
||||
};
|
||||
|
||||
// A collection of OpDefs
|
||||
message OpList {
|
||||
repeated OpDef op = 1;
|
||||
};
|
68
modules/dnn/src/tensorflow/tensor.proto
Normal file
68
modules/dnn/src/tensorflow/tensor.proto
Normal file
@ -0,0 +1,68 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package tensorflow;
|
||||
option cc_enable_arenas = true;
|
||||
option java_outer_classname = "TensorProtos";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "org.tensorflow.framework";
|
||||
|
||||
import "tensor_shape.proto";
|
||||
import "types.proto";
|
||||
|
||||
// Protocol buffer representing a tensor.
|
||||
message TensorProto {
|
||||
DataType dtype = 1;
|
||||
|
||||
// Shape of the tensor. TODO(touts): sort out the 0-rank issues.
|
||||
TensorShapeProto tensor_shape = 2;
|
||||
|
||||
// Only one of the representations below is set, one of "tensor_contents" and
|
||||
// the "xxx_val" attributes. We are not using oneof because as oneofs cannot
|
||||
// contain repeated fields it would require another extra set of messages.
|
||||
|
||||
// Version number.
|
||||
//
|
||||
// In version 0, if the "repeated xxx" representations contain only one
|
||||
// element, that element is repeated to fill the shape. This makes it easy
|
||||
// to represent a constant Tensor with a single value.
|
||||
int32 version_number = 3;
|
||||
|
||||
// Serialized content from Tensor::AsProtoTensorContent(). This representation
|
||||
// can be used for all tensor types.
|
||||
bytes tensor_content = 4;
|
||||
|
||||
// Type specific representations that make it easy to create tensor protos in
|
||||
// all languages. Only the representation corresponding to "dtype" can
|
||||
// be set. The values hold the flattened representation of the tensor in
|
||||
// row major order.
|
||||
|
||||
// DT_HALF. Note that since protobuf has no int16 type, we'll have some
|
||||
// pointless zero padding for each value here.
|
||||
repeated int32 half_val = 13 [packed = true];
|
||||
|
||||
// DT_FLOAT.
|
||||
repeated float float_val = 5 [packed = true];
|
||||
|
||||
// DT_DOUBLE.
|
||||
repeated double double_val = 6 [packed = true];
|
||||
|
||||
// DT_INT32, DT_INT16, DT_INT8, DT_UINT8.
|
||||
repeated int32 int_val = 7 [packed = true];
|
||||
|
||||
// DT_STRING
|
||||
repeated bytes string_val = 8;
|
||||
|
||||
// DT_COMPLEX64. scomplex_val(2*i) and scomplex_val(2*i+1) are real
|
||||
// and imaginary parts of i-th single precision complex.
|
||||
repeated float scomplex_val = 9 [packed = true];
|
||||
|
||||
// DT_INT64
|
||||
repeated int64 int64_val = 10 [packed = true];
|
||||
|
||||
// DT_BOOL
|
||||
repeated bool bool_val = 11 [packed = true];
|
||||
|
||||
// DT_COMPLEX128. dcomplex_val(2*i) and dcomplex_val(2*i+1) are real
|
||||
// and imaginary parts of i-th double precision complex.
|
||||
repeated double dcomplex_val = 12 [packed = true];
|
||||
};
|
45
modules/dnn/src/tensorflow/tensor_shape.proto
Normal file
45
modules/dnn/src/tensorflow/tensor_shape.proto
Normal file
@ -0,0 +1,45 @@
|
||||
// Protocol buffer representing the shape of tensors.
|
||||
|
||||
syntax = "proto3";
|
||||
option cc_enable_arenas = true;
|
||||
option java_outer_classname = "TensorShapeProtos";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "org.tensorflow.framework";
|
||||
|
||||
package tensorflow;
|
||||
|
||||
// Dimensions of a tensor.
|
||||
message TensorShapeProto {
|
||||
// One dimension of the tensor.
|
||||
message Dim {
|
||||
// Size of the tensor in that dimension.
|
||||
// This value must be >= -1, but values of -1 are reserved for "unknown"
|
||||
// shapes (values of -1 mean "unknown" dimension). Certain wrappers
|
||||
// that work with TensorShapeProto may fail at runtime when deserializing
|
||||
// a TensorShapeProto containing a dim value of -1.
|
||||
int64 size = 1;
|
||||
|
||||
// Optional name of the tensor dimension.
|
||||
string name = 2;
|
||||
};
|
||||
|
||||
// Dimensions of the tensor, such as {"input", 30}, {"output", 40}
|
||||
// for a 30 x 40 2D tensor. If an entry has size -1, this
|
||||
// corresponds to a dimension of unknown size. The names are
|
||||
// optional.
|
||||
//
|
||||
// The order of entries in "dim" matters: It indicates the layout of the
|
||||
// values in the tensor in-memory representation.
|
||||
//
|
||||
// The first entry in "dim" is the outermost dimension used to layout the
|
||||
// values, the last entry is the innermost dimension. This matches the
|
||||
// in-memory layout of RowMajor Eigen tensors.
|
||||
//
|
||||
// If "dim.size()" > 0, "unknown_rank" must be false.
|
||||
repeated Dim dim = 2;
|
||||
|
||||
// If true, the number of dimensions in the shape is unknown.
|
||||
//
|
||||
// If true, "dim.size()" must be 0.
|
||||
bool unknown_rank = 3;
|
||||
};
|
759
modules/dnn/src/tensorflow/tf_importer.cpp
Normal file
759
modules/dnn/src/tensorflow/tf_importer.cpp
Normal file
@ -0,0 +1,759 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2016, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
/*
|
||||
Implementation of Tensorflow models parser
|
||||
*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
using namespace cv;
|
||||
using namespace cv::dnn;
|
||||
|
||||
#if HAVE_PROTOBUF
|
||||
#include "graph.pb.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include "tf_io.hpp"
|
||||
|
||||
using ::google::protobuf::RepeatedField;
|
||||
using ::google::protobuf::RepeatedPtrField;
|
||||
using ::google::protobuf::Message;
|
||||
using ::google::protobuf::Descriptor;
|
||||
using ::google::protobuf::FieldDescriptor;
|
||||
using ::google::protobuf::Reflection;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static int toNCHW[] = {0, 2, 3, 1};
|
||||
|
||||
typedef std::vector<std::pair<String, int> > StrIntVector;
|
||||
|
||||
struct Pin
|
||||
{
|
||||
Pin(const std::string &_name, int _blobIndex = 0) :
|
||||
name(_name), blobIndex(_blobIndex) {}
|
||||
|
||||
Pin() :
|
||||
name(""), blobIndex(-1) {}
|
||||
|
||||
std::string name;
|
||||
int blobIndex;
|
||||
};
|
||||
|
||||
void blobShapeFromTensor(const tensorflow::TensorProto &tensor, MatShape& shape)
|
||||
{
|
||||
shape.clear();
|
||||
if (tensor.has_tensor_shape())
|
||||
{
|
||||
const tensorflow::TensorShapeProto &_shape = tensor.tensor_shape();
|
||||
int i, n = _shape.dim_size();
|
||||
shape.resize(n);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
shape[i] = (int)_shape.dim(i).size();
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Error(Error::StsError, "Unknown shape of input tensor");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void parseTensor(const tensorflow::TensorProto &tensor, Mat &dstBlob)
|
||||
{
|
||||
MatShape shape;
|
||||
blobShapeFromTensor(tensor, shape);
|
||||
int dims = (int)shape.size();
|
||||
|
||||
if (dims == 4)
|
||||
{
|
||||
// REORDER blob NHWC to NCHW
|
||||
swap(shape[2], shape[3]); // NHCW
|
||||
swap(shape[1], shape[2]); // NCHW
|
||||
}
|
||||
|
||||
dstBlob.create(shape, CV_32F);
|
||||
|
||||
int size = tensor.tensor_content().size() / sizeof(T);
|
||||
CV_Assert(size == (int)dstBlob.total());
|
||||
|
||||
float *dstData = dstBlob.ptr<float>();
|
||||
const T *data = reinterpret_cast<const T*>(tensor.tensor_content().c_str());
|
||||
|
||||
if (dims == 4)
|
||||
{
|
||||
int num = shape[0], channels = shape[1], height = shape[2], width = shape[3];
|
||||
int total = num*channels*height*width;
|
||||
for(int i_n = 0; i_n < shape[0]; i_n++) {
|
||||
for(int i_c = 0; i_c < shape[1]; i_c++) {
|
||||
for(int i_h = 0; i_h < shape[2]; i_h++) {
|
||||
for(int i_w = 0; i_w < shape[3]; i_w++) {
|
||||
int dst_i = channels*height*width*i_n + height*width*i_c + width*i_h + i_w;
|
||||
int src_i = channels*height*width*i_n + i_c + channels*width*i_h + channels*i_w;
|
||||
|
||||
CV_Assert(dst_i < total);
|
||||
CV_Assert(src_i < total);
|
||||
|
||||
dstData[dst_i] = data[src_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < size; i++)
|
||||
dstData[i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void blobFromTensor(const tensorflow::TensorProto &tensor, Mat &dstBlob)
|
||||
{
|
||||
switch (tensor.dtype()) {
|
||||
case tensorflow::DT_FLOAT:
|
||||
parseTensor<float>(tensor, dstBlob);
|
||||
break;
|
||||
case tensorflow::DT_DOUBLE:
|
||||
parseTensor<double>(tensor, dstBlob);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsError, "Tensor's data type is not supported");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void printList(const tensorflow::AttrValue::ListValue &val)
|
||||
{
|
||||
std::cout << "(";
|
||||
for (int i = 0; i < val.i_size(); i++)
|
||||
std::cout << " " << val.i(i);
|
||||
std::cout << " )";
|
||||
}
|
||||
|
||||
void printTensorShape(const tensorflow::TensorShapeProto &shape)
|
||||
{
|
||||
std::cout << "[ ";
|
||||
for (int d = 0; d < shape.dim_size(); d++)
|
||||
std::cout << shape.dim(d).name() <<
|
||||
":" << shape.dim(d).size() << " ";
|
||||
std::cout << "]";
|
||||
}
|
||||
|
||||
void printTensor(const tensorflow::TensorProto &tensor)
|
||||
{
|
||||
printTensorShape(tensor.tensor_shape());
|
||||
|
||||
if (tensor.tensor_content().empty())
|
||||
return;
|
||||
|
||||
switch (tensor.dtype())
|
||||
{
|
||||
case 1: // float
|
||||
{
|
||||
const float *data = reinterpret_cast<const float*>(tensor.tensor_content().c_str());
|
||||
int size = tensor.tensor_content().size() / sizeof(float);
|
||||
for (int i = 0; i < std::min(10, size); i++)
|
||||
std::cout << " " << data[i];
|
||||
if (size > 10)
|
||||
std::cout << " ... " << size - 10 << " more";
|
||||
break;
|
||||
}
|
||||
case 3: // int32
|
||||
{
|
||||
const int *data = reinterpret_cast<const int*>(tensor.tensor_content().c_str());
|
||||
int size = tensor.tensor_content().size() / sizeof(int);
|
||||
for (int i = 0; i < std::min(10, size); i++)
|
||||
std::cout << " " << data[i];
|
||||
if (size > 10)
|
||||
std::cout << " ... " << size - 10 << " more";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CV_Error(Error::StsError, "Tensor type is not supported");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void printLayerAttr(const tensorflow::NodeDef &layer)
|
||||
{
|
||||
std::cout << std::endl << layer.name() << ":" << layer.op();
|
||||
for (int ii = 0; ii < layer.input_size(); ii++)
|
||||
std::cout << "(" << layer.input(ii) << ")";
|
||||
std::cout << std::endl;
|
||||
google::protobuf::Map<std::string, tensorflow::AttrValue> attr
|
||||
= layer.attr();
|
||||
for (google::protobuf::Map<std::string, tensorflow::AttrValue>::const_iterator ai = attr.begin();
|
||||
ai != attr.end(); ++ai)
|
||||
{
|
||||
std::cout << ai->first << ":";
|
||||
if (ai->first == "dtype" || ai->first == "T")
|
||||
std::cout << ai->second.i();
|
||||
else if (ai->first == "padding")
|
||||
std::cout << ai->second.s();
|
||||
else if (ai->first == "transpose_a" || ai->first == "transpose_b")
|
||||
std::cout << ai->second.b();
|
||||
// else if (ai->first == "shape")
|
||||
// printTensorShape(ai->second.shape());
|
||||
else if (ai->first == "strides" || ai->first == "ksize")
|
||||
printList(ai->second.list());
|
||||
else
|
||||
printTensor(ai->second.tensor());
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasLayerAttr(const tensorflow::NodeDef &layer, const std::string &name)
|
||||
{
|
||||
google::protobuf::Map<std::string, tensorflow::AttrValue> attr = layer.attr();
|
||||
return attr.find(name) != attr.end();
|
||||
}
|
||||
|
||||
const tensorflow::AttrValue& getLayerAttr(const tensorflow::NodeDef &layer, const std::string &name)
|
||||
{
|
||||
return layer.attr().at(name);
|
||||
}
|
||||
|
||||
void setStrides(LayerParams &layerParams, const tensorflow::NodeDef &layer)
|
||||
{
|
||||
if (hasLayerAttr(layer, "strides"))
|
||||
{
|
||||
const tensorflow::AttrValue& val = getLayerAttr(layer, "strides");
|
||||
if (val.list().i_size() != 4 ||
|
||||
val.list().i(0) != 1 || val.list().i(3) != 1)
|
||||
CV_Error(Error::StsError, "Unsupported strides");
|
||||
layerParams.set("stride_h", static_cast<int>(val.list().i(1)));
|
||||
layerParams.set("stride_w", static_cast<int>(val.list().i(2)));
|
||||
}
|
||||
}
|
||||
|
||||
DictValue parseDims(const tensorflow::TensorProto &tensor) {
|
||||
MatShape shape;
|
||||
blobShapeFromTensor(tensor, shape);
|
||||
int dims = (int)shape.size();
|
||||
|
||||
CV_Assert(tensor.dtype() == tensorflow::DT_INT32);
|
||||
CV_Assert(dims == 1);
|
||||
|
||||
int size = tensor.tensor_content().size() / sizeof(int);
|
||||
const int *data = reinterpret_cast<const int*>(tensor.tensor_content().c_str());
|
||||
// TODO: add reordering shape if dims == 4
|
||||
return DictValue::arrayInt(data, size);
|
||||
}
|
||||
|
||||
void setKSize(LayerParams &layerParams, const tensorflow::NodeDef &layer)
|
||||
{
|
||||
if (hasLayerAttr(layer, "ksize"))
|
||||
{
|
||||
const tensorflow::AttrValue& val = getLayerAttr(layer, "ksize");
|
||||
if (val.list().i_size() != 4 ||
|
||||
val.list().i(0) != 1 || val.list().i(3) != 1)
|
||||
CV_Error(Error::StsError, "Unsupported ksize");
|
||||
layerParams.set("kernel_h", static_cast<int>(val.list().i(1)));
|
||||
layerParams.set("kernel_w", static_cast<int>(val.list().i(2)));
|
||||
}
|
||||
else
|
||||
{
|
||||
layerParams.set("kernel_h", 1);
|
||||
layerParams.set("kernel_w", 1);
|
||||
}
|
||||
}
|
||||
|
||||
void setPadding(LayerParams &layerParams, const tensorflow::NodeDef &layer)
|
||||
{
|
||||
if (hasLayerAttr(layer, "padding"))
|
||||
layerParams.set("pad_mode", getLayerAttr(layer, "padding").s());
|
||||
}
|
||||
|
||||
void RemoveIdentityOps(tensorflow::GraphDef& net) {
|
||||
typedef std::map<String, String> IdentityOpsMap;
|
||||
IdentityOpsMap identity_ops;
|
||||
|
||||
std::vector<int> identity_ops_idx;
|
||||
|
||||
int layersCount = net.node_size();
|
||||
for (int li = 0; li < layersCount; li++)
|
||||
{
|
||||
const tensorflow::NodeDef &layer = net.node(li);
|
||||
String type = layer.op();
|
||||
|
||||
if (type == "Identity") {
|
||||
identity_ops_idx.push_back(li);
|
||||
identity_ops[layer.name()] = layer.input(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int li = 0; li < layersCount; li++)
|
||||
{
|
||||
tensorflow::NodeDef* layer = net.mutable_node(li);
|
||||
for (int input_id = 0; input_id < layer->input_size(); input_id++) {
|
||||
String input_op_name = layer->input(input_id);
|
||||
IdentityOpsMap::iterator it = identity_ops.find(input_op_name);
|
||||
|
||||
if (it != identity_ops.end()) {
|
||||
layer->set_input(input_id, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(identity_ops_idx.begin(), identity_ops_idx.end());
|
||||
|
||||
int removed_nodes = 0;
|
||||
for(size_t i = 0; i < identity_ops_idx.size(); i++) {
|
||||
int start_id = identity_ops_idx[i] - removed_nodes;
|
||||
net.mutable_node()->DeleteSubrange(start_id, 1);
|
||||
removed_nodes++;
|
||||
}
|
||||
}
|
||||
|
||||
Pin parsePin(const std::string &name)
|
||||
{
|
||||
Pin pin(name);
|
||||
|
||||
size_t delimiter_pos = name.find_first_of(":");
|
||||
if (delimiter_pos != std::string::npos)
|
||||
{
|
||||
pin.name = name.substr(0, delimiter_pos);
|
||||
std::istringstream(name.substr(delimiter_pos + 1)) >> pin.blobIndex;
|
||||
}
|
||||
|
||||
return pin;
|
||||
}
|
||||
|
||||
StrIntVector getNextLayers(const tensorflow::GraphDef& net, const String& layer_name, const String& type = "")
|
||||
{
|
||||
StrIntVector layers;
|
||||
|
||||
for (int li = 0; li < net.node_size(); li++)
|
||||
{
|
||||
const tensorflow::NodeDef& layer = net.node(li);
|
||||
for (int input_id = 0; input_id < layer.input_size(); input_id++) {
|
||||
String input_op_name = parsePin(layer.input(input_id)).name;
|
||||
bool type_ok = type.empty() ? true : type == layer.op();
|
||||
if (input_op_name == layer_name && type_ok)
|
||||
layers.push_back(std::make_pair(layer.name(), li));
|
||||
}
|
||||
}
|
||||
|
||||
return layers;
|
||||
}
|
||||
|
||||
void ExcludeLayer(tensorflow::GraphDef& net, const int layer_index, const int input_blob_index, bool remove_from_net = true) {
|
||||
String layer_name = net.node(layer_index).name();
|
||||
StrIntVector layers = getNextLayers(net, layer_name);
|
||||
|
||||
String removed_layer_input = net.node(layer_index).input(input_blob_index);
|
||||
|
||||
for (size_t i = 0; i < layers.size(); i++)
|
||||
{
|
||||
tensorflow::NodeDef* layer = net.mutable_node(layers[i].second);
|
||||
for (int input_id = 0; input_id < layer->input_size(); input_id++) {
|
||||
String input_op_name = layer->input(input_id);
|
||||
|
||||
if (input_op_name == layer_name) {
|
||||
layer->set_input(input_id, removed_layer_input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (remove_from_net)
|
||||
net.mutable_node()->DeleteSubrange(layer_index, 1);
|
||||
}
|
||||
|
||||
class TFImporter : public Importer {
|
||||
public:
|
||||
TFImporter(const char *model);
|
||||
void populateNet(Net dstNet);
|
||||
~TFImporter() {}
|
||||
|
||||
private:
|
||||
void kernelFromTensor(const tensorflow::TensorProto &tensor, Mat &dstBlob);
|
||||
|
||||
void connect(const std::map<String, int>& layers_name_id_map, Net& network, const Pin& outPin,
|
||||
const int input_layer_id, const int input_blob_id);
|
||||
void connectToAllBlobs(const std::map<String, int>& layer_id, Net& network, const Pin& outPin,
|
||||
const int input_layer_id, const int input_blobs_count);
|
||||
const tensorflow::TensorProto& getConstBlob(const tensorflow::NodeDef &layer, std::map<String, int> const_layers,
|
||||
int input_blob_index = -1, int* actual_inp_blob_idx = 0);
|
||||
|
||||
|
||||
tensorflow::GraphDef net;
|
||||
};
|
||||
|
||||
TFImporter::TFImporter(const char *model)
|
||||
{
|
||||
if (model && model[0])
|
||||
ReadTFNetParamsFromBinaryFileOrDie(model, &net);
|
||||
}
|
||||
|
||||
void TFImporter::kernelFromTensor(const tensorflow::TensorProto &tensor, Mat &dstBlob)
|
||||
{
|
||||
MatShape shape;
|
||||
blobShapeFromTensor(tensor, shape);
|
||||
int dims = (int)shape.size();
|
||||
|
||||
// TODO: other blob types
|
||||
CV_Assert(tensor.dtype() == tensorflow::DT_FLOAT);
|
||||
CV_Assert(dims == 4);
|
||||
|
||||
// REORDER kernel HWIO to OIHW
|
||||
swap(shape[0], shape[2]); // IWHO
|
||||
swap(shape[1], shape[3]); // IOHW
|
||||
swap(shape[0], shape[1]); // OIHW
|
||||
|
||||
dstBlob.create(shape, CV_32F);
|
||||
|
||||
int size = tensor.tensor_content().size() / sizeof(float);
|
||||
CV_Assert(size == (int)dstBlob.total());
|
||||
|
||||
float *dstData = dstBlob.ptr<float>();
|
||||
const float *data = reinterpret_cast<const float*>(tensor.tensor_content().c_str());
|
||||
|
||||
int out_c = shape[0], input_c = shape[1], height = shape[2], width = shape[3];
|
||||
int total = out_c*input_c*height*width;
|
||||
for(int i_oc = 0; i_oc < out_c; i_oc++) {
|
||||
for(int i_ic = 0; i_ic < input_c; i_ic++) {
|
||||
for(int i_h = 0; i_h < height; i_h++) {
|
||||
for(int i_w = 0; i_w < width; i_w++) {
|
||||
int dst_i = input_c*height*width*i_oc + height*width*i_ic + width*i_h + i_w;
|
||||
int src_i = out_c*input_c*width*i_h + out_c*input_c*i_w + out_c*i_ic + i_oc;
|
||||
CV_Assert(dst_i < total);
|
||||
CV_Assert(src_i < total);
|
||||
dstData[dst_i] = data[src_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TFImporter::connect(const std::map<String, int>& layers_name_id_map, Net& network, const Pin& outPin,
|
||||
const int input_layer_id, const int input_blob_id)
|
||||
{
|
||||
std::map<String, int>::const_iterator it = layers_name_id_map.find(outPin.name);
|
||||
if (it == layers_name_id_map.end())
|
||||
CV_Error(Error::StsError, "Input layer not found: " + outPin.name);
|
||||
network.connect(it->second, outPin.blobIndex, input_layer_id, input_blob_id);
|
||||
}
|
||||
|
||||
void TFImporter::connectToAllBlobs(const std::map<String, int>& layer_id, Net& network, const Pin& outPin,
|
||||
const int input_layer_id, const int input_blobs_count)
|
||||
{
|
||||
for (int input_blob_id = 0; input_blob_id < input_blobs_count; input_blob_id++)
|
||||
connect(layer_id, network, outPin, input_layer_id, input_blob_id);
|
||||
}
|
||||
|
||||
const tensorflow::TensorProto& TFImporter::getConstBlob(const tensorflow::NodeDef &layer, std::map<String, int> const_layers,
|
||||
int input_blob_index, int* actual_inp_blob_idx) {
|
||||
if (input_blob_index == -1) {
|
||||
for(int i = 0; i < layer.input_size(); i++) {
|
||||
Pin input = parsePin(layer.input(i));
|
||||
if (const_layers.find(input.name) != const_layers.end()) {
|
||||
if (input_blob_index != -1)
|
||||
CV_Error(Error::StsError, "More than one input is Const op");
|
||||
|
||||
input_blob_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (input_blob_index == -1)
|
||||
CV_Error(Error::StsError, "Const input blob for weights not found");
|
||||
|
||||
Pin kernel_inp = parsePin(layer.input(input_blob_index));
|
||||
if (const_layers.find(kernel_inp.name) == const_layers.end())
|
||||
CV_Error(Error::StsError, "Const kernel input not found");
|
||||
if (kernel_inp.blobIndex != 0)
|
||||
CV_Error(Error::StsError, "Unsupported kernel input");
|
||||
|
||||
if(actual_inp_blob_idx) {
|
||||
*actual_inp_blob_idx = input_blob_index;
|
||||
}
|
||||
|
||||
return net.node(const_layers.at(kernel_inp.name)).attr().at("value").tensor();
|
||||
}
|
||||
|
||||
|
||||
void TFImporter::populateNet(Net dstNet)
|
||||
{
|
||||
RemoveIdentityOps(net);
|
||||
|
||||
std::map<int, String> layers_to_ignore;
|
||||
|
||||
int layersSize = net.node_size();
|
||||
|
||||
// find all Const layers for params
|
||||
std::map<String, int> value_id;
|
||||
for (int li = 0; li < layersSize; li++)
|
||||
{
|
||||
const tensorflow::NodeDef &layer = net.node(li);
|
||||
String name = layer.name();
|
||||
String type = layer.op();
|
||||
|
||||
if (type != "Const")
|
||||
continue; // only Const parameters are supported
|
||||
|
||||
if (layer.attr().find("value") != layer.attr().end())
|
||||
{
|
||||
value_id.insert(std::make_pair(name, li));
|
||||
}
|
||||
|
||||
layers_to_ignore[li] = name;
|
||||
}
|
||||
|
||||
std::map<String, int> layer_id;
|
||||
|
||||
for (int li = 0; li < layersSize; li++)
|
||||
{
|
||||
const tensorflow::NodeDef &layer = net.node(li);
|
||||
String name = layer.name();
|
||||
String type = layer.op();
|
||||
LayerParams layerParams;
|
||||
|
||||
if(layers_to_ignore.find(li) != layers_to_ignore.end())
|
||||
continue;
|
||||
|
||||
if (type == "Conv2D")
|
||||
{
|
||||
layerParams.set("bias_term", false);
|
||||
layerParams.blobs.resize(1);
|
||||
|
||||
StrIntVector next_layers = getNextLayers(net, name, "BiasAdd");
|
||||
if (next_layers.size() == 1) {
|
||||
layerParams.set("bias_term", true);
|
||||
layerParams.blobs.resize(2);
|
||||
|
||||
int weights_layer_index = next_layers[0].second;
|
||||
|
||||
blobFromTensor(getConstBlob(net.node(weights_layer_index), value_id), layerParams.blobs[1]);
|
||||
ExcludeLayer(net, weights_layer_index, 0, false);
|
||||
layers_to_ignore[weights_layer_index] = next_layers[0].first;
|
||||
}
|
||||
|
||||
kernelFromTensor(getConstBlob(layer, value_id), layerParams.blobs[0]);
|
||||
const int* kshape = layerParams.blobs[0].size.p;
|
||||
layerParams.set("kernel_h", kshape[2]);
|
||||
layerParams.set("kernel_w", kshape[3]);
|
||||
layerParams.set("num_output", kshape[0]);
|
||||
|
||||
setStrides(layerParams, layer);
|
||||
setPadding(layerParams, layer);
|
||||
|
||||
int id = dstNet.addLayer(name, "Convolution", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
// one input only
|
||||
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
|
||||
}
|
||||
else if (type == "BiasAdd" || type == "Add")
|
||||
{
|
||||
layerParams.blobs.resize(1);
|
||||
blobFromTensor(getConstBlob(layer, value_id), layerParams.blobs[0]);
|
||||
|
||||
int id = dstNet.addLayer(name, "Shift", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
// one input only
|
||||
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
|
||||
}
|
||||
else if (type == "Identity")
|
||||
{
|
||||
int id = dstNet.addLayer(name, "Identity", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
connectToAllBlobs(layer_id, dstNet, parsePin(layer.input(0)), id, layer.input_size());
|
||||
}
|
||||
else if (type == "MatMul")
|
||||
{
|
||||
CV_Assert(layer.input_size() == 2);
|
||||
|
||||
layerParams.set("bias_term", false);
|
||||
layerParams.blobs.resize(1);
|
||||
|
||||
StrIntVector next_layers = getNextLayers(net, name, "BiasAdd");
|
||||
if (next_layers.size() == 1) {
|
||||
layerParams.set("bias_term", true);
|
||||
layerParams.blobs.resize(2);
|
||||
|
||||
int weights_layer_index = next_layers[0].second;
|
||||
blobFromTensor(getConstBlob(net.node(weights_layer_index), value_id), layerParams.blobs[1]);
|
||||
ExcludeLayer(net, weights_layer_index, 0, false);
|
||||
layers_to_ignore[weights_layer_index] = next_layers[0].first;
|
||||
}
|
||||
|
||||
int kernel_blob_index = -1;
|
||||
blobFromTensor(getConstBlob(layer, value_id, -1, &kernel_blob_index), layerParams.blobs[0]);
|
||||
|
||||
if (kernel_blob_index == 1) { // In this case output is computed by x*W formula - W should be transposed
|
||||
Mat data = layerParams.blobs[0].t();
|
||||
layerParams.blobs[0] = data.clone();
|
||||
}
|
||||
|
||||
layerParams.set("num_output", layerParams.blobs[0].size[0]);
|
||||
|
||||
int id = dstNet.addLayer(name, "InnerProduct", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
// one input only
|
||||
int input_blob_index = kernel_blob_index == 0 ? 1 : 0;
|
||||
connect(layer_id, dstNet, parsePin(layer.input(input_blob_index)), id, 0);
|
||||
}
|
||||
else if (type == "Reshape")
|
||||
{
|
||||
layerParams.set("dim", parseDims(getConstBlob(layer, value_id, 1)));
|
||||
layerParams.set("reorder_dims", true);
|
||||
|
||||
int id = dstNet.addLayer(name, "Reshape", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
// one input only
|
||||
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
|
||||
}
|
||||
else if (type == "Const")
|
||||
{
|
||||
}
|
||||
else if (type == "Softmax")
|
||||
{
|
||||
int id = dstNet.addLayer(name, "Softmax", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
connectToAllBlobs(layer_id, dstNet, parsePin(layer.input(0)), id, layer.input_size());
|
||||
}
|
||||
else if (type == "LRN")
|
||||
{
|
||||
if(hasLayerAttr(layer, "alpha")) {
|
||||
layerParams.set("alpha", getLayerAttr(layer, "alpha").f());
|
||||
}
|
||||
if(hasLayerAttr(layer, "beta")) {
|
||||
layerParams.set("beta", getLayerAttr(layer, "beta").f());
|
||||
}
|
||||
if(hasLayerAttr(layer, "depth_radius")) {
|
||||
int radius = (int)getLayerAttr(layer, "depth_radius").i();
|
||||
layerParams.set("local_size", 2*radius + 1);
|
||||
}
|
||||
if(hasLayerAttr(layer, "bias")) {
|
||||
layerParams.set("bias", getLayerAttr(layer, "bias").f());
|
||||
}
|
||||
layerParams.set("norm_by_size", false);
|
||||
|
||||
int id = dstNet.addLayer(name, "LRN", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
connectToAllBlobs(layer_id, dstNet, parsePin(layer.input(0)), id, layer.input_size());
|
||||
}
|
||||
else if (type == "Concat")
|
||||
{
|
||||
int axis = getConstBlob(layer, value_id, 0).int_val().Get(0);
|
||||
layerParams.set("axis", toNCHW[axis]);
|
||||
|
||||
int id = dstNet.addLayer(name, "Concat", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
// input(0) is concat_dim
|
||||
for (int ii = 1; ii < layer.input_size(); ii++)
|
||||
{
|
||||
Pin inp = parsePin(layer.input(ii));
|
||||
if (layer_id.find(inp.name) == layer_id.end())
|
||||
CV_Error(Error::StsError, "Input layer not found: " + inp.name);
|
||||
dstNet.connect(layer_id.at(inp.name), inp.blobIndex, id, ii - 1);
|
||||
}
|
||||
}
|
||||
else if (type == "Relu")
|
||||
{
|
||||
int id = dstNet.addLayer(name, "ReLU", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
connectToAllBlobs(layer_id, dstNet, parsePin(layer.input(0)), id, layer.input_size());
|
||||
}
|
||||
else if (type == "MaxPool")
|
||||
{
|
||||
layerParams.set("pool", "max");
|
||||
|
||||
setKSize(layerParams, layer);
|
||||
setStrides(layerParams, layer);
|
||||
setPadding(layerParams, layer);
|
||||
|
||||
int id = dstNet.addLayer(name, "Pooling", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
connectToAllBlobs(layer_id, dstNet, parsePin(layer.input(0)), id, layer.input_size());
|
||||
}
|
||||
else if (type == "AvgPool")
|
||||
{
|
||||
layerParams.set("pool", "ave");
|
||||
|
||||
setKSize(layerParams, layer);
|
||||
setStrides(layerParams, layer);
|
||||
setPadding(layerParams, layer);
|
||||
|
||||
int id = dstNet.addLayer(name, "Pooling", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
connectToAllBlobs(layer_id, dstNet, parsePin(layer.input(0)), id, layer.input_size());
|
||||
}
|
||||
else if (type == "Placeholder")
|
||||
{
|
||||
std::vector<String> netInputs(1);
|
||||
netInputs[0] = name;
|
||||
layer_id[name] = 0;
|
||||
dstNet.setInputsNames(netInputs);
|
||||
}
|
||||
else if (type == "Split") {
|
||||
// TODO: determing axis index remapping by input dimensions order of input blob
|
||||
// TODO: slicing input may be Const op
|
||||
// TODO: slicing kernels for convolutions - in current implenmentation it is impossible
|
||||
// TODO: add parsing num of slices parameter
|
||||
CV_Assert(layer.input_size() == 2);
|
||||
// num_split
|
||||
// 1st blob is dims tensor
|
||||
layerParams.set("slice_point", DictValue::arrayReal((double*)0, 0));
|
||||
|
||||
int axis = getConstBlob(layer, value_id, 0).int_val().Get(0);
|
||||
layerParams.set("axis", toNCHW[axis]);
|
||||
|
||||
int id = dstNet.addLayer(name, "Slice", layerParams);
|
||||
layer_id[name] = id;
|
||||
|
||||
// one input only
|
||||
connect(layer_id, dstNet, parsePin(layer.input(1)), id, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
printLayerAttr(layer);
|
||||
CV_Error_(Error::StsError, ("Unknown layer type %s in op %s", type.c_str(), name.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Ptr<Importer> cv::dnn::createTensorflowImporter(const String &model)
|
||||
{
|
||||
return Ptr<Importer>(new TFImporter(model.c_str()));
|
||||
}
|
||||
|
||||
#else //HAVE_PROTOBUF
|
||||
|
||||
Ptr<Importer> cv::dnn::createTensorflowImporter(const String&)
|
||||
{
|
||||
CV_Error(cv::Error::StsNotImplemented, "libprotobuf required to import data from TensorFlow models");
|
||||
return Ptr<Importer>();
|
||||
}
|
||||
|
||||
#endif //HAVE_PROTOBUF
|
||||
|
||||
Net cv::dnn::readNetFromTensorflow(const String &model)
|
||||
{
|
||||
Ptr<Importer> importer = createTensorflowImporter(model);
|
||||
Net net;
|
||||
if (importer)
|
||||
importer->populateNet(net);
|
||||
return net;
|
||||
}
|
63
modules/dnn/src/tensorflow/tf_io.cpp
Normal file
63
modules/dnn/src/tensorflow/tf_io.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2016, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
/*
|
||||
Implementation of various functions which are related to Tensorflow models reading.
|
||||
*/
|
||||
|
||||
#if HAVE_PROTOBUF
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/text_format.h>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "graph.pb.h"
|
||||
#include "tf_io.hpp"
|
||||
#include "../caffe/glog_emulator.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
using namespace tensorflow;
|
||||
using namespace ::google::protobuf;
|
||||
using namespace ::google::protobuf::io;
|
||||
|
||||
const int kProtoReadBytesLimit = INT_MAX; // Max size of 2 GB minus 1 byte.
|
||||
|
||||
// TODO: remove Caffe duplicate
|
||||
bool ReadProtoFromBinaryFileTF(const char* filename, Message* proto) {
|
||||
std::ifstream fs(filename, std::ifstream::in | std::ifstream::binary);
|
||||
CHECK(fs.is_open()) << "Can't open \"" << filename << "\"";
|
||||
ZeroCopyInputStream* raw_input = new IstreamInputStream(&fs);
|
||||
CodedInputStream* coded_input = new CodedInputStream(raw_input);
|
||||
coded_input->SetTotalBytesLimit(kProtoReadBytesLimit, 536870912);
|
||||
|
||||
bool success = proto->ParseFromCodedStream(coded_input);
|
||||
|
||||
delete coded_input;
|
||||
delete raw_input;
|
||||
fs.close();
|
||||
return success;
|
||||
}
|
||||
|
||||
void ReadTFNetParamsFromBinaryFileOrDie(const char* param_file,
|
||||
tensorflow::GraphDef* param) {
|
||||
CHECK(ReadProtoFromBinaryFileTF(param_file, param))
|
||||
<< "Failed to parse GraphDef file: " << param_file;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
29
modules/dnn/src/tensorflow/tf_io.hpp
Normal file
29
modules/dnn/src/tensorflow/tf_io.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2016, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
/*
|
||||
Declaration of various functions which are related to Tensorflow models reading.
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_DNN_TF_IO_HPP__
|
||||
#define __OPENCV_DNN_TF_IO_HPP__
|
||||
#if HAVE_PROTOBUF
|
||||
|
||||
#include "graph.pb.h"
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
|
||||
// Read parameters from a file into a GraphDef proto message.
|
||||
void ReadTFNetParamsFromBinaryFileOrDie(const char* param_file,
|
||||
tensorflow::GraphDef* param);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
60
modules/dnn/src/tensorflow/types.proto
Normal file
60
modules/dnn/src/tensorflow/types.proto
Normal file
@ -0,0 +1,60 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package tensorflow;
|
||||
option cc_enable_arenas = true;
|
||||
option java_outer_classname = "TypesProtos";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "org.tensorflow.framework";
|
||||
|
||||
enum DataType {
|
||||
// Not a legal value for DataType. Used to indicate a DataType field
|
||||
// has not been set.
|
||||
DT_INVALID = 0;
|
||||
|
||||
// Data types that all computation devices are expected to be
|
||||
// capable to support.
|
||||
DT_FLOAT = 1;
|
||||
DT_DOUBLE = 2;
|
||||
DT_INT32 = 3;
|
||||
DT_UINT8 = 4;
|
||||
DT_INT16 = 5;
|
||||
DT_INT8 = 6;
|
||||
DT_STRING = 7;
|
||||
DT_COMPLEX64 = 8; // Single-precision complex
|
||||
DT_INT64 = 9;
|
||||
DT_BOOL = 10;
|
||||
DT_QINT8 = 11; // Quantized int8
|
||||
DT_QUINT8 = 12; // Quantized uint8
|
||||
DT_QINT32 = 13; // Quantized int32
|
||||
DT_BFLOAT16 = 14; // Float32 truncated to 16 bits. Only for cast ops.
|
||||
DT_QINT16 = 15; // Quantized int16
|
||||
DT_QUINT16 = 16; // Quantized uint16
|
||||
DT_UINT16 = 17;
|
||||
DT_COMPLEX128 = 18; // Double-precision complex
|
||||
DT_HALF = 19;
|
||||
|
||||
// TODO(josh11b): DT_GENERIC_PROTO = ??;
|
||||
// TODO(jeff,josh11b): DT_UINT64? DT_UINT32?
|
||||
|
||||
// Do not use! These are only for parameters. Every enum above
|
||||
// should have a corresponding value below (verified by types_test).
|
||||
DT_FLOAT_REF = 101;
|
||||
DT_DOUBLE_REF = 102;
|
||||
DT_INT32_REF = 103;
|
||||
DT_UINT8_REF = 104;
|
||||
DT_INT16_REF = 105;
|
||||
DT_INT8_REF = 106;
|
||||
DT_STRING_REF = 107;
|
||||
DT_COMPLEX64_REF = 108;
|
||||
DT_INT64_REF = 109;
|
||||
DT_BOOL_REF = 110;
|
||||
DT_QINT8_REF = 111;
|
||||
DT_QUINT8_REF = 112;
|
||||
DT_QINT32_REF = 113;
|
||||
DT_BFLOAT16_REF = 114;
|
||||
DT_QINT16_REF = 115;
|
||||
DT_QUINT16_REF = 116;
|
||||
DT_UINT16_REF = 117;
|
||||
DT_COMPLEX128_REF = 118;
|
||||
DT_HALF_REF = 119;
|
||||
}
|
31
modules/dnn/src/tensorflow/versions.proto
Normal file
31
modules/dnn/src/tensorflow/versions.proto
Normal file
@ -0,0 +1,31 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package tensorflow;
|
||||
option cc_enable_arenas = true;
|
||||
option java_outer_classname = "VersionsProtos";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "org.tensorflow.framework";
|
||||
|
||||
// Version information for a piece of serialized data
|
||||
//
|
||||
// There are different types of versions for each type of data
|
||||
// (GraphDef, etc.), but they all have the same common shape
|
||||
// described here.
|
||||
//
|
||||
// Each consumer has "consumer" and "min_producer" versions (specified
|
||||
// elsewhere). A consumer is allowed to consume this data if
|
||||
//
|
||||
// producer >= min_producer
|
||||
// consumer >= min_consumer
|
||||
// consumer not in bad_consumers
|
||||
//
|
||||
message VersionDef {
|
||||
// The version of the code that produced this data.
|
||||
int32 producer = 1;
|
||||
|
||||
// Any consumer below this version is not allowed to consume this data.
|
||||
int32 min_consumer = 2;
|
||||
|
||||
// Specific consumer versions which are disallowed (e.g. due to bugs).
|
||||
repeated int32 bad_consumers = 3;
|
||||
};
|
36
modules/dnn/src/torch/COPYRIGHT.txt
Normal file
36
modules/dnn/src/torch/COPYRIGHT.txt
Normal file
@ -0,0 +1,36 @@
|
||||
Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert)
|
||||
Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu)
|
||||
Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu)
|
||||
Copyright (c) 2011-2013 NYU (Clement Farabet)
|
||||
Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston)
|
||||
Copyright (c) 2006 Idiap Research Institute (Samy Bengio)
|
||||
Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz)
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the names of Deepmind Technologies, NYU, NEC Laboratories America
|
||||
and IDIAP Research Institute nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
795
modules/dnn/src/torch/THDiskFile.cpp
Normal file
795
modules/dnn/src/torch/THDiskFile.cpp
Normal file
@ -0,0 +1,795 @@
|
||||
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
|
||||
#include "THGeneral.h"
|
||||
#include "THDiskFile.h"
|
||||
#include "THFilePrivate.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
typedef struct THDiskFile__
|
||||
{
|
||||
THFile file;
|
||||
|
||||
FILE *handle;
|
||||
char *name;
|
||||
int isNativeEncoding;
|
||||
int longSize;
|
||||
|
||||
} THDiskFile;
|
||||
|
||||
static int THDiskFile_isOpened(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)self;
|
||||
return (dfself->handle != NULL);
|
||||
}
|
||||
|
||||
const char *THDiskFile_name(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)self;
|
||||
return dfself->name;
|
||||
}
|
||||
|
||||
/* workaround mac osx lion ***insane*** fread bug */
|
||||
#ifdef __APPLE__
|
||||
static size_t fread__(void *ptr, size_t size, size_t nitems, FILE *stream)
|
||||
{
|
||||
size_t nread = 0;
|
||||
while(!feof(stream) && !ferror(stream) && (nread < nitems))
|
||||
nread += fread((char*)ptr+nread*size, size, THMin(2147483648UL/size, nitems-nread), stream);
|
||||
return nread;
|
||||
}
|
||||
#else
|
||||
#define fread__ fread
|
||||
#endif
|
||||
|
||||
#define READ_WRITE_METHODS(TYPE, TYPEC, ASCII_READ_ELEM, ASCII_WRITE_ELEM) \
|
||||
static long THDiskFile_read##TYPEC(THFile *self, TYPE *data, long n) \
|
||||
{ \
|
||||
THDiskFile *dfself = (THDiskFile*)(self); \
|
||||
long nread = 0L; \
|
||||
\
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); \
|
||||
THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file"); \
|
||||
\
|
||||
if(dfself->file.isBinary) \
|
||||
{ \
|
||||
nread = fread__(data, sizeof(TYPE), n, dfself->handle); \
|
||||
if(!dfself->isNativeEncoding && (sizeof(TYPE) > 1) && (nread > 0)) \
|
||||
THDiskFile_reverseMemory(data, data, sizeof(TYPE), nread); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
long i; \
|
||||
for(i = 0; i < n; i++) \
|
||||
{ \
|
||||
ASCII_READ_ELEM; /* increment here result and break if wrong */ \
|
||||
} \
|
||||
if(dfself->file.isAutoSpacing && (n > 0)) \
|
||||
{ \
|
||||
int c = fgetc(dfself->handle); \
|
||||
if( (c != '\n') && (c != EOF) ) \
|
||||
ungetc(c, dfself->handle); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if(nread != n) \
|
||||
{ \
|
||||
dfself->file.hasError = 1; /* shouldn't we put hasError to 0 all the time ? */ \
|
||||
if(!dfself->file.isQuiet) \
|
||||
THError("read error: read %d blocks instead of %d", nread, n); \
|
||||
} \
|
||||
\
|
||||
return nread; \
|
||||
} \
|
||||
\
|
||||
static long THDiskFile_write##TYPEC(THFile *self, TYPE *data, long n) \
|
||||
{ \
|
||||
THDiskFile *dfself = (THDiskFile*)(self); \
|
||||
long nwrite = 0L; \
|
||||
\
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); \
|
||||
THArgCheck(dfself->file.isWritable, 1, "attempt to write in a read-only file"); \
|
||||
\
|
||||
if(dfself->file.isBinary) \
|
||||
{ \
|
||||
if(dfself->isNativeEncoding) \
|
||||
{ \
|
||||
nwrite = fwrite(data, sizeof(TYPE), n, dfself->handle); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if(sizeof(TYPE) > 1) \
|
||||
{ \
|
||||
char *buffer = (char*)THAlloc(sizeof(TYPE)*n); \
|
||||
THDiskFile_reverseMemory(buffer, data, sizeof(TYPE), n); \
|
||||
nwrite = fwrite(buffer, sizeof(TYPE), n, dfself->handle); \
|
||||
THFree(buffer); \
|
||||
} \
|
||||
else \
|
||||
nwrite = fwrite(data, sizeof(TYPE), n, dfself->handle); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
long i; \
|
||||
for(i = 0; i < n; i++) \
|
||||
{ \
|
||||
ASCII_WRITE_ELEM; \
|
||||
if( dfself->file.isAutoSpacing && (i < n-1) ) \
|
||||
fprintf(dfself->handle, " "); \
|
||||
} \
|
||||
if(dfself->file.isAutoSpacing && (n > 0)) \
|
||||
fprintf(dfself->handle, "\n"); \
|
||||
} \
|
||||
\
|
||||
if(nwrite != n) \
|
||||
{ \
|
||||
dfself->file.hasError = 1; \
|
||||
if(!dfself->file.isQuiet) \
|
||||
THError("write error: wrote %d blocks instead of %d", nwrite, n); \
|
||||
} \
|
||||
\
|
||||
return nwrite; \
|
||||
}
|
||||
|
||||
static int THDiskFile_mode(const char *mode, int *isReadable, int *isWritable)
|
||||
{
|
||||
*isReadable = 0;
|
||||
*isWritable = 0;
|
||||
if(strlen(mode) == 1)
|
||||
{
|
||||
if(*mode == 'r')
|
||||
{
|
||||
*isReadable = 1;
|
||||
return 1;
|
||||
}
|
||||
else if(*mode == 'w')
|
||||
{
|
||||
*isWritable = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if(strlen(mode) == 2)
|
||||
{
|
||||
if(mode[0] == 'r' && mode[1] == 'w')
|
||||
{
|
||||
*isReadable = 1;
|
||||
*isWritable = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void THDiskFile_synchronize(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
fflush(dfself->handle);
|
||||
}
|
||||
|
||||
static void THDiskFile_seek(THFile *self, long position)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
|
||||
#if defined(_WIN64)
|
||||
if(_fseeki64(dfself->handle, (__int64)position, SEEK_SET) < 0)
|
||||
#elif defined(_WIN32)
|
||||
if(fseek(dfself->handle, (long)position, SEEK_SET) < 0)
|
||||
#else
|
||||
if(fseeko(dfself->handle, (off_t)position, SEEK_SET) < 0)
|
||||
#endif
|
||||
{
|
||||
dfself->file.hasError = 1;
|
||||
if(!dfself->file.isQuiet)
|
||||
THError("unable to seek at position %d", position);
|
||||
}
|
||||
}
|
||||
|
||||
static void THDiskFile_seekEnd(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
|
||||
#if defined(_WIN64)
|
||||
if(_fseeki64(dfself->handle, 0L, SEEK_END) < 0)
|
||||
#elif defined(_WIN32)
|
||||
if(fseek(dfself->handle, 0L, SEEK_END) < 0)
|
||||
#else
|
||||
if(fseeko(dfself->handle, 0L, SEEK_END) < 0)
|
||||
#endif
|
||||
{
|
||||
dfself->file.hasError = 1;
|
||||
if(!dfself->file.isQuiet)
|
||||
THError("unable to seek at end of file");
|
||||
}
|
||||
}
|
||||
|
||||
static long THDiskFile_position(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
|
||||
#if defined(_WIN64)
|
||||
__int64 offset = _ftelli64(dfself->handle);
|
||||
#elif defined(_WIN32)
|
||||
long offset = ftell(dfself->handle);
|
||||
#else
|
||||
off_t offset = ftello(dfself->handle);
|
||||
#endif
|
||||
if (offset > -1)
|
||||
return (long)offset;
|
||||
else if(!dfself->file.isQuiet)
|
||||
THError("unable to obtain disk file offset (maybe a long overflow occurred)");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void THDiskFile_close(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
fclose(dfself->handle);
|
||||
dfself->handle = NULL;
|
||||
}
|
||||
|
||||
/* Little and Big Endian */
|
||||
|
||||
static void THDiskFile_reverseMemory(void *dst, const void *src, long blockSize, long numBlocks)
|
||||
{
|
||||
if(blockSize != 1)
|
||||
{
|
||||
long halfBlockSize = blockSize/2;
|
||||
char *charSrc = (char*)src;
|
||||
char *charDst = (char*)dst;
|
||||
long b, i;
|
||||
for(b = 0; b < numBlocks; b++)
|
||||
{
|
||||
for(i = 0; i < halfBlockSize; i++)
|
||||
{
|
||||
char z = charSrc[i];
|
||||
charDst[i] = charSrc[blockSize-1-i];
|
||||
charDst[blockSize-1-i] = z;
|
||||
}
|
||||
charSrc += blockSize;
|
||||
charDst += blockSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int THDiskFile_isLittleEndianCPU(void)
|
||||
{
|
||||
int x = 7;
|
||||
char *ptr = (char *)&x;
|
||||
|
||||
if(ptr[0] == 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int THDiskFile_isBigEndianCPU(void)
|
||||
{
|
||||
return(!THDiskFile_isLittleEndianCPU());
|
||||
}
|
||||
|
||||
void THDiskFile_nativeEndianEncoding(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
dfself->isNativeEncoding = 1;
|
||||
}
|
||||
|
||||
void THDiskFile_littleEndianEncoding(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
dfself->isNativeEncoding = THDiskFile_isLittleEndianCPU();
|
||||
}
|
||||
|
||||
void THDiskFile_bigEndianEncoding(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
dfself->isNativeEncoding = !THDiskFile_isLittleEndianCPU();
|
||||
}
|
||||
|
||||
/* End of Little and Big Endian Stuff */
|
||||
|
||||
void THDiskFile_longSize(THFile *self, int size)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
THArgCheck(size == 0 || size == 4 || size == 8, 1, "Invalid long size specified");
|
||||
dfself->longSize = size;
|
||||
}
|
||||
|
||||
void THDiskFile_noBuffer(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
if (setvbuf(dfself->handle, NULL, _IONBF, 0)) {
|
||||
THError("error: cannot disable buffer");
|
||||
}
|
||||
}
|
||||
|
||||
static void THDiskFile_free(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
if(dfself->handle)
|
||||
fclose(dfself->handle);
|
||||
THFree(dfself->name);
|
||||
THFree(dfself);
|
||||
}
|
||||
|
||||
/* READ_WRITE_METHODS(int, Bool, */
|
||||
/* int value = 0; int ret = fscanf(file->handle, "%d", &value); array[i] = (value ? 1 : 0); if(ret <= 0) break; else result++, */
|
||||
/* int value = (array[i] ? 1 : 0); nElemWritten = fprintf(file->handle, "%d", value), */
|
||||
/* true) */
|
||||
|
||||
/* Note that we do a trick */
|
||||
READ_WRITE_METHODS(unsigned char, Byte,
|
||||
nread = fread(data, 1, n, dfself->handle); break,
|
||||
nwrite = fwrite(data, 1, n, dfself->handle); break)
|
||||
|
||||
READ_WRITE_METHODS(char, Char,
|
||||
nread = fread(data, 1, n, dfself->handle); break,
|
||||
nwrite = fwrite(data, 1, n, dfself->handle); break)
|
||||
|
||||
READ_WRITE_METHODS(short, Short,
|
||||
int ret = fscanf(dfself->handle, "%hd", &data[i]); if(ret <= 0) break; else nread++,
|
||||
int ret = fprintf(dfself->handle, "%hd", data[i]); if(ret <= 0) break; else nwrite++)
|
||||
|
||||
READ_WRITE_METHODS(int, Int,
|
||||
int ret = fscanf(dfself->handle, "%d\n\r", &data[i]); if(ret <= 0) break; else nread++,
|
||||
int ret = fprintf(dfself->handle, "%d", data[i]); if(ret <= 0) break; else nwrite++)
|
||||
|
||||
/*READ_WRITE_METHODS(long, Long,
|
||||
int ret = fscanf(dfself->handle, "%ld", &data[i]); if(ret <= 0) break; else nread++,
|
||||
int ret = fprintf(dfself->handle, "%ld", data[i]); if(ret <= 0) break; else nwrite++)*/
|
||||
|
||||
READ_WRITE_METHODS(float, Float,
|
||||
int ret = fscanf(dfself->handle, "%g", &data[i]); if(ret <= 0) break; else nread++,
|
||||
int ret = fprintf(dfself->handle, "%.9g", data[i]); if(ret <= 0) break; else nwrite++)
|
||||
|
||||
READ_WRITE_METHODS(double, Double,
|
||||
int ret = fscanf(dfself->handle, "%lg", &data[i]); if(ret <= 0) break; else nread++,
|
||||
int ret = fprintf(dfself->handle, "%.17g", data[i]); if(ret <= 0) break; else nwrite++)
|
||||
|
||||
|
||||
/* For Long we need to rewrite everything, because of the special management of longSize */
|
||||
static long THDiskFile_readLong(THFile *self, int64 *data, long n)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
long nread = 0L;
|
||||
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file");
|
||||
|
||||
if(dfself->file.isBinary)
|
||||
{
|
||||
if(dfself->longSize == 0 || dfself->longSize == sizeof(int64))
|
||||
{
|
||||
nread = fread__(data, sizeof(int64), n, dfself->handle);
|
||||
if(!dfself->isNativeEncoding && (sizeof(int64) > 1) && (nread > 0))
|
||||
THDiskFile_reverseMemory(data, data, sizeof(int64), nread);
|
||||
} else if(dfself->longSize == 4)
|
||||
{
|
||||
nread = fread__(data, 4, n, dfself->handle);
|
||||
if(!dfself->isNativeEncoding && (nread > 0))
|
||||
THDiskFile_reverseMemory(data, data, 4, nread);
|
||||
long i;
|
||||
for(i = nread; i > 0; i--)
|
||||
data[i-1] = ((int *)data)[i-1];
|
||||
}
|
||||
else /* if(dfself->longSize == 8) */
|
||||
{
|
||||
int big_endian = !THDiskFile_isLittleEndianCPU();
|
||||
int32_t *buffer = (int32_t*)THAlloc(8*n);
|
||||
nread = fread__(buffer, 8, n, dfself->handle);
|
||||
long i;
|
||||
for(i = nread; i > 0; i--)
|
||||
data[i-1] = buffer[2*(i-1) + big_endian];
|
||||
THFree(buffer);
|
||||
if(!dfself->isNativeEncoding && (nread > 0))
|
||||
THDiskFile_reverseMemory(data, data, 4, nread);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long i;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
long d;
|
||||
int ret = fscanf(dfself->handle, "%ld", &d); if(ret <= 0) break; else nread++;
|
||||
data[i] = d;
|
||||
}
|
||||
if(dfself->file.isAutoSpacing && (n > 0))
|
||||
{
|
||||
int c = fgetc(dfself->handle);
|
||||
if( (c != '\n') && (c != EOF) )
|
||||
ungetc(c, dfself->handle);
|
||||
}
|
||||
}
|
||||
|
||||
if(nread != n)
|
||||
{
|
||||
dfself->file.hasError = 1; /* shouldn't we put hasError to 0 all the time ? */
|
||||
if(!dfself->file.isQuiet)
|
||||
THError("read error: read %d blocks instead of %d", nread, n);
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
static long THDiskFile_writeLong(THFile *self, int64 *data, long n)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
long nwrite = 0L;
|
||||
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
THArgCheck(dfself->file.isWritable, 1, "attempt to write in a read-only file");
|
||||
|
||||
if(dfself->file.isBinary)
|
||||
{
|
||||
if(dfself->longSize == 0 || dfself->longSize == sizeof(long))
|
||||
{
|
||||
if(dfself->isNativeEncoding)
|
||||
{
|
||||
nwrite = fwrite(data, sizeof(long), n, dfself->handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *buffer = (char*)THAlloc(sizeof(long)*n);
|
||||
THDiskFile_reverseMemory(buffer, data, sizeof(long), n);
|
||||
nwrite = fwrite(buffer, sizeof(long), n, dfself->handle);
|
||||
THFree(buffer);
|
||||
}
|
||||
} else if(dfself->longSize == 4)
|
||||
{
|
||||
int32_t *buffer = (int32_t *)THAlloc(4*n);
|
||||
long i;
|
||||
for(i = 0; i < n; i++)
|
||||
buffer[i] = data[i];
|
||||
if(!dfself->isNativeEncoding)
|
||||
THDiskFile_reverseMemory(buffer, buffer, 4, n);
|
||||
nwrite = fwrite(buffer, 4, n, dfself->handle);
|
||||
THFree(buffer);
|
||||
}
|
||||
else /* if(dfself->longSize == 8) */
|
||||
{
|
||||
int big_endian = !THDiskFile_isLittleEndianCPU();
|
||||
int32_t *buffer = (int32_t*)THAlloc(8*n);
|
||||
long i;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
buffer[2*i + !big_endian] = 0;
|
||||
buffer[2*i + big_endian] = data[i];
|
||||
}
|
||||
if(!dfself->isNativeEncoding)
|
||||
THDiskFile_reverseMemory(buffer, buffer, 8, n);
|
||||
nwrite = fwrite(buffer, 8, n, dfself->handle);
|
||||
THFree(buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long i;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
long res = 0;
|
||||
int ret = fprintf(dfself->handle, "%ld", res); data[i] = res; if(ret <= 0) break; else nwrite++;
|
||||
if( dfself->file.isAutoSpacing && (i < n-1) )
|
||||
fprintf(dfself->handle, " ");
|
||||
}
|
||||
if(dfself->file.isAutoSpacing && (n > 0))
|
||||
fprintf(dfself->handle, "\n");
|
||||
}
|
||||
|
||||
if(nwrite != n)
|
||||
{
|
||||
dfself->file.hasError = 1;
|
||||
if(!dfself->file.isQuiet)
|
||||
THError("write error: wrote %d blocks instead of %d", nwrite, n);
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
}
|
||||
|
||||
static long THDiskFile_readString(THFile *self, const char *format, char **str_)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file");
|
||||
THArgCheck((strlen(format) >= 2 ? (format[0] == '*') && (format[1] == 'a' || format[1] == 'l') : 0), 2, "format must be '*a' or '*l'");
|
||||
|
||||
/* note: the string won't survive long, as it is copied into lua */
|
||||
/* so 1024 is not that big... */
|
||||
#define TBRS_BSZ 1024L
|
||||
|
||||
if(format[1] == 'a')
|
||||
{
|
||||
char *p = (char*)THAlloc(TBRS_BSZ);
|
||||
long total = TBRS_BSZ;
|
||||
long pos = 0L;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if(total-pos == 0) /* we need more space! */
|
||||
{
|
||||
total += TBRS_BSZ;
|
||||
p = (char*)THRealloc(p, total);
|
||||
}
|
||||
pos += fread(p+pos, 1, total-pos, dfself->handle);
|
||||
if (pos < total) /* eof? */
|
||||
{
|
||||
if(pos == 0L)
|
||||
{
|
||||
THFree(p);
|
||||
dfself->file.hasError = 1;
|
||||
if(!dfself->file.isQuiet)
|
||||
THError("read error: read 0 blocks instead of 1");
|
||||
|
||||
*str_ = NULL;
|
||||
return 0;
|
||||
}
|
||||
*str_ = p;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *p = (char*)THAlloc(TBRS_BSZ);
|
||||
long total = TBRS_BSZ;
|
||||
long pos = 0L;
|
||||
long size;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if(total-pos <= 1) /* we can only write '\0' in there! */
|
||||
{
|
||||
total += TBRS_BSZ;
|
||||
p = (char*)THRealloc(p, total);
|
||||
}
|
||||
if (fgets(p+pos, total-pos, dfself->handle) == NULL) /* eof? */
|
||||
{
|
||||
if(pos == 0L)
|
||||
{
|
||||
THFree(p);
|
||||
dfself->file.hasError = 1;
|
||||
if(!dfself->file.isQuiet)
|
||||
THError("read error: read 0 blocks instead of 1");
|
||||
|
||||
*str_ = NULL;
|
||||
return 0;
|
||||
}
|
||||
*str_ = p;
|
||||
return pos;
|
||||
}
|
||||
size = strlen(p+pos);
|
||||
if (size == 0L || (p+pos)[size-1] != '\n')
|
||||
{
|
||||
pos += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos += size-1L; /* do not include `eol' */
|
||||
*str_ = p;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*str_ = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long THDiskFile_writeString(THFile *self, const char *str, long size)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
long nwrite;
|
||||
|
||||
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
|
||||
THArgCheck(dfself->file.isWritable, 1, "attempt to write in a read-only file");
|
||||
|
||||
nwrite = fwrite(str, 1, size, dfself->handle);
|
||||
if(nwrite != size)
|
||||
{
|
||||
dfself->file.hasError = 1;
|
||||
if(!dfself->file.isQuiet)
|
||||
THError("write error: wrote %ld blocks instead of %ld", nwrite, size);
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
}
|
||||
|
||||
THFile *THDiskFile_new(const char *name, const char *mode, int isQuiet)
|
||||
{
|
||||
static struct THFileVTable vtable = {
|
||||
THDiskFile_isOpened,
|
||||
|
||||
THDiskFile_readByte,
|
||||
THDiskFile_readChar,
|
||||
THDiskFile_readShort,
|
||||
THDiskFile_readInt,
|
||||
THDiskFile_readLong,
|
||||
THDiskFile_readFloat,
|
||||
THDiskFile_readDouble,
|
||||
THDiskFile_readString,
|
||||
|
||||
THDiskFile_writeByte,
|
||||
THDiskFile_writeChar,
|
||||
THDiskFile_writeShort,
|
||||
THDiskFile_writeInt,
|
||||
THDiskFile_writeLong,
|
||||
THDiskFile_writeFloat,
|
||||
THDiskFile_writeDouble,
|
||||
THDiskFile_writeString,
|
||||
|
||||
THDiskFile_synchronize,
|
||||
THDiskFile_seek,
|
||||
THDiskFile_seekEnd,
|
||||
THDiskFile_position,
|
||||
THDiskFile_close,
|
||||
THDiskFile_free
|
||||
};
|
||||
|
||||
int isReadable;
|
||||
int isWritable;
|
||||
FILE *handle;
|
||||
THDiskFile *self;
|
||||
|
||||
THArgCheck(THDiskFile_mode(mode, &isReadable, &isWritable), 2, "file mode should be 'r','w' or 'rw'");
|
||||
|
||||
if( isReadable && isWritable )
|
||||
{
|
||||
handle = fopen(name, "r+b");
|
||||
if(!handle)
|
||||
{
|
||||
handle = fopen(name, "wb");
|
||||
if(handle)
|
||||
{
|
||||
fclose(handle);
|
||||
handle = fopen(name, "r+b");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
handle = fopen(name, (isReadable ? "rb" : "wb"));
|
||||
|
||||
if(!handle)
|
||||
{
|
||||
if(isQuiet)
|
||||
return 0;
|
||||
else
|
||||
THError("cannot open <%s> in mode %c%c", name, (isReadable ? 'r' : ' '), (isWritable ? 'w' : ' '));
|
||||
}
|
||||
|
||||
self = (THDiskFile*)THAlloc(sizeof(THDiskFile));
|
||||
|
||||
self->handle = handle;
|
||||
self->name = (char*)THAlloc(strlen(name)+1);
|
||||
strcpy(self->name, name);
|
||||
self->isNativeEncoding = 1;
|
||||
self->longSize = 0;
|
||||
|
||||
self->file.vtable = &vtable;
|
||||
self->file.isQuiet = isQuiet;
|
||||
self->file.isReadable = isReadable;
|
||||
self->file.isWritable = isWritable;
|
||||
self->file.isBinary = 0;
|
||||
self->file.isAutoSpacing = 1;
|
||||
self->file.hasError = 0;
|
||||
|
||||
return (THFile*)self;
|
||||
}
|
||||
|
||||
/* PipeFile */
|
||||
|
||||
static int THPipeFile_mode(const char *mode, int *isReadable, int *isWritable)
|
||||
{
|
||||
*isReadable = 0;
|
||||
*isWritable = 0;
|
||||
if(strlen(mode) == 1)
|
||||
{
|
||||
if(*mode == 'r')
|
||||
{
|
||||
*isReadable = 1;
|
||||
return 1;
|
||||
}
|
||||
else if(*mode == 'w')
|
||||
{
|
||||
*isWritable = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void THPipeFile_free(THFile *self)
|
||||
{
|
||||
THDiskFile *dfself = (THDiskFile*)(self);
|
||||
if(dfself->handle)
|
||||
pclose(dfself->handle);
|
||||
THFree(dfself->name);
|
||||
THFree(dfself);
|
||||
}
|
||||
|
||||
THFile *THPipeFile_new(const char *name, const char *mode, int isQuiet)
|
||||
{
|
||||
static struct THFileVTable vtable = {
|
||||
THDiskFile_isOpened,
|
||||
|
||||
THDiskFile_readByte,
|
||||
THDiskFile_readChar,
|
||||
THDiskFile_readShort,
|
||||
THDiskFile_readInt,
|
||||
THDiskFile_readLong,
|
||||
THDiskFile_readFloat,
|
||||
THDiskFile_readDouble,
|
||||
THDiskFile_readString,
|
||||
|
||||
THDiskFile_writeByte,
|
||||
THDiskFile_writeChar,
|
||||
THDiskFile_writeShort,
|
||||
THDiskFile_writeInt,
|
||||
THDiskFile_writeLong,
|
||||
THDiskFile_writeFloat,
|
||||
THDiskFile_writeDouble,
|
||||
THDiskFile_writeString,
|
||||
|
||||
THDiskFile_synchronize,
|
||||
THDiskFile_seek,
|
||||
THDiskFile_seekEnd,
|
||||
THDiskFile_position,
|
||||
THDiskFile_close,
|
||||
THPipeFile_free
|
||||
};
|
||||
|
||||
int isReadable;
|
||||
int isWritable;
|
||||
FILE *handle;
|
||||
THDiskFile *self;
|
||||
|
||||
THArgCheck(THPipeFile_mode(mode, &isReadable, &isWritable), 2, "file mode should be 'r','w'");
|
||||
|
||||
#ifdef _WIN32
|
||||
handle = popen(name, (isReadable ? "rb" : "wb"));
|
||||
#else
|
||||
handle = popen(name, (isReadable ? "r" : "w"));
|
||||
#endif
|
||||
|
||||
if(!handle)
|
||||
{
|
||||
if(isQuiet)
|
||||
return 0;
|
||||
else
|
||||
THError("cannot open <%s> in mode %c%c", name, (isReadable ? 'r' : ' '), (isWritable ? 'w' : ' '));
|
||||
}
|
||||
|
||||
self = (THDiskFile*)THAlloc(sizeof(THDiskFile));
|
||||
|
||||
self->handle = handle;
|
||||
self->name = (char*)THAlloc(strlen(name)+1);
|
||||
strcpy(self->name, name);
|
||||
self->isNativeEncoding = 1;
|
||||
self->longSize = 0;
|
||||
|
||||
self->file.vtable = &vtable;
|
||||
self->file.isQuiet = isQuiet;
|
||||
self->file.isReadable = isReadable;
|
||||
self->file.isWritable = isWritable;
|
||||
self->file.isBinary = 0;
|
||||
self->file.isAutoSpacing = 1;
|
||||
self->file.hasError = 0;
|
||||
|
||||
return (THFile*)self;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
19
modules/dnn/src/torch/THDiskFile.h
Normal file
19
modules/dnn/src/torch/THDiskFile.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef TH_DISK_FILE_INC
|
||||
#define TH_DISK_FILE_INC
|
||||
|
||||
#include "THFile.h"
|
||||
|
||||
TH_API THFile *THDiskFile_new(const char *name, const char *mode, int isQuiet);
|
||||
TH_API THFile *THPipeFile_new(const char *name, const char *mode, int isQuiet);
|
||||
|
||||
TH_API const char *THDiskFile_name(THFile *self);
|
||||
|
||||
TH_API int THDiskFile_isLittleEndianCPU(void);
|
||||
TH_API int THDiskFile_isBigEndianCPU(void);
|
||||
TH_API void THDiskFile_nativeEndianEncoding(THFile *self);
|
||||
TH_API void THDiskFile_littleEndianEncoding(THFile *self);
|
||||
TH_API void THDiskFile_bigEndianEncoding(THFile *self);
|
||||
TH_API void THDiskFile_longSize(THFile *self, int size);
|
||||
TH_API void THDiskFile_noBuffer(THFile *self);
|
||||
|
||||
#endif
|
163
modules/dnn/src/torch/THFile.cpp
Normal file
163
modules/dnn/src/torch/THFile.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
|
||||
#include "THFile.h"
|
||||
#include "THFilePrivate.h"
|
||||
#include <opencv2/core.hpp>
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#define IMPLEMENT_THFILE_RW(TYPEC, TYPE) \
|
||||
long THFile_read##TYPEC##Raw(THFile *self, TYPE *data, long n) \
|
||||
{ \
|
||||
return (*self->vtable->read##TYPEC)(self, data, n); \
|
||||
} \
|
||||
\
|
||||
long THFile_write##TYPEC##Raw(THFile *self, TYPE *data, long n) \
|
||||
{ \
|
||||
return (*self->vtable->write##TYPEC)(self, data, n); \
|
||||
}
|
||||
|
||||
IMPLEMENT_THFILE_RW(Byte, unsigned char)
|
||||
IMPLEMENT_THFILE_RW(Char, char)
|
||||
IMPLEMENT_THFILE_RW(Short, short)
|
||||
IMPLEMENT_THFILE_RW(Int, int)
|
||||
IMPLEMENT_THFILE_RW(Long, int64)
|
||||
IMPLEMENT_THFILE_RW(Float, float)
|
||||
IMPLEMENT_THFILE_RW(Double, double)
|
||||
|
||||
long THFile_readStringRaw(THFile *self, const char *format, char **str_)
|
||||
{
|
||||
return self->vtable->readString(self, format, str_);
|
||||
}
|
||||
|
||||
long THFile_writeStringRaw(THFile *self, const char *str, long size)
|
||||
{
|
||||
return self->vtable->writeString(self, str, size);
|
||||
}
|
||||
|
||||
void THFile_synchronize(THFile *self)
|
||||
{
|
||||
self->vtable->synchronize(self);
|
||||
}
|
||||
|
||||
void THFile_seek(THFile *self, long position)
|
||||
{
|
||||
self->vtable->seek(self, position);
|
||||
}
|
||||
|
||||
void THFile_seekEnd(THFile *self)
|
||||
{
|
||||
self->vtable->seekEnd(self);
|
||||
}
|
||||
|
||||
long THFile_position(THFile *self)
|
||||
{
|
||||
return self->vtable->position(self);
|
||||
}
|
||||
|
||||
void THFile_close(THFile *self)
|
||||
{
|
||||
self->vtable->close(self);
|
||||
}
|
||||
|
||||
void THFile_free(THFile *self)
|
||||
{
|
||||
self->vtable->free(self);
|
||||
}
|
||||
|
||||
int THFile_isOpened(THFile *self)
|
||||
{
|
||||
return self->vtable->isOpened(self);
|
||||
}
|
||||
|
||||
#define IMPLEMENT_THFILE_FLAGS(FLAG) \
|
||||
int THFile_##FLAG(THFile *self) \
|
||||
{ \
|
||||
return self->FLAG; \
|
||||
}
|
||||
|
||||
IMPLEMENT_THFILE_FLAGS(isQuiet)
|
||||
IMPLEMENT_THFILE_FLAGS(isReadable)
|
||||
IMPLEMENT_THFILE_FLAGS(isWritable)
|
||||
IMPLEMENT_THFILE_FLAGS(isBinary)
|
||||
IMPLEMENT_THFILE_FLAGS(isAutoSpacing)
|
||||
IMPLEMENT_THFILE_FLAGS(hasError)
|
||||
|
||||
void THFile_binary(THFile *self)
|
||||
{
|
||||
self->isBinary = 1;
|
||||
}
|
||||
|
||||
void THFile_ascii(THFile *self)
|
||||
{
|
||||
self->isBinary = 0;
|
||||
}
|
||||
|
||||
void THFile_autoSpacing(THFile *self)
|
||||
{
|
||||
self->isAutoSpacing = 1;
|
||||
}
|
||||
|
||||
void THFile_noAutoSpacing(THFile *self)
|
||||
{
|
||||
self->isAutoSpacing = 0;
|
||||
}
|
||||
|
||||
void THFile_quiet(THFile *self)
|
||||
{
|
||||
self->isQuiet = 1;
|
||||
}
|
||||
|
||||
void THFile_pedantic(THFile *self)
|
||||
{
|
||||
self->isQuiet = 0;
|
||||
}
|
||||
|
||||
void THFile_clearError(THFile *self)
|
||||
{
|
||||
self->hasError = 0;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_THFILE_SCALAR(TYPEC, TYPE) \
|
||||
TYPE THFile_read##TYPEC##Scalar(THFile *self) \
|
||||
{ \
|
||||
TYPE scalar; \
|
||||
THFile_read##TYPEC##Raw(self, &scalar, 1); \
|
||||
return scalar; \
|
||||
} \
|
||||
\
|
||||
void THFile_write##TYPEC##Scalar(THFile *self, TYPE scalar) \
|
||||
{ \
|
||||
THFile_write##TYPEC##Raw(self, &scalar, 1); \
|
||||
}
|
||||
|
||||
IMPLEMENT_THFILE_SCALAR(Byte, unsigned char)
|
||||
IMPLEMENT_THFILE_SCALAR(Char, char)
|
||||
IMPLEMENT_THFILE_SCALAR(Short, short)
|
||||
IMPLEMENT_THFILE_SCALAR(Int, int)
|
||||
IMPLEMENT_THFILE_SCALAR(Long, int64)
|
||||
IMPLEMENT_THFILE_SCALAR(Float, float)
|
||||
IMPLEMENT_THFILE_SCALAR(Double, double)
|
||||
|
||||
/*
|
||||
#define IMPLEMENT_THFILE_STORAGE(TYPEC, TYPE) \
|
||||
long THFile_read##TYPEC(THFile *self, TH##TYPEC##Storage *storage) \
|
||||
{ \
|
||||
return THFile_read##TYPEC##Raw(self, storage->data, storage->size); \
|
||||
} \
|
||||
\
|
||||
long THFile_write##TYPEC(THFile *self, TH##TYPEC##Storage *storage) \
|
||||
{ \
|
||||
return THFile_write##TYPEC##Raw(self, storage->data, storage->size); \
|
||||
}
|
||||
|
||||
IMPLEMENT_THFILE_STORAGE(Byte, unsigned char)
|
||||
IMPLEMENT_THFILE_STORAGE(Char, char)
|
||||
IMPLEMENT_THFILE_STORAGE(Short, short)
|
||||
IMPLEMENT_THFILE_STORAGE(Int, int)
|
||||
IMPLEMENT_THFILE_STORAGE(Long, long)
|
||||
IMPLEMENT_THFILE_STORAGE(Float, float)
|
||||
IMPLEMENT_THFILE_STORAGE(Double, double)
|
||||
*/
|
||||
|
||||
}
|
||||
#endif
|
90
modules/dnn/src/torch/THFile.h
Normal file
90
modules/dnn/src/torch/THFile.h
Normal file
@ -0,0 +1,90 @@
|
||||
#ifndef TH_FILE_INC
|
||||
#define TH_FILE_INC
|
||||
|
||||
//#include "THStorage.h"
|
||||
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
|
||||
#include "THGeneral.h"
|
||||
#include "opencv2/core/hal/interface.h"
|
||||
|
||||
typedef struct THFile__ THFile;
|
||||
|
||||
TH_API int THFile_isOpened(THFile *self);
|
||||
TH_API int THFile_isQuiet(THFile *self);
|
||||
TH_API int THFile_isReadable(THFile *self);
|
||||
TH_API int THFile_isWritable(THFile *self);
|
||||
TH_API int THFile_isBinary(THFile *self);
|
||||
TH_API int THFile_isAutoSpacing(THFile *self);
|
||||
TH_API int THFile_hasError(THFile *self);
|
||||
|
||||
TH_API void THFile_binary(THFile *self);
|
||||
TH_API void THFile_ascii(THFile *self);
|
||||
TH_API void THFile_autoSpacing(THFile *self);
|
||||
TH_API void THFile_noAutoSpacing(THFile *self);
|
||||
TH_API void THFile_quiet(THFile *self);
|
||||
TH_API void THFile_pedantic(THFile *self);
|
||||
TH_API void THFile_clearError(THFile *self);
|
||||
|
||||
/* scalar */
|
||||
TH_API unsigned char THFile_readByteScalar(THFile *self);
|
||||
TH_API char THFile_readCharScalar(THFile *self);
|
||||
TH_API short THFile_readShortScalar(THFile *self);
|
||||
TH_API int THFile_readIntScalar(THFile *self);
|
||||
TH_API int64 THFile_readLongScalar(THFile *self);
|
||||
TH_API float THFile_readFloatScalar(THFile *self);
|
||||
TH_API double THFile_readDoubleScalar(THFile *self);
|
||||
|
||||
TH_API void THFile_writeByteScalar(THFile *self, unsigned char scalar);
|
||||
TH_API void THFile_writeCharScalar(THFile *self, char scalar);
|
||||
TH_API void THFile_writeShortScalar(THFile *self, short scalar);
|
||||
TH_API void THFile_writeIntScalar(THFile *self, int scalar);
|
||||
TH_API void THFile_writeLongScalar(THFile *self, int64 scalar);
|
||||
TH_API void THFile_writeFloatScalar(THFile *self, float scalar);
|
||||
TH_API void THFile_writeDoubleScalar(THFile *self, double scalar);
|
||||
|
||||
/* storage */
|
||||
/*
|
||||
TH_API long THFile_readByte(THFile *self, THByteStorage *storage);
|
||||
TH_API long THFile_readChar(THFile *self, THCharStorage *storage);
|
||||
TH_API long THFile_readShort(THFile *self, THShortStorage *storage);
|
||||
TH_API long THFile_readInt(THFile *self, THIntStorage *storage);
|
||||
TH_API long THFile_readLong(THFile *self, THLongStorage *storage);
|
||||
TH_API long THFile_readFloat(THFile *self, THFloatStorage *storage);
|
||||
TH_API long THFile_readDouble(THFile *self, THDoubleStorage *storage);
|
||||
|
||||
TH_API long THFile_writeByte(THFile *self, THByteStorage *storage);
|
||||
TH_API long THFile_writeChar(THFile *self, THCharStorage *storage);
|
||||
TH_API long THFile_writeShort(THFile *self, THShortStorage *storage);
|
||||
TH_API long THFile_writeInt(THFile *self, THIntStorage *storage);
|
||||
TH_API long THFile_writeLong(THFile *self, THLongStorage *storage);
|
||||
TH_API long THFile_writeFloat(THFile *self, THFloatStorage *storage);
|
||||
TH_API long THFile_writeDouble(THFile *self, THDoubleStorage *storage);
|
||||
*/
|
||||
|
||||
/* raw */
|
||||
TH_API long THFile_readByteRaw(THFile *self, unsigned char *data, long n);
|
||||
TH_API long THFile_readCharRaw(THFile *self, char *data, long n);
|
||||
TH_API long THFile_readShortRaw(THFile *self, short *data, long n);
|
||||
TH_API long THFile_readIntRaw(THFile *self, int *data, long n);
|
||||
TH_API long THFile_readLongRaw(THFile *self, int64 *data, long n);
|
||||
TH_API long THFile_readFloatRaw(THFile *self, float *data, long n);
|
||||
TH_API long THFile_readDoubleRaw(THFile *self, double *data, long n);
|
||||
TH_API long THFile_readStringRaw(THFile *self, const char *format, char **str_); /* you must deallocate str_ */
|
||||
|
||||
TH_API long THFile_writeByteRaw(THFile *self, unsigned char *data, long n);
|
||||
TH_API long THFile_writeCharRaw(THFile *self, char *data, long n);
|
||||
TH_API long THFile_writeShortRaw(THFile *self, short *data, long n);
|
||||
TH_API long THFile_writeIntRaw(THFile *self, int *data, long n);
|
||||
TH_API long THFile_writeLongRaw(THFile *self, int64 *data, long n);
|
||||
TH_API long THFile_writeFloatRaw(THFile *self, float *data, long n);
|
||||
TH_API long THFile_writeDoubleRaw(THFile *self, double *data, long n);
|
||||
TH_API long THFile_writeStringRaw(THFile *self, const char *str, long size);
|
||||
|
||||
TH_API void THFile_synchronize(THFile *self);
|
||||
TH_API void THFile_seek(THFile *self, long position);
|
||||
TH_API void THFile_seekEnd(THFile *self);
|
||||
TH_API long THFile_position(THFile *self);
|
||||
TH_API void THFile_close(THFile *self);
|
||||
TH_API void THFile_free(THFile *self);
|
||||
|
||||
#endif //defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
|
||||
#endif //TH_FILE_INC
|
43
modules/dnn/src/torch/THFilePrivate.h
Normal file
43
modules/dnn/src/torch/THFilePrivate.h
Normal file
@ -0,0 +1,43 @@
|
||||
struct THFile__
|
||||
{
|
||||
struct THFileVTable *vtable;
|
||||
|
||||
int isQuiet;
|
||||
int isReadable;
|
||||
int isWritable;
|
||||
int isBinary;
|
||||
int isAutoSpacing;
|
||||
int hasError;
|
||||
};
|
||||
|
||||
/* virtual table definition */
|
||||
|
||||
struct THFileVTable
|
||||
{
|
||||
int (*isOpened)(THFile *self);
|
||||
|
||||
long (*readByte)(THFile *self, unsigned char *data, long n);
|
||||
long (*readChar)(THFile *self, char *data, long n);
|
||||
long (*readShort)(THFile *self, short *data, long n);
|
||||
long (*readInt)(THFile *self, int *data, long n);
|
||||
long (*readLong)(THFile *self, int64 *data, long n);
|
||||
long (*readFloat)(THFile *self, float *data, long n);
|
||||
long (*readDouble)(THFile *self, double *data, long n);
|
||||
long (*readString)(THFile *self, const char *format, char **str_);
|
||||
|
||||
long (*writeByte)(THFile *self, unsigned char *data, long n);
|
||||
long (*writeChar)(THFile *self, char *data, long n);
|
||||
long (*writeShort)(THFile *self, short *data, long n);
|
||||
long (*writeInt)(THFile *self, int *data, long n);
|
||||
long (*writeLong)(THFile *self, int64 *data, long n);
|
||||
long (*writeFloat)(THFile *self, float *data, long n);
|
||||
long (*writeDouble)(THFile *self, double *data, long n);
|
||||
long (*writeString)(THFile *self, const char *str, long size);
|
||||
|
||||
void (*synchronize)(THFile *self);
|
||||
void (*seek)(THFile *self, long position);
|
||||
void (*seekEnd)(THFile *self);
|
||||
long (*position)(THFile *self);
|
||||
void (*close)(THFile *self);
|
||||
void (*free)(THFile *self);
|
||||
};
|
256
modules/dnn/src/torch/THGeneral.cpp
Normal file
256
modules/dnn/src/torch/THGeneral.cpp
Normal file
@ -0,0 +1,256 @@
|
||||
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#if defined(TH_DISABLE_HEAP_TRACKING)
|
||||
#elif (defined(__unix) || defined(_WIN32))
|
||||
#include <malloc.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <malloc/malloc.h>
|
||||
#endif
|
||||
|
||||
#include "THGeneral.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#ifndef TH_HAVE_THREAD
|
||||
#define __thread
|
||||
#endif
|
||||
|
||||
/* Torch Error Handling */
|
||||
static void defaultTorchErrorHandlerFunction(const char *msg, void*)
|
||||
{
|
||||
CV_Error(cv::Error::StsError, cv::String("Torch Error: ") + msg);
|
||||
}
|
||||
|
||||
static __thread void (*torchErrorHandlerFunction)(const char *msg, void *data) = defaultTorchErrorHandlerFunction;
|
||||
static __thread void *torchErrorHandlerData;
|
||||
|
||||
void _THError(const char *file, const int line, const char *fmt, ...)
|
||||
{
|
||||
char msg[2048];
|
||||
va_list args;
|
||||
|
||||
/* vasprintf not standard */
|
||||
/* vsnprintf: how to handle if does not exists? */
|
||||
va_start(args, fmt);
|
||||
int n = vsnprintf(msg, 2048, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if(n < 2048) {
|
||||
snprintf(msg + n, 2048 - n, " at %s:%d", file, line);
|
||||
}
|
||||
|
||||
(*torchErrorHandlerFunction)(msg, torchErrorHandlerData);
|
||||
}
|
||||
|
||||
void _THAssertionFailed(const char *file, const int line, const char *exp, const char *fmt, ...) {
|
||||
char msg[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(msg, 1024, fmt, args);
|
||||
va_end(args);
|
||||
_THError(file, line, "Assertion `%s' failed. %s", exp, msg);
|
||||
}
|
||||
|
||||
void THSetErrorHandler( void (*torchErrorHandlerFunction_)(const char *msg, void *data), void *data )
|
||||
{
|
||||
if(torchErrorHandlerFunction_)
|
||||
torchErrorHandlerFunction = torchErrorHandlerFunction_;
|
||||
else
|
||||
torchErrorHandlerFunction = defaultTorchErrorHandlerFunction;
|
||||
torchErrorHandlerData = data;
|
||||
}
|
||||
|
||||
/* Torch Arg Checking Handling */
|
||||
static void defaultTorchArgErrorHandlerFunction(int argNumber, const char *msg, void*)
|
||||
{
|
||||
if(msg)
|
||||
CV_Error(cv::Error::StsError, cv::format("Torch invalid argument %d: %s", argNumber, msg));
|
||||
else
|
||||
CV_Error(cv::Error::StsError, cv::format("Invalid argument %d", argNumber));
|
||||
}
|
||||
|
||||
static __thread void (*torchArgErrorHandlerFunction)(int argNumber, const char *msg, void *data) = defaultTorchArgErrorHandlerFunction;
|
||||
static __thread void *torchArgErrorHandlerData;
|
||||
|
||||
void _THArgCheck(const char *file, int line, int condition, int argNumber, const char *fmt, ...)
|
||||
{
|
||||
if(!condition) {
|
||||
char msg[2048];
|
||||
va_list args;
|
||||
|
||||
/* vasprintf not standard */
|
||||
/* vsnprintf: how to handle if does not exists? */
|
||||
va_start(args, fmt);
|
||||
int n = vsnprintf(msg, 2048, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if(n < 2048) {
|
||||
snprintf(msg + n, 2048 - n, " at %s:%d", file, line);
|
||||
}
|
||||
|
||||
(*torchArgErrorHandlerFunction)(argNumber, msg, torchArgErrorHandlerData);
|
||||
}
|
||||
}
|
||||
|
||||
void THSetArgErrorHandler( void (*torchArgErrorHandlerFunction_)(int argNumber, const char *msg, void *data), void *data )
|
||||
{
|
||||
if(torchArgErrorHandlerFunction_)
|
||||
torchArgErrorHandlerFunction = torchArgErrorHandlerFunction_;
|
||||
else
|
||||
torchArgErrorHandlerFunction = defaultTorchArgErrorHandlerFunction;
|
||||
torchArgErrorHandlerData = data;
|
||||
}
|
||||
|
||||
static __thread void (*torchGCFunction)(void *data) = NULL;
|
||||
static __thread void *torchGCData;
|
||||
static __thread long torchHeapSize = 0;
|
||||
static __thread long torchHeapSizeSoftMax = 300000000; // 300MB, adjusted upward dynamically
|
||||
|
||||
/* Optional hook for integrating with a garbage-collected frontend.
|
||||
*
|
||||
* If torch is running with a garbage-collected frontend (e.g. Lua),
|
||||
* the GC isn't aware of TH-allocated memory so may not know when it
|
||||
* needs to run. These hooks trigger the GC to run in two cases:
|
||||
*
|
||||
* (1) When a memory allocation (malloc, realloc, ...) fails
|
||||
* (2) When the total TH-allocated memory hits a dynamically-adjusted
|
||||
* soft maximum.
|
||||
*/
|
||||
void THSetGCHandler( void (*torchGCFunction_)(void *data), void *data )
|
||||
{
|
||||
torchGCFunction = torchGCFunction_;
|
||||
torchGCData = data;
|
||||
}
|
||||
|
||||
static long getAllocSize(void *ptr) {
|
||||
#if defined(TH_DISABLE_HEAP_TRACKING)
|
||||
return 0;
|
||||
#elif defined(__unix)
|
||||
return malloc_usable_size(ptr);
|
||||
#elif defined(__APPLE__)
|
||||
return malloc_size(ptr);
|
||||
#elif defined(_WIN32)
|
||||
return _msize(ptr);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* (1) if the torch-allocated heap size exceeds the soft max, run GC
|
||||
* (2) if post-GC heap size exceeds 80% of the soft max, increase the
|
||||
* soft max by 40%
|
||||
*/
|
||||
static void maybeTriggerGC() {
|
||||
if(torchGCFunction && torchHeapSize > torchHeapSizeSoftMax) {
|
||||
torchGCFunction(torchGCData);
|
||||
if(torchHeapSize > torchHeapSizeSoftMax * 0.8) {
|
||||
torchHeapSizeSoftMax = torchHeapSizeSoftMax * 1.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hooks into the TH heap tracking
|
||||
void THHeapUpdate(long size) {
|
||||
torchHeapSize += size;
|
||||
if (size > 0)
|
||||
maybeTriggerGC();
|
||||
}
|
||||
|
||||
static void* THAllocInternal(long size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (size > 5120)
|
||||
{
|
||||
#if (defined(__unix) || defined(__APPLE__)) && (!defined(DISABLE_POSIX_MEMALIGN))
|
||||
if (posix_memalign(&ptr, 64, size) != 0)
|
||||
ptr = NULL;
|
||||
/*
|
||||
#elif defined(_WIN32)
|
||||
ptr = _aligned_malloc(size, 64);
|
||||
*/
|
||||
#else
|
||||
ptr = malloc(size);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = malloc(size);
|
||||
}
|
||||
|
||||
THHeapUpdate(getAllocSize(ptr));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* THAlloc(long size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if(size < 0)
|
||||
THError("$ Torch: invalid memory size -- maybe an overflow?");
|
||||
|
||||
if(size == 0)
|
||||
return NULL;
|
||||
|
||||
ptr = THAllocInternal(size);
|
||||
|
||||
if(!ptr && torchGCFunction) {
|
||||
torchGCFunction(torchGCData);
|
||||
ptr = THAllocInternal(size);
|
||||
}
|
||||
|
||||
if(!ptr)
|
||||
THError("$ Torch: not enough memory: you tried to allocate %dGB. Buy new RAM!", size/1073741824);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* THRealloc(void *ptr, long size)
|
||||
{
|
||||
if(!ptr)
|
||||
return(THAlloc(size));
|
||||
|
||||
if(size == 0)
|
||||
{
|
||||
THFree(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(size < 0)
|
||||
THError("$ Torch: invalid memory size -- maybe an overflow?");
|
||||
|
||||
THHeapUpdate(-getAllocSize(ptr));
|
||||
void *newptr = realloc(ptr, size);
|
||||
|
||||
if(!newptr && torchGCFunction) {
|
||||
torchGCFunction(torchGCData);
|
||||
newptr = realloc(ptr, size);
|
||||
}
|
||||
THHeapUpdate(getAllocSize(newptr ? newptr : ptr));
|
||||
|
||||
if(!newptr)
|
||||
THError("$ Torch: not enough memory: you tried to reallocate %dGB. Buy new RAM!", size/1073741824);
|
||||
|
||||
return newptr;
|
||||
}
|
||||
|
||||
void THFree(void *ptr)
|
||||
{
|
||||
THHeapUpdate(-getAllocSize(ptr));
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
double THLog1p(const double x)
|
||||
{
|
||||
#if (defined(_MSC_VER) || defined(__MINGW32__))
|
||||
volatile double y = 1 + x;
|
||||
return log(y) - ((y-1)-x)/y ; /* cancels errors with IEEE arithmetic */
|
||||
#else
|
||||
return log1p(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
89
modules/dnn/src/torch/THGeneral.h
Normal file
89
modules/dnn/src/torch/THGeneral.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef TH_GENERAL_INC
|
||||
#define TH_GENERAL_INC
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define TH_EXTERNC extern "C"
|
||||
#else
|
||||
# define TH_EXTERNC extern
|
||||
#endif
|
||||
|
||||
#define TH_API TH_EXTERNC
|
||||
|
||||
#define THInf DBL_MAX
|
||||
|
||||
//#define TH_INLINE @TH_INLINE@
|
||||
|
||||
#ifndef __cplusplus
|
||||
//#define inline @TH_INLINE@
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
TH_API double THLog1p(const double x);
|
||||
TH_API void _THError(const char *file, const int line, const char *fmt, ...);
|
||||
TH_API void _THAssertionFailed(const char *file, const int line, const char *exp, const char *fmt, ...);
|
||||
TH_API void THSetErrorHandler( void (*torchErrorHandlerFunction)(const char *msg, void *data), void *data );
|
||||
TH_API void _THArgCheck(const char *file, int line, int condition, int argNumber, const char *fmt, ...);
|
||||
TH_API void THSetArgErrorHandler( void (*torchArgErrorHandlerFunction)(int argNumber, const char *msg, void *data), void *data );
|
||||
TH_API void* THAlloc(long size);
|
||||
TH_API void* THRealloc(void *ptr, long size);
|
||||
TH_API void THFree(void *ptr);
|
||||
TH_API void THSetGCHandler( void (*torchGCHandlerFunction)(void *data), void *data );
|
||||
// this hook should only be called by custom allocator functions
|
||||
TH_API void THHeapUpdate(long size);
|
||||
|
||||
#define THError(...) _THError(__FILE__, __LINE__, __VA_ARGS__)
|
||||
#define THArgCheck(...) _THArgCheck(__FILE__, __LINE__, __VA_ARGS__)
|
||||
#define THAssert(exp) \
|
||||
do { \
|
||||
if (!(exp)) { \
|
||||
_THAssertionFailed(__FILE__, __LINE__, #exp, ""); \
|
||||
} \
|
||||
} while(0)
|
||||
#define THAssertMsg(exp, ...) \
|
||||
do { \
|
||||
if (!(exp)) { \
|
||||
_THAssertionFailed(__FILE__, __LINE__, #exp, __VA_ARGS__); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define TH_CONCAT_STRING_2(x,y) TH_CONCAT_STRING_2_EXPAND(x,y)
|
||||
#define TH_CONCAT_STRING_2_EXPAND(x,y) #x #y
|
||||
|
||||
#define TH_CONCAT_STRING_3(x,y,z) TH_CONCAT_STRING_3_EXPAND(x,y,z)
|
||||
#define TH_CONCAT_STRING_3_EXPAND(x,y,z) #x #y #z
|
||||
|
||||
#define TH_CONCAT_STRING_4(x,y,z,w) TH_CONCAT_STRING_4_EXPAND(x,y,z,w)
|
||||
#define TH_CONCAT_STRING_4_EXPAND(x,y,z,w) #x #y #z #w
|
||||
|
||||
#define TH_CONCAT_2(x,y) TH_CONCAT_2_EXPAND(x,y)
|
||||
#define TH_CONCAT_2_EXPAND(x,y) x ## y
|
||||
|
||||
#define TH_CONCAT_3(x,y,z) TH_CONCAT_3_EXPAND(x,y,z)
|
||||
#define TH_CONCAT_3_EXPAND(x,y,z) x ## y ## z
|
||||
|
||||
#define TH_CONCAT_4_EXPAND(x,y,z,w) x ## y ## z ## w
|
||||
#define TH_CONCAT_4(x,y,z,w) TH_CONCAT_4_EXPAND(x,y,z,w)
|
||||
|
||||
#define THMin(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
#define THMax(X, Y) ((X) > (Y) ? (X) : (Y))
|
||||
|
||||
#if (defined(_MSC_VER) || defined(__MINGW32__))
|
||||
# define log1p(x) THLog1p(x)
|
||||
#define snprintf _snprintf
|
||||
#define popen _popen
|
||||
#define pclose _pclose
|
||||
#endif
|
||||
|
||||
#endif
|
1025
modules/dnn/src/torch/torch_importer.cpp
Normal file
1025
modules/dnn/src/torch/torch_importer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
140
modules/dnn/test/cityscapes_semsegm_test_enet.py
Normal file
140
modules/dnn/test/cityscapes_semsegm_test_enet.py
Normal file
@ -0,0 +1,140 @@
|
||||
import numpy as np
|
||||
import sys
|
||||
import os
|
||||
import fnmatch
|
||||
import argparse
|
||||
|
||||
try:
|
||||
import cv2 as cv
|
||||
except ImportError:
|
||||
raise ImportError('Can\'t find OpenCV Python module. If you\'ve built it from sources without installation, '
|
||||
'configure environemnt variable PYTHONPATH to "opencv_build_dir/lib" directory (with "python3" subdirectory if required)')
|
||||
try:
|
||||
import torch
|
||||
except ImportError:
|
||||
raise ImportError('Can\'t find pytorch. Please intall it by following instructions on the official site')
|
||||
|
||||
from torch.utils.serialization import load_lua
|
||||
from pascal_semsegm_test_fcn import eval_segm_result, get_conf_mat, get_metrics, DatasetImageFetch, SemSegmEvaluation
|
||||
from imagenet_cls_test_alexnet import Framework, DnnCaffeModel
|
||||
|
||||
|
||||
class NormalizePreproc:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def process(img):
|
||||
image_data = np.array(img).transpose(2, 0, 1).astype(np.float32)
|
||||
image_data = np.expand_dims(image_data, 0)
|
||||
image_data /= 255.0
|
||||
return image_data
|
||||
|
||||
|
||||
class CityscapesDataFetch(DatasetImageFetch):
|
||||
img_dir = ''
|
||||
segm_dir = ''
|
||||
segm_files = []
|
||||
colors = []
|
||||
i = 0
|
||||
|
||||
def __init__(self, img_dir, segm_dir, preproc):
|
||||
self.img_dir = img_dir
|
||||
self.segm_dir = segm_dir
|
||||
self.segm_files = sorted([img for img in self.locate('*_color.png', segm_dir)])
|
||||
self.colors = self.get_colors()
|
||||
self.data_prepoc = preproc
|
||||
self.i = 0
|
||||
|
||||
@staticmethod
|
||||
def get_colors():
|
||||
result = []
|
||||
colors_list = (
|
||||
(0, 0, 0), (128, 64, 128), (244, 35, 232), (70, 70, 70), (102, 102, 156), (190, 153, 153), (153, 153, 153),
|
||||
(250, 170, 30), (220, 220, 0), (107, 142, 35), (152, 251, 152), (70, 130, 180), (220, 20, 60), (255, 0, 0),
|
||||
(0, 0, 142), (0, 0, 70), (0, 60, 100), (0, 80, 100), (0, 0, 230), (119, 11, 32))
|
||||
|
||||
for c in colors_list:
|
||||
result.append(DatasetImageFetch.pix_to_c(c))
|
||||
return result
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
if self.i < len(self.segm_files):
|
||||
segm_file = self.segm_files[self.i]
|
||||
segm = cv.imread(segm_file, cv.IMREAD_COLOR)[:, :, ::-1]
|
||||
segm = cv.resize(segm, (1024, 512), interpolation=cv.INTER_NEAREST)
|
||||
|
||||
img_file = self.rreplace(self.img_dir + segm_file[len(self.segm_dir):], 'gtFine_color', 'leftImg8bit')
|
||||
assert os.path.exists(img_file)
|
||||
img = cv.imread(img_file, cv.IMREAD_COLOR)[:, :, ::-1]
|
||||
img = cv.resize(img, (1024, 512))
|
||||
|
||||
self.i += 1
|
||||
gt = self.color_to_gt(segm, self.colors)
|
||||
img = self.data_prepoc.process(img)
|
||||
return img, gt
|
||||
else:
|
||||
self.i = 0
|
||||
raise StopIteration
|
||||
|
||||
def get_num_classes(self):
|
||||
return len(self.colors)
|
||||
|
||||
@staticmethod
|
||||
def locate(pattern, root_path):
|
||||
for path, dirs, files in os.walk(os.path.abspath(root_path)):
|
||||
for filename in fnmatch.filter(files, pattern):
|
||||
yield os.path.join(path, filename)
|
||||
|
||||
@staticmethod
|
||||
def rreplace(s, old, new, occurrence=1):
|
||||
li = s.rsplit(old, occurrence)
|
||||
return new.join(li)
|
||||
|
||||
|
||||
class TorchModel(Framework):
|
||||
net = object
|
||||
|
||||
def __init__(self, model_file):
|
||||
self.net = load_lua(model_file)
|
||||
|
||||
def get_name(self):
|
||||
return 'Torch'
|
||||
|
||||
def get_output(self, input_blob):
|
||||
tensor = torch.FloatTensor(input_blob)
|
||||
out = self.net.forward(tensor).numpy()
|
||||
return out
|
||||
|
||||
|
||||
class DnnTorchModel(DnnCaffeModel):
|
||||
net = cv.dnn.Net()
|
||||
|
||||
def __init__(self, model_file):
|
||||
self.net = cv.dnn.readNetFromTorch(model_file)
|
||||
|
||||
def get_output(self, input_blob):
|
||||
self.net.setBlob("", input_blob)
|
||||
self.net.forward()
|
||||
return self.net.getBlob(self.net.getLayerNames()[-1])
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--imgs_dir", help="path to Cityscapes validation images dir, imgsfine/leftImg8bit/val")
|
||||
parser.add_argument("--segm_dir", help="path to Cityscapes dir with segmentation, gtfine/gtFine/val")
|
||||
parser.add_argument("--model", help="path to torch model, download it here: "
|
||||
"https://www.dropbox.com/sh/dywzk3gyb12hpe5/AAD5YkUa8XgMpHs2gCRgmCVCa")
|
||||
parser.add_argument("--log", help="path to logging file")
|
||||
args = parser.parse_args()
|
||||
|
||||
prep = NormalizePreproc()
|
||||
df = CityscapesDataFetch(args.imgs_dir, args.segm_dir, prep)
|
||||
|
||||
fw = [TorchModel(args.model),
|
||||
DnnTorchModel(args.model)]
|
||||
|
||||
segm_eval = SemSegmEvaluation(args.log)
|
||||
segm_eval.process(fw, df)
|
291
modules/dnn/test/cnpy.cpp
Normal file
291
modules/dnn/test/cnpy.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
//Copyright (C) 2011 Carl Rogers
|
||||
//Released under MIT License
|
||||
//license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
#include"cnpy.h"
|
||||
#include<complex>
|
||||
#include<cstdlib>
|
||||
#include<algorithm>
|
||||
#include<cstring>
|
||||
#include<iomanip>
|
||||
|
||||
char cnpy::BigEndianTest() {
|
||||
union
|
||||
{
|
||||
unsigned char x[2];
|
||||
short y;
|
||||
};
|
||||
x[0] = 1;
|
||||
x[1] = 0;
|
||||
|
||||
return y == 1 ? '<' : '>';
|
||||
}
|
||||
|
||||
char cnpy::map_type(const std::type_info& t)
|
||||
{
|
||||
if(t == typeid(float) ) return 'f';
|
||||
if(t == typeid(double) ) return 'f';
|
||||
if(t == typeid(long double) ) return 'f';
|
||||
|
||||
if(t == typeid(int) ) return 'i';
|
||||
if(t == typeid(char) ) return 'i';
|
||||
if(t == typeid(short) ) return 'i';
|
||||
if(t == typeid(long) ) return 'i';
|
||||
if(t == typeid(long long) ) return 'i';
|
||||
|
||||
if(t == typeid(unsigned char) ) return 'u';
|
||||
if(t == typeid(unsigned short) ) return 'u';
|
||||
if(t == typeid(unsigned long) ) return 'u';
|
||||
if(t == typeid(unsigned long long) ) return 'u';
|
||||
if(t == typeid(unsigned int) ) return 'u';
|
||||
|
||||
if(t == typeid(bool) ) return 'b';
|
||||
|
||||
if(t == typeid(std::complex<float>) ) return 'c';
|
||||
if(t == typeid(std::complex<double>) ) return 'c';
|
||||
if(t == typeid(std::complex<long double>) ) return 'c';
|
||||
|
||||
else return '?';
|
||||
}
|
||||
|
||||
template<> std::vector<char>& cnpy::operator+=(std::vector<char>& lhs, const std::string rhs) {
|
||||
lhs.insert(lhs.end(),rhs.begin(),rhs.end());
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<> std::vector<char>& cnpy::operator+=(std::vector<char>& lhs, const char* rhs) {
|
||||
//write in little endian
|
||||
size_t len = strlen(rhs);
|
||||
lhs.reserve(len);
|
||||
for(size_t byte = 0; byte < len; byte++) {
|
||||
lhs.push_back(rhs[byte]);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
void cnpy::parse_npy_header(FILE* fp, unsigned int& word_size, unsigned int*& shape, unsigned int& ndims, bool& fortran_order) {
|
||||
char buffer[256];
|
||||
size_t res = fread(buffer,sizeof(char),11,fp);
|
||||
if(res != 11)
|
||||
throw std::runtime_error("parse_npy_header: failed fread");
|
||||
std::string header = fgets(buffer,256,fp);
|
||||
cnpy_assert(header[header.size()-1] == '\n');
|
||||
|
||||
size_t loc1, loc2;
|
||||
|
||||
//fortran order
|
||||
loc1 = header.find("fortran_order")+16;
|
||||
fortran_order = (header.substr(loc1,5) == "True" ? true : false);
|
||||
|
||||
//shape
|
||||
loc1 = header.find("(");
|
||||
loc2 = header.find(")");
|
||||
std::string str_shape = header.substr(loc1+1,loc2-loc1-1);
|
||||
if(str_shape[str_shape.size()-1] == ',') ndims = 1;
|
||||
else ndims = (unsigned)std::count(str_shape.begin(),str_shape.end(),',')+1;
|
||||
shape = new unsigned int[ndims];
|
||||
for(unsigned int i = 0;i < ndims;i++) {
|
||||
loc1 = str_shape.find(",");
|
||||
shape[i] = atoi(str_shape.substr(0,loc1).c_str());
|
||||
str_shape = str_shape.substr(loc1+1);
|
||||
}
|
||||
|
||||
//endian, word size, data type
|
||||
//byte order code | stands for not applicable.
|
||||
//not sure when this applies except for byte array
|
||||
loc1 = header.find("descr")+9;
|
||||
bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
|
||||
cnpy_assert(littleEndian);
|
||||
|
||||
//char type = header[loc1+1];
|
||||
//assert(type == map_type(T));
|
||||
|
||||
std::string str_ws = header.substr(loc1+2);
|
||||
loc2 = str_ws.find("'");
|
||||
word_size = atoi(str_ws.substr(0,loc2).c_str());
|
||||
}
|
||||
|
||||
void cnpy::parse_zip_footer(FILE* fp, unsigned short& nrecs, unsigned int& global_header_size, unsigned int& global_header_offset)
|
||||
{
|
||||
std::vector<char> footer(22);
|
||||
fseek(fp,-22,SEEK_END);
|
||||
size_t res = fread(&footer[0],sizeof(char),22,fp);
|
||||
if(res != 22)
|
||||
throw std::runtime_error("parse_zip_footer: failed fread");
|
||||
|
||||
unsigned short disk_no, disk_start, nrecs_on_disk, comment_len;
|
||||
disk_no = *(unsigned short*) &footer[4];
|
||||
disk_start = *(unsigned short*) &footer[6];
|
||||
nrecs_on_disk = *(unsigned short*) &footer[8];
|
||||
nrecs = *(unsigned short*) &footer[10];
|
||||
global_header_size = *(unsigned int*) &footer[12];
|
||||
global_header_offset = *(unsigned int*) &footer[16];
|
||||
comment_len = *(unsigned short*) &footer[20];
|
||||
|
||||
cnpy_assert(disk_no == 0);
|
||||
cnpy_assert(disk_start == 0);
|
||||
cnpy_assert(nrecs_on_disk == nrecs);
|
||||
cnpy_assert(comment_len == 0);
|
||||
}
|
||||
|
||||
cnpy::NpyArray load_the_npy_file(FILE* fp) {
|
||||
unsigned int* shape;
|
||||
unsigned int ndims, word_size;
|
||||
bool fortran_order;
|
||||
cnpy::parse_npy_header(fp,word_size,shape,ndims,fortran_order);
|
||||
unsigned long long size = 1; //long long so no overflow when multiplying by word_size
|
||||
for(unsigned int i = 0;i < ndims;i++) size *= shape[i];
|
||||
|
||||
cnpy::NpyArray arr;
|
||||
arr.word_size = word_size;
|
||||
arr.shape = std::vector<unsigned int>(shape,shape+ndims);
|
||||
delete[] shape;
|
||||
arr.data = new char[size*word_size];
|
||||
arr.fortran_order = fortran_order;
|
||||
size_t nread = fread(arr.data,word_size,size,fp);
|
||||
if(nread != size)
|
||||
throw std::runtime_error("load_the_npy_file: failed fread");
|
||||
return arr;
|
||||
}
|
||||
|
||||
cnpy::npz_t cnpy::npz_load(std::string fname) {
|
||||
FILE* fp = fopen(fname.c_str(),"rb");
|
||||
|
||||
if(!fp) printf("npz_load: Error! Unable to open file %s!\n",fname.c_str());
|
||||
cnpy_assert(fp);
|
||||
|
||||
cnpy::npz_t arrays;
|
||||
|
||||
while(1) {
|
||||
std::vector<char> local_header(30);
|
||||
size_t headerres = fread(&local_header[0],sizeof(char),30,fp);
|
||||
if(headerres != 30)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
|
||||
//if we've reached the global header, stop reading
|
||||
if(local_header[2] != 0x03 || local_header[3] != 0x04) break;
|
||||
|
||||
//read in the variable name
|
||||
unsigned short name_len = *(unsigned short*) &local_header[26];
|
||||
std::string varname(name_len,' ');
|
||||
size_t vname_res = fread(&varname[0],sizeof(char),name_len,fp);
|
||||
if(vname_res != name_len)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
|
||||
//erase the lagging .npy
|
||||
varname.erase(varname.end()-4,varname.end());
|
||||
|
||||
//read in the extra field
|
||||
unsigned short extra_field_len = *(unsigned short*) &local_header[28];
|
||||
if(extra_field_len > 0) {
|
||||
std::vector<char> buff(extra_field_len);
|
||||
size_t efield_res = fread(&buff[0],sizeof(char),extra_field_len,fp);
|
||||
if(efield_res != extra_field_len)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
}
|
||||
|
||||
arrays[varname] = load_the_npy_file(fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return arrays;
|
||||
}
|
||||
|
||||
cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) {
|
||||
FILE* fp = fopen(fname.c_str(),"rb");
|
||||
|
||||
if(!fp) {
|
||||
throw std::runtime_error("npz_load: Error! Unable to open file " + fname + "!\n");
|
||||
}
|
||||
|
||||
while(1) {
|
||||
std::vector<char> local_header(30);
|
||||
size_t header_res = fread(&local_header[0],sizeof(char),30,fp);
|
||||
if(header_res != 30)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
|
||||
//if we've reached the global header, stop reading
|
||||
if(local_header[2] != 0x03 || local_header[3] != 0x04) break;
|
||||
|
||||
//read in the variable name
|
||||
unsigned short name_len = *(unsigned short*) &local_header[26];
|
||||
std::string vname(name_len,' ');
|
||||
size_t vname_res = fread(&vname[0],sizeof(char),name_len,fp);
|
||||
if(vname_res != name_len)
|
||||
throw std::runtime_error("npz_load: failed fread");
|
||||
vname.erase(vname.end()-4,vname.end()); //erase the lagging .npy
|
||||
|
||||
//read in the extra field
|
||||
unsigned short extra_field_len = *(unsigned short*) &local_header[28];
|
||||
fseek(fp,extra_field_len,SEEK_CUR); //skip past the extra field
|
||||
|
||||
if(vname == varname) {
|
||||
NpyArray array = load_the_npy_file(fp);
|
||||
fclose(fp);
|
||||
return array;
|
||||
}
|
||||
else {
|
||||
//skip past the data
|
||||
unsigned int size = *(unsigned int*) &local_header[22];
|
||||
fseek(fp,size,SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
throw std::runtime_error("npz_load: Error! Variable name " + varname + " not found in " + fname + "!\n");
|
||||
}
|
||||
|
||||
cnpy::NpyArray cnpy::npy_load(std::string fname) {
|
||||
|
||||
FILE* fp = fopen(fname.c_str(), "rb");
|
||||
|
||||
if(!fp) {
|
||||
throw std::runtime_error("npy_load: Error! Unable to open file " + fname + "!\n");
|
||||
}
|
||||
|
||||
NpyArray arr = load_the_npy_file(fp);
|
||||
|
||||
fclose(fp);
|
||||
return arr;
|
||||
}
|
294
modules/dnn/test/cnpy.h
Normal file
294
modules/dnn/test/cnpy.h
Normal file
@ -0,0 +1,294 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
//Copyright (C) 2011 Carl Rogers
|
||||
//Released under MIT License
|
||||
//license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
#ifndef LIBCNPY_H_
|
||||
#define LIBCNPY_H_
|
||||
|
||||
#include<string>
|
||||
#include<stdexcept>
|
||||
#include<sstream>
|
||||
#include<vector>
|
||||
#include<cstdio>
|
||||
#include<typeinfo>
|
||||
#include<iostream>
|
||||
#include<cassert>
|
||||
#include<map>
|
||||
#if defined(HAVE_ZLIB) && HAVE_ZLIB
|
||||
#include<zlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define cnpy_assert(expression) assert(expression)
|
||||
#else
|
||||
#define cnpy_assert(expression) ((void)(expression))
|
||||
#endif
|
||||
|
||||
namespace cnpy {
|
||||
|
||||
struct NpyArray {
|
||||
char* data;
|
||||
std::vector<unsigned int> shape;
|
||||
unsigned int word_size;
|
||||
bool fortran_order;
|
||||
void destruct() {delete[] data;}
|
||||
};
|
||||
|
||||
struct npz_t : public std::map<std::string, NpyArray>
|
||||
{
|
||||
void destruct()
|
||||
{
|
||||
npz_t::iterator it = this->begin();
|
||||
for(; it != this->end(); ++it) (*it).second.destruct();
|
||||
}
|
||||
};
|
||||
|
||||
char BigEndianTest();
|
||||
char map_type(const std::type_info& t);
|
||||
template<typename T> std::vector<char> create_npy_header(const T* data, const unsigned int* shape, const unsigned int ndims);
|
||||
void parse_npy_header(FILE* fp,unsigned int& word_size, unsigned int*& shape, unsigned int& ndims, bool& fortran_order);
|
||||
void parse_zip_footer(FILE* fp, unsigned short& nrecs, unsigned int& global_header_size, unsigned int& global_header_offset);
|
||||
npz_t npz_load(std::string fname);
|
||||
NpyArray npz_load(std::string fname, std::string varname);
|
||||
NpyArray npy_load(std::string fname);
|
||||
|
||||
template<typename T> std::vector<char>& operator+=(std::vector<char>& lhs, const T rhs) {
|
||||
//write in little endian
|
||||
for(char byte = 0; (size_t)byte < sizeof(T); byte++) {
|
||||
char val = *((char*)&rhs+byte);
|
||||
lhs.push_back(val);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<> std::vector<char>& operator+=(std::vector<char>& lhs, const std::string rhs);
|
||||
template<> std::vector<char>& operator+=(std::vector<char>& lhs, const char* rhs);
|
||||
|
||||
|
||||
template<typename T> std::string tostring(T i, int = 0, char = ' ') {
|
||||
std::stringstream s;
|
||||
s << i;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
template<typename T> void npy_save(std::string fname, const T* data, const unsigned int* shape, const unsigned int ndims, std::string mode = "w") {
|
||||
FILE* fp = NULL;
|
||||
|
||||
if(mode == "a") fp = fopen(fname.c_str(),"r+b");
|
||||
|
||||
if(fp) {
|
||||
//file exists. we need to append to it. read the header, modify the array size
|
||||
unsigned int word_size, tmp_dims;
|
||||
unsigned int* tmp_shape = 0;
|
||||
bool fortran_order;
|
||||
parse_npy_header(fp,word_size,tmp_shape,tmp_dims,fortran_order);
|
||||
cnpy_assert(!fortran_order);
|
||||
|
||||
if(word_size != sizeof(T)) {
|
||||
std::cout<<"libnpy error: "<<fname<<" has word size "<<word_size<<" but npy_save appending data sized "<<sizeof(T)<<"\n";
|
||||
cnpy_assert( word_size == sizeof(T) );
|
||||
}
|
||||
if(tmp_dims != ndims) {
|
||||
std::cout<<"libnpy error: npy_save attempting to append misdimensioned data to "<<fname<<"\n";
|
||||
cnpy_assert(tmp_dims == ndims);
|
||||
}
|
||||
|
||||
for(unsigned i = 1; i < ndims; i++) {
|
||||
if(shape[i] != tmp_shape[i]) {
|
||||
std::cout<<"libnpy error: npy_save attempting to append misshaped data to "<<fname<<"\n";
|
||||
cnpy_assert(shape[i] == tmp_shape[i]);
|
||||
}
|
||||
}
|
||||
tmp_shape[0] += shape[0];
|
||||
|
||||
fseek(fp,0,SEEK_SET);
|
||||
std::vector<char> header = create_npy_header(data,tmp_shape,ndims);
|
||||
fwrite(&header[0],sizeof(char),header.size(),fp);
|
||||
fseek(fp,0,SEEK_END);
|
||||
|
||||
delete[] tmp_shape;
|
||||
}
|
||||
else {
|
||||
fp = fopen(fname.c_str(),"wb");
|
||||
std::vector<char> header = create_npy_header(data,shape,ndims);
|
||||
fwrite(&header[0],sizeof(char),header.size(),fp);
|
||||
}
|
||||
|
||||
unsigned int nels = 1;
|
||||
for(unsigned i = 0;i < ndims;i++) nels *= shape[i];
|
||||
|
||||
fwrite(data,sizeof(T),nels,fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
template<typename T> void npz_save(std::string zipname, std::string fname, const T* data, const unsigned int* shape, const unsigned int ndims, std::string mode = "w")
|
||||
{
|
||||
//first, append a .npy to the fname
|
||||
fname += ".npy";
|
||||
|
||||
//now, on with the show
|
||||
FILE* fp = NULL;
|
||||
unsigned short nrecs = 0;
|
||||
unsigned int global_header_offset = 0;
|
||||
std::vector<char> global_header;
|
||||
|
||||
if(mode == "a") fp = fopen(zipname.c_str(),"r+b");
|
||||
|
||||
if(fp) {
|
||||
//zip file exists. we need to add a new npy file to it.
|
||||
//first read the footer. this gives us the offset and size of the global header
|
||||
//then read and store the global header.
|
||||
//below, we will write the the new data at the start of the global header then append the global header and footer below it
|
||||
unsigned int global_header_size;
|
||||
parse_zip_footer(fp,nrecs,global_header_size,global_header_offset);
|
||||
fseek(fp,global_header_offset,SEEK_SET);
|
||||
global_header.resize(global_header_size);
|
||||
size_t res = fread(&global_header[0],sizeof(char),global_header_size,fp);
|
||||
if(res != global_header_size){
|
||||
throw std::runtime_error("npz_save: header read error while adding to existing zip");
|
||||
}
|
||||
fseek(fp,global_header_offset,SEEK_SET);
|
||||
}
|
||||
else {
|
||||
fp = fopen(zipname.c_str(),"wb");
|
||||
}
|
||||
|
||||
std::vector<char> npy_header = create_npy_header(data,shape,ndims);
|
||||
|
||||
unsigned long nels = 1;
|
||||
for (unsigned m=0; m<ndims; m++ ) nels *= shape[m];
|
||||
int nbytes = nels*sizeof(T) + npy_header.size();
|
||||
|
||||
//get the CRC of the data to be added
|
||||
#if defined(HAVE_ZLIB) && HAVE_ZLIB
|
||||
unsigned int crc = crc32(0L,(unsigned char*)&npy_header[0],npy_header.size());
|
||||
crc = crc32(crc,(unsigned char*)data,nels*sizeof(T));
|
||||
#else
|
||||
unsigned int crc = 0;
|
||||
#endif
|
||||
|
||||
//build the local header
|
||||
std::vector<char> local_header;
|
||||
local_header += "PK"; //first part of sig
|
||||
local_header += (unsigned short) 0x0403; //second part of sig
|
||||
local_header += (unsigned short) 20; //min version to extract
|
||||
local_header += (unsigned short) 0; //general purpose bit flag
|
||||
local_header += (unsigned short) 0; //compression method
|
||||
local_header += (unsigned short) 0; //file last mod time
|
||||
local_header += (unsigned short) 0; //file last mod date
|
||||
local_header += (unsigned int) crc; //crc
|
||||
local_header += (unsigned int) nbytes; //compressed size
|
||||
local_header += (unsigned int) nbytes; //uncompressed size
|
||||
local_header += (unsigned short) fname.size(); //fname length
|
||||
local_header += (unsigned short) 0; //extra field length
|
||||
local_header += fname;
|
||||
|
||||
//build global header
|
||||
global_header += "PK"; //first part of sig
|
||||
global_header += (unsigned short) 0x0201; //second part of sig
|
||||
global_header += (unsigned short) 20; //version made by
|
||||
global_header.insert(global_header.end(),local_header.begin()+4,local_header.begin()+30);
|
||||
global_header += (unsigned short) 0; //file comment length
|
||||
global_header += (unsigned short) 0; //disk number where file starts
|
||||
global_header += (unsigned short) 0; //internal file attributes
|
||||
global_header += (unsigned int) 0; //external file attributes
|
||||
global_header += (unsigned int) global_header_offset; //relative offset of local file header, since it begins where the global header used to begin
|
||||
global_header += fname;
|
||||
|
||||
//build footer
|
||||
std::vector<char> footer;
|
||||
footer += "PK"; //first part of sig
|
||||
footer += (unsigned short) 0x0605; //second part of sig
|
||||
footer += (unsigned short) 0; //number of this disk
|
||||
footer += (unsigned short) 0; //disk where footer starts
|
||||
footer += (unsigned short) (nrecs+1); //number of records on this disk
|
||||
footer += (unsigned short) (nrecs+1); //total number of records
|
||||
footer += (unsigned int) global_header.size(); //nbytes of global headers
|
||||
footer += (unsigned int) (global_header_offset + nbytes + local_header.size()); //offset of start of global headers, since global header now starts after newly written array
|
||||
footer += (unsigned short) 0; //zip file comment length
|
||||
|
||||
//write everything
|
||||
fwrite(&local_header[0],sizeof(char),local_header.size(),fp);
|
||||
fwrite(&npy_header[0],sizeof(char),npy_header.size(),fp);
|
||||
fwrite(data,sizeof(T),nels,fp);
|
||||
fwrite(&global_header[0],sizeof(char),global_header.size(),fp);
|
||||
fwrite(&footer[0],sizeof(char),footer.size(),fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
template<typename T> std::vector<char> create_npy_header(const T*, const unsigned int* shape, const unsigned int ndims) {
|
||||
|
||||
std::vector<char> dict;
|
||||
dict += "{'descr': '";
|
||||
dict += BigEndianTest();
|
||||
dict += map_type(typeid(T));
|
||||
dict += tostring(sizeof(T));
|
||||
dict += "', 'fortran_order': False, 'shape': (";
|
||||
dict += tostring(shape[0]);
|
||||
for(unsigned i = 1;i < ndims;i++) {
|
||||
dict += ", ";
|
||||
dict += tostring(shape[i]);
|
||||
}
|
||||
if(ndims == 1) dict += ",";
|
||||
dict += "), }";
|
||||
//pad with spaces so that preamble+dict is modulo 16 bytes. preamble is 10 bytes. dict needs to end with \n
|
||||
int remainder = 16 - (10 + dict.size()) % 16;
|
||||
dict.insert(dict.end(),remainder,' ');
|
||||
dict.back() = '\n';
|
||||
|
||||
std::vector<char> header;
|
||||
header += (unsigned char) 0x93;
|
||||
header += "NUMPY";
|
||||
header += (char) 0x01; //major version of numpy format
|
||||
header += (char) 0x00; //minor version of numpy format
|
||||
header += (unsigned short) dict.size();
|
||||
header.insert(header.end(),dict.begin(),dict.end());
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user