Added Reshape layer and altered importer to correctly handle its params.

pull/265/head
Vitaliy Lyudvichenko 10 years ago
parent 3aa37d2971
commit 172419ea1c
  1. 7
      modules/dnn/include/opencv2/dnn/blob.hpp
  2. 11
      modules/dnn/include/opencv2/dnn/blob.inl.hpp
  3. 2
      modules/dnn/include/opencv2/dnn/dict.hpp
  4. 50
      modules/dnn/src/caffe_importer.cpp
  5. 0
      modules/dnn/src/layers/deconvolution_layer.cpp
  6. 2
      modules/dnn/src/layers/elementwise_layers.cpp
  7. 137
      modules/dnn/src/layers/reshape_layer.cpp
  8. 0
      modules/dnn/src/layers/slice_layer.cpp
  9. 0
      modules/dnn/src/layers/split_layer.cpp

@ -10,7 +10,7 @@ namespace dnn
{
struct BlobShape
{
explicit BlobShape(int ndims, int fill = 1);
explicit BlobShape(int ndims = 4, int fill = 1);
BlobShape(int num, int cn, int rows, int cols);
BlobShape(int ndims, const int *sizes);
BlobShape(const std::vector<int> &sizes);
@ -25,15 +25,16 @@ namespace dnn
int operator[](int axis) const;
int &operator[](int axis);
//same as size(), but size of non-existing dimensions equal to 1
int xsize(int axis) const;
ptrdiff_t total();
const int *ptr() const;
bool equal(const BlobShape &other) const;
private:
BlobShape();
cv::AutoBuffer<int,4> sz;
};

@ -79,6 +79,17 @@ inline int &BlobShape::operator[] (int axis)
return sz[(axis < 0) ? axis + dims() : axis];
}
inline ptrdiff_t BlobShape::total()
{
CV_Assert(dims() >= 1);
ptrdiff_t res = 1;
for (int i = 0; i < dims(); i++)
res *= sz[i];
return res;
}
inline const int *BlobShape::ptr() const
{
return sz;

@ -274,7 +274,7 @@ inline bool DictValue::isReal() const
return (type == Param::REAL || type == Param::INT);
}
int DictValue::size() const
inline int DictValue::size() const
{
switch (type)
{

@ -37,30 +37,6 @@ namespace
ReadNetParamsFromBinaryFileOrDie(caffeModel, &netBinary);
}
inline bool skipCaffeLayerParam(const FieldDescriptor *fd)
{
const std::string &name = fd->name();
if (fd->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
{
static const char *SKIP_FIELDS[] = { "type", "name", "top", "bottom", NULL };
for (int i = 0; SKIP_FIELDS[i]; i++)
{
if (name == SKIP_FIELDS[i])
return true;
}
return false;
}
else
{
static const std::string _param("_param");
bool endsWith_param = (name.size() >= _param.size()) && name.compare(name.size() - _param.size(), _param.size(), _param) == 0;
return !endsWith_param;
}
}
void addParam(const Message &msg, const FieldDescriptor *field, cv::dnn::LayerParams &params)
{
const Reflection *refl = msg.GetReflection();
@ -85,6 +61,12 @@ namespace
case FieldDescriptor::CPPTYPE_UINT32:
SET_UP_FILED(GetUInt32, DictValue::arrayInt, ::google::protobuf::uint32);
break;
case FieldDescriptor::CPPTYPE_INT64:
SET_UP_FILED(GetInt32, DictValue::arrayInt, ::google::protobuf::int64);
break;
case FieldDescriptor::CPPTYPE_UINT64:
SET_UP_FILED(GetUInt32, DictValue::arrayInt, ::google::protobuf::uint64);
break;
case FieldDescriptor::CPPTYPE_BOOL:
SET_UP_FILED(GetBool, DictValue::arrayInt, bool);
break;
@ -121,7 +103,13 @@ namespace
}
}
void extractLayerParams(const Message &msg, cv::dnn::LayerParams &params)
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 &params, bool isInternal = false)
{
const Descriptor *msgDesc = msg.GetDescriptor();
const Reflection *msgRefl = msg.GetReflection();
@ -130,19 +118,21 @@ namespace
{
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->has_default_value()*/)) ||
(fd->is_optional() && msgRefl->HasField(msg, fd)) ||
(fd->is_repeated() && msgRefl->FieldSize(msg, fd) > 0);
if ( !hasData || skipCaffeLayerParam(fd) )
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);
extractLayerParams(msgRefl->GetRepeatedMessage(msg, fd, 0), params, true);
else
extractLayerParams(msgRefl->GetMessage(msg, fd), params);
extractLayerParams(msgRefl->GetMessage(msg, fd), params, true);
}
else
{

@ -132,7 +132,7 @@ namespace dnn
template<typename TFloat>
inline TFloat operator()(TFloat x)
{
return log((TFloat)1 + exp(x));
return log((TFloat)1 + exp(-abs(x)));
}
};

@ -0,0 +1,137 @@
#include "../precomp.hpp"
#include "layers_common.hpp"
namespace cv
{
namespace dnn
{
//TODO: Extend cv::Mat::reshape method
class ReshapeLayer : public Layer
{
public:
ReshapeLayer(LayerParams &params);
void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs);
void forward(std::vector<Blob*>&, std::vector<Blob>&) {}
protected:
BlobShape shapeDesc;
int inAxis, inNumAxes, autoAxisIdx;
void computeOutputShape(int startAxis, int endAxis, BlobShape &inpShape, BlobShape &outShape);
};
ReshapeLayer::ReshapeLayer(LayerParams &params)
{
DictValue paramShape = params.get("dim");
shapeDesc = BlobShape(paramShape.size());
autoAxisIdx = -1;
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;
}
inAxis = params.get<int>("axis", 0);
inNumAxes = params.get<int>("num_axes", -1);
CV_Assert(inNumAxes >= -1);
}
void ReshapeLayer::allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs)
{
CV_Assert(inputs.size() == 1);
outputs.resize(1);
Blob &inpBlob = *inputs[0];
Blob &outBlob = outputs[0];
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(newDims);
computeOutputShape(startAxis, endAxis, inpShape, outShape);
outBlob.shareFrom(inpBlob);
outBlob.reshape(outShape);
}
void ReshapeLayer::computeOutputShape(int startAxis, int endAxis, BlobShape &inpShape, BlobShape &outShape)
{
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, "new shape contains a 0, but there was no corresponding bottom axis to copy");
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::StsBadArg, "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));
}
REGISTER_LAYER_CLASS(Reshape, ReshapeLayer)
REGISTER_LAYER_FUNC(Flatten, createFlattenLayer)
}
}
Loading…
Cancel
Save