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

pull/707/head
Vitaliy Lyudvichenko 9 years ago
parent 4f57806858
commit b51ffe3e53
  1. 18
      modules/dnn/include/opencv2/dnn/all_layers.hpp
  2. 2
      modules/dnn/include/opencv2/dnn/blob.hpp
  3. 5
      modules/dnn/include/opencv2/dnn/blob.inl.hpp
  4. 27
      modules/dnn/include/opencv2/dnn/shape_utils.hpp
  5. 522
      modules/dnn/src/blob.cpp
  6. 42
      modules/dnn/src/caffe/layer_loaders.cpp
  7. 2
      modules/dnn/src/caffe/layer_loaders.hpp
  8. 8
      modules/dnn/src/init.cpp
  9. 5
      modules/dnn/src/layers/lrn_layer.cpp
  10. 32
      modules/dnn/src/layers/mvn_layer.cpp
  11. 8
      modules/dnn/src/layers/mvn_layer.hpp
  12. 112
      modules/dnn/src/layers/reshape_layer.cpp
  13. 14
      modules/dnn/src/layers/reshape_layer.hpp

@ -275,8 +275,26 @@ namespace dnn
static Ptr<InnerProductLayer> create(int axis = 1); 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 */ /* 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 class CV_EXPORTS_W ConcatLayer : public Layer
{ {
public: public:

@ -115,6 +115,8 @@ namespace dnn
/** @brief Returns pointer to the first element of continuous size array. */ /** @brief Returns pointer to the first element of continuous size array. */
const int *ptr() const; const int *ptr() const;
/** @overload */
int *ptr();
bool equal(const BlobShape &other) const; //!< Checks equality of two shapes. bool equal(const BlobShape &other) const; //!< Checks equality of two shapes.
bool operator== (const BlobShape &r) const; //!< @sa equal() bool operator== (const BlobShape &r) const; //!< @sa equal()

@ -208,6 +208,11 @@ inline const int *BlobShape::ptr() const
return sz; return sz;
} }
inline int *BlobShape::ptr()
{
return sz;
}
inline bool BlobShape::equal(const BlobShape &other) const inline bool BlobShape::equal(const BlobShape &other) const
{ {
if (this->dims() != other.dims()) if (this->dims() != other.dims())

@ -57,6 +57,7 @@ inline std::ostream &operator<< (std::ostream &s, cv::Range &r)
} }
//Reshaping //Reshaping
//TODO: add -1 specifier for automatic size inferring
template<typename Mat> template<typename Mat>
void reshape(Mat &m, const BlobShape &shape) 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]); return m(&ranges[0]);
} }
//Traits for switching in ploymorphic implementations BlobShape computeShapeByReshapeMask(const BlobShape &srcShape, const BlobShape &maskShape, Range srcRange = Range::all());
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,
};
};
} }
} }

@ -40,321 +40,377 @@
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
#include <opencv2/dnn/shape_utils.hpp>
namespace cv namespace cv
{ {
namespace dnn namespace dnn
{ {
Blob::Blob() Blob::Blob()
{ {
CV_DNN_UMAT_ONLY(state = UNINITIALIZED); CV_DNN_UMAT_ONLY(state = UNINITIALIZED);
} }
Blob::Blob(const BlobShape &shape, int type, int allocFlags) Blob::Blob(const BlobShape &shape, int type, int allocFlags)
{ {
CV_DNN_UMAT_ONLY(state = UNINITIALIZED); CV_DNN_UMAT_ONLY(state = UNINITIALIZED);
this->create(shape, type, allocFlags); this->create(shape, type, allocFlags);
} }
Blob::Blob(InputArray data) Blob::Blob(InputArray data)
{ {
#ifndef CV_DNN_UMAT #ifndef CV_DNN_UMAT
m = data.getMat(); m = data.getMat();
#else #else
CV_Assert(data.isMat() || data.isUMat()); CV_Assert(data.isMat() || data.isUMat());
if (data.isMat()) if (data.isMat())
{ {
m = data.getMat(); m = data.getMat();
state = HEAD_AT_MAT; state = HEAD_AT_MAT;
}
else
{
um = data.getUMat();
state = HEAD_AT_UMAT;
}
#endif
} }
else
void Blob::create(const BlobShape &shape, int type, int allocFlags)
{ {
um = data.getUMat();
state = HEAD_AT_UMAT;
}
#endif
}
void Blob::create(const BlobShape &shape, int type, int allocFlags)
{
#ifndef CV_DNN_UMAT #ifndef CV_DNN_UMAT
CV_Assert(allocFlags & ALLOC_MAT); CV_Assert(allocFlags & ALLOC_MAT);
m.create(shape.dims(), shape.ptr(), type); m.create(shape.dims(), shape.ptr(), type);
#else #else
CV_Assert(allocFlags & ALLOC_MAT || allocFlags & ALLOC_UMAT); CV_Assert(allocFlags & ALLOC_MAT || allocFlags & ALLOC_UMAT);
if (allocFlags & ALLOC_MAT)
m.create(shape.dims(), shape.ptr(), type);
if (allocFlags & ALLOC_UMAT)
um.create(shape.dims(), shape.ptr(), type);
if (state == UNINITIALIZED) if (allocFlags & ALLOC_MAT)
{ m.create(shape.dims(), shape.ptr(), type);
if (allocFlags & ALLOC_MAT && allocFlags & ALLOC_UMAT) if (allocFlags & ALLOC_UMAT)
state = SYNCED; um.create(shape.dims(), shape.ptr(), type);
else if (allocFlags & ALLOC_MAT)
state = HEAD_AT_MAT;
else
state = HEAD_AT_UMAT;
}
#endif
}
void Blob::fill(InputArray in) if (state == UNINITIALIZED)
{ {
#ifdef CV_DNN_UMAT if (allocFlags & ALLOC_MAT && allocFlags & ALLOC_UMAT)
CV_Assert(in.isMat() || in.isUMat()); state = SYNCED;
if (in.isMat()) else if (allocFlags & ALLOC_MAT)
{
m = in.getMat();
state = HEAD_AT_MAT; state = HEAD_AT_MAT;
}
else else
{
um = in.getUMat();
state = HEAD_AT_UMAT; state = HEAD_AT_UMAT;
}
#else
CV_Assert(in.isMat());
m = in.getMat();
#endif
} }
#endif
}
static inline int getMatChannels(const Mat &mat) void Blob::fill(InputArray in)
{
#ifdef CV_DNN_UMAT
CV_Assert(in.isMat() || in.isUMat());
if (in.isMat())
{ {
return (mat.dims <= 2) ? mat.channels() : mat.size[0]; m = in.getMat();
state = HEAD_AT_MAT;
} }
else
static BlobShape getBlobShape(std::vector<Mat> &vmat, int requestedCn = -1)
{ {
BlobShape shape(BlobShape::all(4)); um = in.getUMat();
int cnSum = 0, matCn; state = HEAD_AT_UMAT;
}
CV_Assert(vmat.size() > 0); #else
CV_Assert(in.isMat());
m = in.getMat();
#endif
}
for (size_t i = 0; i < vmat.size(); i++) static inline int getMatChannels(const Mat &mat)
{ {
Mat &mat = vmat[i]; return (mat.dims <= 2) ? mat.channels() : mat.size[0];
CV_Assert(!mat.empty()); }
CV_Assert((mat.dims == 3 && mat.channels() == 1) || mat.dims <= 2);
matCn = getMatChannels(mat); static BlobShape getBlobShape(std::vector<Mat> &vmat, int requestedCn = -1)
cnSum += getMatChannels(mat); {
BlobShape shape(BlobShape::all(4));
int cnSum = 0, matCn;
if (i == 0) CV_Assert(vmat.size() > 0);
{
shape[-1] = mat.cols;
shape[-2] = mat.rows;
shape[-3] = (requestedCn <= 0) ? matCn : requestedCn;
}
else
{
if (mat.cols != shape[-1] || mat.rows != shape[-2])
CV_Error(Error::StsError, "Each Mat.size() must be equal");
if (requestedCn <= 0 && matCn != shape[-3]) for (size_t i = 0; i < vmat.size(); i++)
CV_Error(Error::StsError, "Each Mat.chnannels() (or number of planes) must be equal"); {
} Mat &mat = vmat[i];
} CV_Assert(!mat.empty());
CV_Assert((mat.dims == 3 && mat.channels() == 1) || mat.dims <= 2);
if (cnSum % shape[-3] != 0)
CV_Error(Error::StsError, "Total number of channels in vector is not a multiple of requsted channel number");
shape[0] = cnSum / shape[-3]; matCn = getMatChannels(mat);
return shape; cnSum += getMatChannels(mat);
}
static std::vector<Mat> extractMatVector(InputArray in) if (i == 0)
{
if (in.isMat() || in.isUMat())
{
return std::vector<Mat>(1, in.getMat());
}
else if (in.isMatVector())
{
return *static_cast<const std::vector<Mat>*>(in.getObj());
}
else if (in.isUMatVector())
{ {
std::vector<Mat> vmat; shape[-1] = mat.cols;
in.getMatVector(vmat); shape[-2] = mat.rows;
return vmat; shape[-3] = (requestedCn <= 0) ? matCn : requestedCn;
} }
else else
{ {
CV_Assert(in.isMat() || in.isMatVector() || in.isUMat() || in.isUMatVector()); if (mat.cols != shape[-1] || mat.rows != shape[-2])
return std::vector<Mat>(); CV_Error(Error::StsError, "Each Mat.size() must be equal");
if (requestedCn <= 0 && matCn != shape[-3])
CV_Error(Error::StsError, "Each Mat.chnannels() (or number of planes) must be equal");
} }
} }
void Blob::batchFromImages(InputArray image, int dstCn) if (cnSum % shape[-3] != 0)
CV_Error(Error::StsError, "Total number of channels in vector is not a multiple of requsted channel number");
shape[0] = cnSum / shape[-3];
return shape;
}
static std::vector<Mat> extractMatVector(InputArray in)
{
if (in.isMat() || in.isUMat())
{
return std::vector<Mat>(1, in.getMat());
}
else if (in.isMatVector())
{ {
CV_Assert(dstCn == -1 || dstCn > 0); return *static_cast<const std::vector<Mat>*>(in.getObj());
std::vector<Mat> inMats = extractMatVector(image); }
BlobShape dstShape = getBlobShape(inMats, dstCn); else if (in.isUMatVector())
{
std::vector<Mat> vmat;
in.getMatVector(vmat);
return vmat;
}
else
{
CV_Assert(in.isMat() || in.isMatVector() || in.isUMat() || in.isUMatVector());
return std::vector<Mat>();
}
}
int dtype = CV_32F; void Blob::batchFromImages(InputArray image, int dstCn)
this->create(dstShape, dtype, ALLOC_MAT); {
uchar *dstPtr = this->matRef().ptr(); CV_Assert(dstCn == -1 || dstCn > 0);
int elemSize = CV_ELEM_SIZE(dtype); std::vector<Mat> inMats = extractMatVector(image);
BlobShape dstShape = getBlobShape(inMats, dstCn);
std::vector<Mat> wrapBuf(dstShape[-3]); int dtype = CV_32F;
for (size_t i = 0; i < inMats.size(); i++) this->create(dstShape, dtype, ALLOC_MAT);
{ uchar *dstPtr = this->matRef().ptr();
Mat inMat = inMats[i]; int elemSize = CV_ELEM_SIZE(dtype);
if (inMat.dims <= 2) std::vector<Mat> wrapBuf(dstShape[-3]);
{ for (size_t i = 0; i < inMats.size(); i++)
inMat.convertTo(inMat, dtype); {
Mat inMat = inMats[i];
wrapBuf.resize(0); if (inMat.dims <= 2)
for (int cn = 0; cn < inMat.channels(); cn++) {
{ inMat.convertTo(inMat, dtype);
wrapBuf.push_back(Mat(inMat.rows, inMat.cols, dtype, dstPtr));
dstPtr += elemSize * inMat.total();
}
cv::split(inMat, wrapBuf); wrapBuf.resize(0);
} for (int cn = 0; cn < inMat.channels(); cn++)
else
{ {
inMat.convertTo(Mat(inMat.dims, inMat.size, dtype, dstPtr), dtype); wrapBuf.push_back(Mat(inMat.rows, inMat.cols, dtype, dstPtr));
dstPtr += elemSize * inMat.total(); dstPtr += elemSize * inMat.total();
} }
}
}
Blob Blob::fromImages(InputArray image, int dstCn)
{
Blob res;
res.batchFromImages(image, dstCn);
return res;
}
void Blob::fill(const BlobShape &shape, int type, void *data, bool deepCopy) cv::split(inMat, wrapBuf);
{
if (deepCopy)
{
create(shape, type);
memcpy(ptr(), data, this->total() * CV_ELEM_SIZE(type));
} }
else else
{ {
m = Mat(shape.dims(), shape.ptr(), type, data); inMat.convertTo(Mat(inMat.dims, inMat.size, dtype, dstPtr), dtype);
dstPtr += elemSize * inMat.total();
} }
CV_DNN_UMAT_ONLY(state = HEAD_AT_MAT);
} }
}
void Blob::setTo(InputArray value, int allocFlags) Blob Blob::fromImages(InputArray image, int dstCn)
{
Blob res;
res.batchFromImages(image, dstCn);
return res;
}
void Blob::fill(const BlobShape &shape, int type, void *data, bool deepCopy)
{
if (deepCopy)
{ {
#ifdef CV_DNN_UMAT create(shape, type);
if (allocFlags == -1) memcpy(ptr(), data, this->total() * CV_ELEM_SIZE(type));
{ }
if (state == HEAD_AT_UMAT) else
um.setTo(value); {
else if (state == HEAD_AT_MAT) m = Mat(shape.dims(), shape.ptr(), type, data);
m.setTo(value); }
else //SYNCED or UNINITIALIZED CV_DNN_UMAT_ONLY(state = HEAD_AT_MAT);
{ }
um.setTo(value);
m.setTo(value);
if (state == UNINITIALIZED) void Blob::setTo(InputArray value, int allocFlags)
state = SYNCED; {
} #ifdef CV_DNN_UMAT
} if (allocFlags == -1)
else if (allocFlags == ALLOC_BOTH) {
{ if (state == HEAD_AT_UMAT)
m.setTo(value);
um.setTo(value); um.setTo(value);
state = SYNCED; else if (state == HEAD_AT_MAT)
} m.setTo(value);
else if (allocFlags == ALLOC_MAT) else //SYNCED or UNINITIALIZED
{
matRef().setTo(value);
}
else if (allocFlags == ALLOC_UMAT)
{
umatRef().setTo(value);
}
else
{ {
CV_Error(Error::StsBadArg, "allocFlags sholud be -1 or one of Blob::AllocFlag values"); um.setTo(value);
m.setTo(value);
if (state == UNINITIALIZED)
state = SYNCED;
} }
#else }
else if (allocFlags == ALLOC_BOTH)
{
m.setTo(value); m.setTo(value);
#endif um.setTo(value);
state = SYNCED;
} }
else if (allocFlags == ALLOC_MAT)
void Blob::updateMat(bool syncData) const
{ {
matRef().setTo(value);
}
else if (allocFlags == ALLOC_UMAT)
{
umatRef().setTo(value);
}
else
{
CV_Error(Error::StsBadArg, "allocFlags sholud be -1 or one of Blob::AllocFlag values");
}
#else
m.setTo(value);
#endif
}
void Blob::updateMat(bool syncData) const
{
#ifdef CV_DNN_UMAT #ifdef CV_DNN_UMAT
if (state == UNINITIALIZED || state == SYNCED || state == HEAD_AT_MAT) if (state == UNINITIALIZED || state == SYNCED || state == HEAD_AT_MAT)
{ {
return; return;
} }
else if (state == HEAD_AT_UMAT) else if (state == HEAD_AT_UMAT)
{ {
if (syncData) if (syncData)
um.copyTo(m); um.copyTo(m);
else
m.create(dims(), sizes(), type());
state = SYNCED;
}
else else
{ m.create(dims(), sizes(), type());
CV_Error(Error::StsInternal, ""); state = SYNCED;
} }
else
{
CV_Error(Error::StsInternal, "");
}
#else #else
(void)syncData; (void)syncData;
#endif #endif
}
void Blob::updateUMat(bool syncData) const
{
#ifdef CV_DNN_UMAT
if (state == UNINITIALIZED || state == SYNCED || state == HEAD_AT_UMAT)
{
return;
} }
else if (state == HEAD_AT_MAT)
{
if (syncData)
m.copyTo(um);
else
um.create(dims(), sizes(), type());
}
else
{
CV_Error(Error::StsInternal, "");
}
#else
(void)syncData;
#endif
}
void Blob::sync() const
{
updateMat();
updateUMat();
}
void Blob::updateUMat(bool syncData) const Vec4i Blob::shape4() const
{
return Vec4i(num(), channels(), rows(), cols());
}
//BlobShape
std::ostream &operator<< (std::ostream &stream, const BlobShape &shape)
{
stream << "[";
for (int i = 0; i < shape.dims() - 1; i++)
stream << shape[i] << ", ";
if (shape.dims() > 0)
stream << shape[-1];
return stream << "]";
}
BlobShape computeShapeByReshapeMask(const BlobShape &srcShape, const BlobShape &maskShape, Range srcRange /*= Range::all()*/)
{
if (srcRange == Range::all())
srcRange = Range(0, srcShape.dims());
CV_Assert(0 <= srcRange.start && srcRange.start <= srcRange.end && srcRange.end <= srcShape.dims());
Shape dstShape(srcShape.dims() - srcRange.size() + maskShape.dims(), nullptr);
std::copy(srcShape.ptr(), srcShape.ptr() + srcRange.start, dstShape.ptr());
std::copy(srcShape.ptr() + srcRange.end, srcShape.ptr() + srcShape.dims(), dstShape.ptr() + srcRange.start + maskShape.dims());
int inferDim = -1;
for (int i = 0; i < maskShape.dims(); i++)
{ {
#ifdef CV_DNN_UMAT if (maskShape[i] > 0)
if (state == UNINITIALIZED || state == SYNCED || state == HEAD_AT_UMAT)
{ {
return; dstShape[srcRange.start + i] = maskShape[i];
} }
else if (state == HEAD_AT_MAT) else if (maskShape[i] == 0)
{ {
if (syncData) if (srcRange.start + i >= srcShape.dims())
m.copyTo(um); CV_Error(Error::StsBadArg, format("Copy dim[%d] (which has zero size) is out of the source shape bounds", srcRange.start + i));
else dstShape[srcRange.start + i] = srcShape[srcRange.start + i];
um.create(dims(), sizes(), type());
} }
else else if (maskShape[i] == -1)
{ {
CV_Error(Error::StsInternal, ""); if (inferDim != -1)
CV_Error(Error::StsAssert, "Duplicate of inferred dim (which is denoted by -1)");
inferDim = srcRange.start + i;
dstShape[inferDim] = 1;
} }
#else else
(void)syncData; CV_Error(Error::StsBadArg, "maskShape[i] >= -1");
#endif
} }
void Blob::sync() const if (inferDim != -1)
{ {
updateMat(); ptrdiff_t srcTotal = srcShape.total();
updateUMat(); ptrdiff_t dstTotal = dstShape.total();
} if (srcTotal % dstTotal != 0)
CV_Error(Error::StsBackTrace, "Can't infer a dim denoted by -1");
Vec4i Blob::shape4() const dstShape[inferDim] = (int)(srcTotal / dstTotal);
{
return Vec4i(num(), channels(), rows(), cols());
} }
else
std::ostream &operator<< (std::ostream &stream, const BlobShape &shape)
{ {
stream << "["; CV_Assert(srcShape.total() == dstShape.total());
}
for (int i = 0; i < shape.dims() - 1; i++) return dstShape;
stream << shape[i] << ", "; }
if (shape.dims() > 0)
stream << shape[-1];
return stream << "]";
}
} }
} }

@ -162,8 +162,45 @@ Ptr<Layer> createLayerFromCaffe<LRNLayer>(LayerParams& params)
return Ptr<Layer>(LRNLayer::create(type, size, alpha, beta)); 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 */ /* 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<> template<>
Ptr<Layer> createLayerFromCaffe<ConcatLayer>(LayerParams& params) 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<SoftmaxLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<InnerProductLayer>(LayerParams&); template Ptr<Layer> createLayerFromCaffe<InnerProductLayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<LRNLayer>(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<ReLULayer>(LayerParams&);
template Ptr<Layer> createLayerFromCaffe<SigmoidLayer>(LayerParams&); template Ptr<Layer> createLayerFromCaffe<SigmoidLayer>(LayerParams&);

@ -53,6 +53,8 @@ namespace dnn
template <typename PublicLayer> template <typename PublicLayer>
Ptr<Layer> createLayerFromCaffe(LayerParams&); Ptr<Layer> createLayerFromCaffe(LayerParams&);
Ptr<Layer> createFlattenLayerFromCaffe(LayerParams&);
} }
} }
#endif #endif

@ -71,10 +71,8 @@ void initModule()
REG_RUNTIME_LAYER_FUNC(Slice, createLayerFromCaffe<SliceLayer>); REG_RUNTIME_LAYER_FUNC(Slice, createLayerFromCaffe<SliceLayer>);
REG_RUNTIME_LAYER_FUNC(Split, createLayerFromCaffe<SplitLayer>); REG_RUNTIME_LAYER_FUNC(Split, createLayerFromCaffe<SplitLayer>);
REG_RUNTIME_LAYER_FUNC(Concat, createLayerFromCaffe<ConcatLayer>); REG_RUNTIME_LAYER_FUNC(Concat, createLayerFromCaffe<ConcatLayer>);
REG_RUNTIME_LAYER_CLASS(Reshape, ReshapeLayer) REG_RUNTIME_LAYER_FUNC(Reshape, createLayerFromCaffe<ReshapeLayer>);
REG_RUNTIME_LAYER_FUNC(Flatten, createFlattenLayer); REG_RUNTIME_LAYER_FUNC(Flatten, createFlattenLayerFromCaffe);
REG_RUNTIME_LAYER_CLASS(Dropout, BlankLayer)
REG_RUNTIME_LAYER_CLASS(MVN, MVNLayer)
REG_RUNTIME_LAYER_FUNC(Convolution, createLayerFromCaffe<ConvolutionLayer>); REG_RUNTIME_LAYER_FUNC(Convolution, createLayerFromCaffe<ConvolutionLayer>);
REG_RUNTIME_LAYER_FUNC(Deconvolution, createLayerFromCaffe<DeconvolutionLayer>); REG_RUNTIME_LAYER_FUNC(Deconvolution, createLayerFromCaffe<DeconvolutionLayer>);
@ -82,6 +80,7 @@ void initModule()
REG_RUNTIME_LAYER_FUNC(LRN, createLayerFromCaffe<LRNLayer>); REG_RUNTIME_LAYER_FUNC(LRN, createLayerFromCaffe<LRNLayer>);
REG_RUNTIME_LAYER_FUNC(InnerProduct, createLayerFromCaffe<InnerProductLayer>); REG_RUNTIME_LAYER_FUNC(InnerProduct, createLayerFromCaffe<InnerProductLayer>);
REG_RUNTIME_LAYER_FUNC(Softmax, createLayerFromCaffe<SoftmaxLayer>); 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(ReLU, createLayerFromCaffe<ReLULayer>);
REG_RUNTIME_LAYER_FUNC(Sigmoid, createLayerFromCaffe<SigmoidLayer>); REG_RUNTIME_LAYER_FUNC(Sigmoid, createLayerFromCaffe<SigmoidLayer>);
@ -89,6 +88,7 @@ void initModule()
REG_RUNTIME_LAYER_FUNC(BNLL, createLayerFromCaffe<BNLLLayer>); REG_RUNTIME_LAYER_FUNC(BNLL, createLayerFromCaffe<BNLLLayer>);
REG_RUNTIME_LAYER_FUNC(AbsVal, createLayerFromCaffe<AbsLayer>); REG_RUNTIME_LAYER_FUNC(AbsVal, createLayerFromCaffe<AbsLayer>);
REG_RUNTIME_LAYER_FUNC(Power, createLayerFromCaffe<PowerLayer>); REG_RUNTIME_LAYER_FUNC(Power, createLayerFromCaffe<PowerLayer>);
REG_RUNTIME_LAYER_CLASS(Dropout, BlankLayer)
init.status = true; init.status = true;
} }

@ -42,11 +42,12 @@
#include "../precomp.hpp" #include "../precomp.hpp"
#include "layers_common.hpp" #include "layers_common.hpp"
#include "lrn_layer.hpp" #include "lrn_layer.hpp"
#include "opencl_kernels_dnn.hpp" #include "modules/dnn/opencl_kernels_dnn.hpp"
#include <opencv2/imgproc.hpp> #include <opencv2/imgproc.hpp>
#include <opencv2/core/ocl.hpp> #include <opencv2/core/ocl.hpp>
#include <opencv2/dnn/shape_utils.hpp> #include <opencv2/dnn/shape_utils.hpp>
#include <algorithm> #include <algorithm>
#include <type_traits>
namespace cv namespace cv
{ {
@ -220,7 +221,7 @@ void LRNLayerImpl::spatialNormalization_(Blob &srcBlob, Blob &dstBlob)
XMat src = getPlane(srcMat, n, cn); XMat src = getPlane(srcMat, n, cn);
XMat dst = getPlane(dstMat, 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); 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 "../precomp.hpp"
#include "layers_common.hpp" #include "layers_common.hpp"
#include "mvn_layer.hpp" #include "mvn_layer.hpp"
#include <opencv2/dnn/shape_utils.hpp>
namespace cv namespace cv
{ {
namespace dnn namespace dnn
{ {
MVNLayer::MVNLayer(LayerParams &params) : Layer(params) MVNLayerImpl::MVNLayerImpl(bool normVariance_, bool acrossChannels_, double eps_)
{ {
eps = params.get<double>("eps", 1e-9); normVariance = normVariance_;
acrossChannels = params.get<bool>("across_channels", false); acrossChannels = acrossChannels_;
normalizeVariance = params.get<bool>("normalize_variance", true); 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()); outputs.resize(inputs.size());
for (size_t i = 0; i < inputs.size(); i++) 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++) for (size_t inpIdx = 0; inpIdx < inputs.size(); inpIdx++)
{ {
Blob &inpBlob = *inputs[inpIdx]; Blob &inpBlob = *inputs[inpIdx];
Blob &outBlob = outputs[inpIdx]; Blob &outBlob = outputs[inpIdx];
int workSize[2];
int splitDim = (acrossChannels) ? 1 : 2; int splitDim = (acrossChannels) ? 1 : 2;
workSize[0] = (int)inpBlob.total(0, splitDim); Shape workSize((int)inpBlob.total(0, splitDim), (int)inpBlob.total(splitDim));
workSize[1] = (int)inpBlob.total(splitDim); Mat inpMat = reshaped(inpBlob.matRefConst(), workSize);
Mat outMat = reshaped(outBlob.matRef(), workSize);
Mat inpMat = inpBlob.matRef().reshape(1, 2, workSize);
Mat outMat = outBlob.matRef().reshape(1, 2, workSize);
Scalar mean, dev; Scalar mean, dev;
for (int i = 0; i < workSize[0]; i++) 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 inpRow = inpMat.row(i);
Mat outRow = outMat.row(i); Mat outRow = outMat.row(i);
cv::meanStdDev(inpRow, mean, (normalizeVariance) ? dev : noArray()); cv::meanStdDev(inpRow, mean, (normVariance) ? dev : noArray());
double alpha = (normalizeVariance) ? 1/(eps + dev[0]) : 1; double alpha = (normVariance) ? 1/(eps + dev[0]) : 1;
inpRow.convertTo(outRow, outRow.type(), alpha, -mean[0] * alpha); 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__ #ifndef __OPENCV_DNN_LAYERS_MVN_LAYER_HPP__
#define __OPENCV_DNN_LAYERS_MVN_LAYER_HPP__ #define __OPENCV_DNN_LAYERS_MVN_LAYER_HPP__
#include "../precomp.hpp" #include "../precomp.hpp"
#include <opencv2/dnn/all_layers.hpp>
namespace cv namespace cv
{ {
namespace dnn namespace dnn
{ {
class MVNLayer : public Layer class MVNLayerImpl : public MVNLayer
{ {
double eps;
bool acrossChannels, normalizeVariance;
public: 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 allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs);
void forward(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 "../precomp.hpp"
#include "layers_common.hpp" #include "layers_common.hpp"
#include "reshape_layer.hpp" #include "reshape_layer.hpp"
#include <opencv2/dnn/shape_utils.hpp>
namespace cv namespace cv
{ {
namespace dnn namespace dnn
{ {
ReshapeLayer::ReshapeLayer(LayerParams &params) : Layer(params) ReshapeLayerImpl::ReshapeLayerImpl(const BlobShape &newShape_, Range applyingRange_)
{ {
inAxis = params.get<int>("axis", 0); newShapeDesc = newShape_;
inNumAxes = params.get<int>("num_axes", -1); newShapeRange = applyingRange_;
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;
}
} }
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()); outputs.resize(inputs.size());
outShapes.resize(inputs.size()); outShapes.resize(inputs.size());
for (size_t i = 0; i < inputs.size(); i++) for (size_t i = 0; i < inputs.size(); i++)
{ {
Blob &inpBlob = *inputs[i]; outShapes[i] = computeShapeByReshapeMask(inputs[i]->shape(), newShapeDesc, newShapeRange);
Blob &outBlob = outputs[i]; outputs[i].shareFrom(*inputs[i]);
BlobShape inpShape = inpBlob.shape(); outputs[i].reshape(outShapes[i]);
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);
} }
} }
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++) 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; return Ptr<ReshapeLayer>(new ReshapeLayerImpl(newShape, applyingRange));
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");
}
} }
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__ #ifndef __OPENCV_DNN_LAYERS_RESHAPE_LAYER_HPP__
#define __OPENCV_DNN_LAYERS_RESHAPE_LAYER_HPP__ #define __OPENCV_DNN_LAYERS_RESHAPE_LAYER_HPP__
#include "../precomp.hpp" #include "../precomp.hpp"
#include <opencv2/dnn/all_layers.hpp>
namespace cv namespace cv
{ {
namespace dnn namespace dnn
{ {
class ReshapeLayer : public Layer class ReshapeLayerImpl : public ReshapeLayer
{ {
std::vector<BlobShape> outShapes;
public: public:
ReshapeLayer(LayerParams &params); ReshapeLayerImpl(const BlobShape &newShape_, Range applyingRange_);
void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs); void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs);
void forward(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&); Ptr<Layer> createFlattenLayer(LayerParams&);

Loading…
Cancel
Save