mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Layers for fast-neural-style models: https://github.com/jcjohnson/fast-neural-style
This commit is contained in:
@@ -10,6 +10,7 @@ Implementation of padding layer, which adds paddings to input blob.
|
||||
*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "layers_common.hpp"
|
||||
#include "op_halide.hpp"
|
||||
#include <vector>
|
||||
|
||||
@@ -26,6 +27,7 @@ public:
|
||||
setParamsFrom(params);
|
||||
paddingValue = params.get<float>("value", 0);
|
||||
inputDims = params.get<int>("input_dims", -1);
|
||||
paddingType = params.get<String>("type", "constant");
|
||||
|
||||
CV_Assert(params.has("paddings"));
|
||||
const DictValue& paddingsParam = params.get("paddings");
|
||||
@@ -94,8 +96,45 @@ public:
|
||||
CV_TRACE_FUNCTION();
|
||||
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
|
||||
|
||||
outputs[0].setTo(paddingValue);
|
||||
inputs[0]->copyTo(outputs[0](dstRanges));
|
||||
if (paddingType == "constant")
|
||||
{
|
||||
outputs[0].setTo(paddingValue);
|
||||
inputs[0]->copyTo(outputs[0](dstRanges));
|
||||
}
|
||||
else if (paddingType == "reflect")
|
||||
{
|
||||
CV_Assert(inputs.size() == 1);
|
||||
CV_Assert(outputs.size() == 1);
|
||||
CV_Assert(inputs[0]->dims == 4);
|
||||
CV_Assert(outputs[0].dims == 4);
|
||||
|
||||
if (inputs[0]->size[0] != outputs[0].size[0] || inputs[0]->size[1] != outputs[0].size[1])
|
||||
CV_Error(Error::StsNotImplemented, "Only spatial reflection padding is supported.");
|
||||
|
||||
const int inpHeight = inputs[0]->size[2];
|
||||
const int inpWidth = inputs[0]->size[3];
|
||||
const int outHeight = outputs[0].size[2];
|
||||
const int outWidth = outputs[0].size[3];
|
||||
const int padTop = dstRanges[2].start;
|
||||
const int padBottom = outHeight - dstRanges[2].end;
|
||||
const int padLeft = dstRanges[3].start;
|
||||
const int padRight = outWidth - dstRanges[3].end;
|
||||
CV_Assert(padTop < inpHeight, padBottom < inpHeight,
|
||||
padLeft < inpWidth, padRight < inpWidth);
|
||||
|
||||
for (size_t n = 0; n < inputs[0]->size[0]; ++n)
|
||||
{
|
||||
for (size_t ch = 0; ch < inputs[0]->size[1]; ++ch)
|
||||
{
|
||||
copyMakeBorder(getPlane(*inputs[0], n, ch),
|
||||
getPlane(outputs[0], n, ch),
|
||||
padTop, padBottom, padLeft, padRight,
|
||||
BORDER_REFLECT_101);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
CV_Error(Error::StsNotImplemented, "Unknown padding type: " + paddingType);
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
@@ -124,6 +163,7 @@ private:
|
||||
std::vector<Range> dstRanges;
|
||||
int inputDims;
|
||||
float paddingValue;
|
||||
std::string paddingType;
|
||||
};
|
||||
|
||||
Ptr<PaddingLayer> PaddingLayer::create(const LayerParams ¶ms)
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
axis = params.get<int>("axis", 1);
|
||||
if (params.has("slice_point"))
|
||||
{
|
||||
CV_Assert(!params.has("begin") && !params.has("size"));
|
||||
CV_Assert(!params.has("begin") && !params.has("size") && !params.has("end"));
|
||||
const DictValue &indicesValue = params.get("slice_point");
|
||||
sliceRanges.resize(indicesValue.size() + 1,
|
||||
std::vector<Range>(axis + 1, Range::all()));
|
||||
@@ -71,24 +71,34 @@ public:
|
||||
}
|
||||
sliceRanges.back()[axis].start = prevSlice;
|
||||
}
|
||||
else if (params.has("begin") && params.has("size"))
|
||||
else if (params.has("begin"))
|
||||
{
|
||||
CV_Assert(params.has("size") ^ params.has("end"));
|
||||
const DictValue &begins = params.get("begin");
|
||||
const DictValue &sizes = params.get("size");
|
||||
CV_Assert(begins.size() == sizes.size());
|
||||
const DictValue &sizesOrEnds = params.has("size") ? params.get("size") : params.get("end");
|
||||
CV_Assert(begins.size() == sizesOrEnds.size());
|
||||
|
||||
sliceRanges.resize(1);
|
||||
sliceRanges[0].resize(begins.size(), Range::all());
|
||||
for (int i = 0; i < begins.size(); ++i)
|
||||
{
|
||||
int start = begins.get<int>(i);
|
||||
int size = sizes.get<int>(i);
|
||||
int sizeOrEnd = sizesOrEnds.get<int>(i); // It may be negative to reverse indexation.
|
||||
CV_Assert(start >= 0);
|
||||
CV_Assert(size == -1 || size > 0); // -1 value means range [start, axis_size).
|
||||
|
||||
sliceRanges[0][i].start = start;
|
||||
if (size > 0)
|
||||
sliceRanges[0][i].end = start + size;
|
||||
if (params.has("size"))
|
||||
{
|
||||
int size = sizeOrEnd;
|
||||
CV_Assert(size == -1 || size > 0); // -1 value means range [start, axis_size).
|
||||
sliceRanges[0][i].end = start > 0 ? start + size : -1; // We'll finalize a negative value later.
|
||||
}
|
||||
else
|
||||
{
|
||||
int end = sizeOrEnd;
|
||||
CV_Assert(end < 0 || end > start); // End index is excluded.
|
||||
sliceRanges[0][i].end = end; // We'll finalize a negative value later.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,8 +119,7 @@ public:
|
||||
CV_Assert(sliceRanges[i].size() <= inpShape.size());
|
||||
for (int j = 0; j < sliceRanges[i].size(); ++j)
|
||||
{
|
||||
outputs[i][j] = std::min(sliceRanges[i][j].end, inpShape[j]) -
|
||||
std::max(sliceRanges[i][j].start, 0);
|
||||
outputs[i][j] = clamp(sliceRanges[i][j], inpShape[j]).size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,8 +161,7 @@ public:
|
||||
// Clamp.
|
||||
for (int j = 0; j < sliceRanges[i].size(); ++j)
|
||||
{
|
||||
sliceRanges[i][j].start = std::max(0, sliceRanges[i][j].start);
|
||||
sliceRanges[i][j].end = std::min(sliceRanges[i][j].end, inpShape[j]);
|
||||
sliceRanges[i][j] = clamp(sliceRanges[i][j], inpShape[j]);
|
||||
}
|
||||
// Fill the rest of ranges.
|
||||
for (int j = sliceRanges[i].size(); j < inpShape[-1]; ++j)
|
||||
|
||||
Reference in New Issue
Block a user