Commit b51ffe3e authored by Vitaliy Lyudvichenko's avatar Vitaliy Lyudvichenko

Adding of public interfaces and refactoring of Reshape and MVN layer.

parent 4f578068
......@@ -275,8 +275,26 @@ namespace dnn
static Ptr<InnerProductLayer> create(int axis = 1);
};
class CV_EXPORTS_W MVNLayer : public Layer
{
public:
double eps;
bool normVariance, acrossChannels;
static Ptr<MVNLayer> create(bool normVariance = true, bool acrossChannels = false, double eps = 1e-9);
};
/* Reshaping */
class CV_EXPORTS_W ReshapeLayer : public Layer
{
public:
BlobShape newShapeDesc;
Range newShapeRange;
static Ptr<ReshapeLayer> create(const BlobShape &newShape, Range applyingRange = Range::all());
};
class CV_EXPORTS_W ConcatLayer : public Layer
{
public:
......
......@@ -115,6 +115,8 @@ namespace dnn
/** @brief Returns pointer to the first element of continuous size array. */
const int *ptr() const;
/** @overload */
int *ptr();
bool equal(const BlobShape &other) const; //!< Checks equality of two shapes.
bool operator== (const BlobShape &r) const; //!< @sa equal()
......
......@@ -208,6 +208,11 @@ inline const int *BlobShape::ptr() const
return sz;
}
inline int *BlobShape::ptr()
{
return sz;
}
inline bool BlobShape::equal(const BlobShape &other) const
{
if (this->dims() != other.dims())
......
......@@ -57,6 +57,7 @@ inline std::ostream &operator<< (std::ostream &s, cv::Range &r)
}
//Reshaping
//TODO: add -1 specifier for automatic size inferring
template<typename Mat>
void reshape(Mat &m, const BlobShape &shape)
......@@ -129,31 +130,7 @@ Mat slice(const Mat &m, const _Range &r0, const _Range &r1, const _Range &r2, co
return m(&ranges[0]);
}
//Traits for switching in ploymorphic implementations
template<typename XMat>
struct MatTraits
{
};
template<>
struct MatTraits<cv::Mat>
{
enum
{
IS_MAT = 1,
IS_UMAT = 0,
};
};
template<>
struct MatTraits<cv::UMat>
{
enum
{
IS_MAT = 0,
IS_UMAT = 1,
};
};
BlobShape computeShapeByReshapeMask(const BlobShape &srcShape, const BlobShape &maskShape, Range srcRange = Range::all());
}
}
......
This diff is collapsed.
......@@ -162,8 +162,45 @@ Ptr<Layer> createLayerFromCaffe<LRNLayer>(LayerParams& params)
return Ptr<Layer>(LRNLayer::create(type, size, alpha, beta));
}
template<>
Ptr<Layer> createLayerFromCaffe<MVNLayer>(LayerParams &params)
{
return Ptr<Layer>(MVNLayer::create(
params.get<bool>("normalize_variance", true),
params.get<bool>("across_channels", false),
params.get<double>("eps", 1e-9)
));
}
/* Reshape layers */
template<>
Ptr<Layer> createLayerFromCaffe<ReshapeLayer>(LayerParams &params)
{
int axis = params.get<int>("axis", 0);
int numAxes = params.get<int>("num_axes", -1);
CV_Assert(numAxes >= -1);
Range applyingRange = (numAxes == -1) ? Range::all() : Range(axis, axis + numAxes);
Shape newShape;
if (params.has("dim"))
{
const DictValue &paramShape = params.get("dim");
newShape = Shape(paramShape.size(), nullptr);
for (int i = 0; i < paramShape.size(); i++)
newShape[i] = paramShape.get<int>(i);
}
else
newShape = Shape::all(0);
return Ptr<Layer>(ReshapeLayer::create(newShape, applyingRange));
}
Ptr<Layer> createFlattenLayerFromCaffe(LayerParams&)
{
return Ptr<Layer>(ReshapeLayer::create(Shape(0, -1)));
}
template<>
Ptr<Layer> createLayerFromCaffe<ConcatLayer>(LayerParams& params)
{
......@@ -239,6 +276,11 @@ template Ptr<Layer> createLayerFromCaffe<DeconvolutionLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<SoftmaxLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<InnerProductLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<LRNLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<MVNLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<ConcatLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<SliceLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<SplitLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<ReLULayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<SigmoidLayer>(LayerParams&);
......
......@@ -53,6 +53,8 @@ namespace dnn
template <typename PublicLayer>
Ptr<Layer> createLayerFromCaffe(LayerParams&);
Ptr<Layer> createFlattenLayerFromCaffe(LayerParams&);
}
}
#endif
\ No newline at end of file
......@@ -71,10 +71,8 @@ void initModule()
REG_RUNTIME_LAYER_FUNC(Slice, createLayerFromCaffe<SliceLayer>);
REG_RUNTIME_LAYER_FUNC(Split, createLayerFromCaffe<SplitLayer>);
REG_RUNTIME_LAYER_FUNC(Concat, createLayerFromCaffe<ConcatLayer>);
REG_RUNTIME_LAYER_CLASS(Reshape, ReshapeLayer)
REG_RUNTIME_LAYER_FUNC(Flatten, createFlattenLayer);
REG_RUNTIME_LAYER_CLASS(Dropout, BlankLayer)
REG_RUNTIME_LAYER_CLASS(MVN, MVNLayer)
REG_RUNTIME_LAYER_FUNC(Reshape, createLayerFromCaffe<ReshapeLayer>);
REG_RUNTIME_LAYER_FUNC(Flatten, createFlattenLayerFromCaffe);
REG_RUNTIME_LAYER_FUNC(Convolution, createLayerFromCaffe<ConvolutionLayer>);
REG_RUNTIME_LAYER_FUNC(Deconvolution, createLayerFromCaffe<DeconvolutionLayer>);
......@@ -82,6 +80,7 @@ void initModule()
REG_RUNTIME_LAYER_FUNC(LRN, createLayerFromCaffe<LRNLayer>);
REG_RUNTIME_LAYER_FUNC(InnerProduct, createLayerFromCaffe<InnerProductLayer>);
REG_RUNTIME_LAYER_FUNC(Softmax, createLayerFromCaffe<SoftmaxLayer>);
REG_RUNTIME_LAYER_FUNC(MVN, createLayerFromCaffe<MVNLayer>);
REG_RUNTIME_LAYER_FUNC(ReLU, createLayerFromCaffe<ReLULayer>);
REG_RUNTIME_LAYER_FUNC(Sigmoid, createLayerFromCaffe<SigmoidLayer>);
......@@ -89,6 +88,7 @@ void initModule()
REG_RUNTIME_LAYER_FUNC(BNLL, createLayerFromCaffe<BNLLLayer>);
REG_RUNTIME_LAYER_FUNC(AbsVal, createLayerFromCaffe<AbsLayer>);
REG_RUNTIME_LAYER_FUNC(Power, createLayerFromCaffe<PowerLayer>);
REG_RUNTIME_LAYER_CLASS(Dropout, BlankLayer)
init.status = true;
}
......
......@@ -42,11 +42,12 @@
#include "../precomp.hpp"
#include "layers_common.hpp"
#include "lrn_layer.hpp"
#include "opencl_kernels_dnn.hpp"
#include "modules/dnn/opencl_kernels_dnn.hpp"
#include <opencv2/imgproc.hpp>
#include <opencv2/core/ocl.hpp>
#include <opencv2/dnn/shape_utils.hpp>
#include <algorithm>
#include <type_traits>
namespace cv
{
......@@ -220,7 +221,7 @@ void LRNLayerImpl::spatialNormalization_(Blob &srcBlob, Blob &dstBlob)
XMat src = getPlane(srcMat, n, cn);
XMat dst = getPlane(dstMat, n, cn);
if (MatTraits<XMat>::IS_UMAT)
if (std::is_same<XMat, UMat>::value)
{
cv::sqrBoxFilter(src, dst, dst.depth(), Size(size, size), Point(-1, -1), false, BORDER_CONSTANT | BORDER_ISOLATED);
}
......
......@@ -42,20 +42,21 @@
#include "../precomp.hpp"
#include "layers_common.hpp"
#include "mvn_layer.hpp"
#include <opencv2/dnn/shape_utils.hpp>
namespace cv
{
namespace dnn
{
MVNLayer::MVNLayer(LayerParams &params) : Layer(params)
MVNLayerImpl::MVNLayerImpl(bool normVariance_, bool acrossChannels_, double eps_)
{
eps = params.get<double>("eps", 1e-9);
acrossChannels = params.get<bool>("across_channels", false);
normalizeVariance = params.get<bool>("normalize_variance", true);
normVariance = normVariance_;
acrossChannels = acrossChannels_;
eps = eps_;
}
void MVNLayer::allocate(const std::vector<Blob *> &inputs, std::vector<Blob> &outputs)
void MVNLayerImpl::allocate(const std::vector<Blob *> &inputs, std::vector<Blob> &outputs)
{
outputs.resize(inputs.size());
for (size_t i = 0; i < inputs.size(); i++)
......@@ -65,20 +66,17 @@ void MVNLayer::allocate(const std::vector<Blob *> &inputs, std::vector<Blob> &ou
}
}
void MVNLayer::forward(std::vector<Blob *> &inputs, std::vector<Blob> &outputs)
void MVNLayerImpl::forward(std::vector<Blob *> &inputs, std::vector<Blob> &outputs)
{
for (size_t inpIdx = 0; inpIdx < inputs.size(); inpIdx++)
{
Blob &inpBlob = *inputs[inpIdx];
Blob &outBlob = outputs[inpIdx];
int workSize[2];
int splitDim = (acrossChannels) ? 1 : 2;
workSize[0] = (int)inpBlob.total(0, splitDim);
workSize[1] = (int)inpBlob.total(splitDim);
Mat inpMat = inpBlob.matRef().reshape(1, 2, workSize);
Mat outMat = outBlob.matRef().reshape(1, 2, workSize);
Shape workSize((int)inpBlob.total(0, splitDim), (int)inpBlob.total(splitDim));
Mat inpMat = reshaped(inpBlob.matRefConst(), workSize);
Mat outMat = reshaped(outBlob.matRef(), workSize);
Scalar mean, dev;
for (int i = 0; i < workSize[0]; i++)
......@@ -86,12 +84,18 @@ void MVNLayer::forward(std::vector<Blob *> &inputs, std::vector<Blob> &outputs)
Mat inpRow = inpMat.row(i);
Mat outRow = outMat.row(i);
cv::meanStdDev(inpRow, mean, (normalizeVariance) ? dev : noArray());
double alpha = (normalizeVariance) ? 1/(eps + dev[0]) : 1;
cv::meanStdDev(inpRow, mean, (normVariance) ? dev : noArray());
double alpha = (normVariance) ? 1/(eps + dev[0]) : 1;
inpRow.convertTo(outRow, outRow.type(), alpha, -mean[0] * alpha);
}
}
}
Ptr<MVNLayer> MVNLayer::create(bool normVariance, bool acrossChannels, double eps)
{
return Ptr<MVNLayer>(new MVNLayerImpl(normVariance, acrossChannels, eps));
}
}
}
......@@ -42,20 +42,18 @@
#ifndef __OPENCV_DNN_LAYERS_MVN_LAYER_HPP__
#define __OPENCV_DNN_LAYERS_MVN_LAYER_HPP__
#include "../precomp.hpp"
#include <opencv2/dnn/all_layers.hpp>
namespace cv
{
namespace dnn
{
class MVNLayer : public Layer
class MVNLayerImpl : public MVNLayer
{
double eps;
bool acrossChannels, normalizeVariance;
public:
MVNLayer(LayerParams &params);
MVNLayerImpl(bool normVariance_ = true, bool acrossChannels_ = false, double eps_ = 1e-9);
void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs);
void forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs);
};
......
......@@ -42,73 +42,33 @@
#include "../precomp.hpp"
#include "layers_common.hpp"
#include "reshape_layer.hpp"
#include <opencv2/dnn/shape_utils.hpp>
namespace cv
{
namespace dnn
{
ReshapeLayer::ReshapeLayer(LayerParams &params) : Layer(params)
ReshapeLayerImpl::ReshapeLayerImpl(const BlobShape &newShape_, Range applyingRange_)
{
inAxis = params.get<int>("axis", 0);
inNumAxes = params.get<int>("num_axes", -1);
CV_Assert(inNumAxes >= -1);
autoAxisIdx = -1;
if (!params.has("dim"))
{
shapeDesc = BlobShape::all(0);
return;
}
DictValue paramShape = params.get("dim");
shapeDesc = BlobShape::all(paramShape.size());
for (int i = 0; i < paramShape.size(); i++)
{
int dim = paramShape.get<int>(i);
CV_Assert(dim >= -1);
if (dim == -1)
{
if (autoAxisIdx != -1)
CV_Error(Error::StsBadArg, "New shape contains multiple -1 dims");
autoAxisIdx = i;
}
shapeDesc[i] = dim;
}
newShapeDesc = newShape_;
newShapeRange = applyingRange_;
}
void ReshapeLayer::allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs)
void ReshapeLayerImpl::allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs)
{
outputs.resize(inputs.size());
outShapes.resize(inputs.size());
for (size_t i = 0; i < inputs.size(); i++)
{
Blob &inpBlob = *inputs[i];
Blob &outBlob = outputs[i];
BlobShape inpShape = inpBlob.shape();
int startAxis = (inAxis >= 0) ? inAxis : inpShape.dims() + 1 + inAxis;
int endAxis = (inNumAxes == -1) ? inpShape.dims() : startAxis + inNumAxes;
CV_Assert(0 <= startAxis && startAxis <= inpShape.dims());
CV_Assert(0 <= endAxis && endAxis <= inpShape.dims());
int newDims = inpShape.dims() - (endAxis - startAxis) + shapeDesc.dims();
BlobShape outShape = BlobShape::all(newDims);
computeOutputShape(startAxis, endAxis, inpShape, outShape);
outShapes[i] = outShape;
outBlob.shareFrom(inpBlob);
outBlob.reshape(outShape);
outShapes[i] = computeShapeByReshapeMask(inputs[i]->shape(), newShapeDesc, newShapeRange);
outputs[i].shareFrom(*inputs[i]);
outputs[i].reshape(outShapes[i]);
}
}
void ReshapeLayer::forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs)
void ReshapeLayerImpl::forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs)
{
for (size_t i = 0; i < outputs.size(); i++)
{
......@@ -117,61 +77,11 @@ void ReshapeLayer::forward(std::vector<Blob*> &inputs, std::vector<Blob> &output
}
}
void ReshapeLayer::computeOutputShape(int startAxis, int endAxis, BlobShape &inpShape, BlobShape &outShape)
Ptr<ReshapeLayer> ReshapeLayer::create(const BlobShape &newShape, Range applyingRange /*= Range::all()*/)
{
int idx = 0;
for (int i = 0; i < startAxis; i++)
outShape[idx++] = inpShape[i];
for (int i = 0; i < shapeDesc.dims(); i++)
{
if (shapeDesc[i] == 0)
{
int inpAxisIdx = startAxis + i;
if (inpAxisIdx < 0 || inpShape.dims() <= inpAxisIdx)
CV_Error(Error::StsOutOfRange, "copy dimension (which has zero size) is not presented into reshaped blob");
outShape[idx++] = inpShape[startAxis + i];
}
else
{
outShape[idx++] = (shapeDesc[i] > 0) ? shapeDesc[i] : 1;
}
}
for (int i = endAxis; i < inpShape.dims(); i++)
outShape[idx++] = inpShape[i];
if (autoAxisIdx >= 0)
{
size_t total = inpShape.total();
size_t curTotal = 1;
for (int i = 0; i < outShape.dims(); i++)
{
if (i != startAxis + autoAxisIdx)
curTotal *= outShape[i];
}
CV_DbgAssert(curTotal <= total && total % curTotal == 0);
outShape[startAxis + autoAxisIdx] = (int)(total / curTotal);
}
if (inpShape.total() != outShape.total())
{
CV_Error(Error::StsUnmatchedSizes, "Mismatch between input and output blob elements count");
}
return Ptr<ReshapeLayer>(new ReshapeLayerImpl(newShape, applyingRange));
}
Ptr<Layer> createFlattenLayer(LayerParams&)
{
LayerParams params;
int shapeDesc[] = {0, -1};
params.set("dim", DictValue::arrayInt(shapeDesc, 2));
return Ptr<Layer>(new ReshapeLayer(params));
}
}
}
......@@ -42,27 +42,23 @@
#ifndef __OPENCV_DNN_LAYERS_RESHAPE_LAYER_HPP__
#define __OPENCV_DNN_LAYERS_RESHAPE_LAYER_HPP__
#include "../precomp.hpp"
#include <opencv2/dnn/all_layers.hpp>
namespace cv
{
namespace dnn
{
class ReshapeLayer : public Layer
class ReshapeLayerImpl : public ReshapeLayer
{
std::vector<BlobShape> outShapes;
public:
ReshapeLayer(LayerParams &params);
ReshapeLayerImpl(const BlobShape &newShape_, Range applyingRange_);
void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs);
void forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs);
protected:
BlobShape shapeDesc;
std::vector<BlobShape> outShapes;
int inAxis, inNumAxes, autoAxisIdx;
void computeOutputShape(int startAxis, int endAxis, BlobShape &inpShape, BlobShape &outShape);
};
Ptr<Layer> createFlattenLayer(LayerParams&);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment