Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/dnn/src/layers/padding_layer.cpp
16337 views
1
// This file is part of OpenCV project.
2
// It is subject to the license terms in the LICENSE file found in the top-level directory
3
// of this distribution and at http://opencv.org/license.html.
4
5
// Copyright (C) 2017, Intel Corporation, all rights reserved.
6
// Third party copyrights are property of their respective owners.
7
8
/*
9
Implementation of padding layer, which adds paddings to input blob.
10
*/
11
12
#include "../precomp.hpp"
13
#include "layers_common.hpp"
14
#include "../op_halide.hpp"
15
#include <vector>
16
17
namespace cv
18
{
19
namespace dnn
20
{
21
22
class PaddingLayerImpl CV_FINAL : public PaddingLayer
23
{
24
public:
25
PaddingLayerImpl(const LayerParams &params)
26
{
27
setParamsFrom(params);
28
paddingValue = params.get<float>("value", 0);
29
inputDims = params.get<int>("input_dims", -1);
30
paddingType = params.get<String>("type", "constant");
31
32
CV_Assert(params.has("paddings"));
33
const DictValue& paddingsParam = params.get("paddings");
34
CV_Assert((paddingsParam.size() & 1) == 0);
35
36
paddings.resize(paddingsParam.size() / 2);
37
for (int i = 0; i < paddings.size(); ++i)
38
{
39
paddings[i].first = paddingsParam.get<int>(i * 2); // Pad before.
40
paddings[i].second = paddingsParam.get<int>(i * 2 + 1); // Pad after.
41
CV_Assert_N(paddings[i].first >= 0, paddings[i].second >= 0);
42
}
43
}
44
45
bool getMemoryShapes(const std::vector<MatShape> &inputs,
46
const int requiredOutputs,
47
std::vector<MatShape> &outputs,
48
std::vector<MatShape> &internals) const CV_OVERRIDE
49
{
50
CV_Assert(inputs.size() == 1);
51
const MatShape& inpShape = inputs[0];
52
CV_Assert(inpShape.size() >= paddings.size());
53
CV_Assert(inputDims == -1 || inpShape.size() == inputDims || inpShape.size() > paddings.size());
54
55
outputs.resize(1, inpShape);
56
int offset = (inputDims == -1 ? 0 : (inpShape.size() > inputDims ? 1 : 0));
57
for (int i = 0; i < paddings.size(); ++i)
58
{
59
outputs[0][offset + i] = inpShape[offset + i] + paddings[i].first + paddings[i].second;
60
}
61
return false;
62
}
63
64
void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays) CV_OVERRIDE
65
{
66
std::vector<Mat> inputs;
67
inputs_arr.getMatVector(inputs);
68
69
// Compute dstRanges.
70
const MatSize& inpShape = inputs[0].size;
71
dstRanges.resize(paddings.size());
72
73
int offset = 0;
74
if (inputDims != -1 && inputs[0].dims != inputDims)
75
{
76
dstRanges.insert(dstRanges.begin(), Range::all());
77
offset = 1;
78
}
79
80
for (int i = 0; i < paddings.size(); ++i)
81
{
82
dstRanges[offset + i].start = paddings[i].first;
83
dstRanges[offset + i].end = paddings[i].first + inpShape[offset + i];
84
}
85
86
// Add the rest of dimensions.
87
for (int i = dstRanges.size(); i < inputs[0].dims; ++i)
88
dstRanges.push_back(Range::all());
89
}
90
91
virtual bool supportBackend(int backendId) CV_OVERRIDE
92
{
93
return backendId == DNN_BACKEND_OPENCV ||
94
backendId == DNN_BACKEND_HALIDE && haveHalide() && dstRanges.size() == 4;
95
}
96
97
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
98
{
99
CV_TRACE_FUNCTION();
100
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
101
102
std::vector<Mat> inputs, outputs;
103
inputs_arr.getMatVector(inputs);
104
outputs_arr.getMatVector(outputs);
105
106
if (paddingType == "constant")
107
{
108
if (inputs_arr.depth() == CV_16S)
109
{
110
std::vector<float> paddingValue_fp32(1, paddingValue);
111
std::vector<int16_t> paddingValue_fp16(1);
112
convertFp16(paddingValue_fp32, paddingValue_fp16);
113
outputs[0].setTo(paddingValue_fp16[0]);
114
}
115
else
116
outputs[0].setTo(paddingValue);
117
inputs[0].copyTo(outputs[0](dstRanges));
118
}
119
else if (paddingType == "reflect")
120
{
121
CV_Assert(inputs.size() == 1);
122
CV_Assert(outputs.size() == 1);
123
CV_Assert(inputs[0].dims == 4);
124
CV_Assert(outputs[0].dims == 4);
125
126
if (inputs[0].size[0] != outputs[0].size[0] || inputs[0].size[1] != outputs[0].size[1])
127
CV_Error(Error::StsNotImplemented, "Only spatial reflection padding is supported.");
128
129
const int inpHeight = inputs[0].size[2];
130
const int inpWidth = inputs[0].size[3];
131
const int outHeight = outputs[0].size[2];
132
const int outWidth = outputs[0].size[3];
133
const int padTop = dstRanges[2].start;
134
const int padBottom = outHeight - dstRanges[2].end;
135
const int padLeft = dstRanges[3].start;
136
const int padRight = outWidth - dstRanges[3].end;
137
CV_CheckLT(padTop, inpHeight, ""); CV_CheckLT(padBottom, inpHeight, "");
138
CV_CheckLT(padLeft, inpWidth, ""); CV_CheckLT(padRight, inpWidth, "");
139
140
for (size_t n = 0; n < inputs[0].size[0]; ++n)
141
{
142
for (size_t ch = 0; ch < inputs[0].size[1]; ++ch)
143
{
144
copyMakeBorder(getPlane(inputs[0], n, ch),
145
getPlane(outputs[0], n, ch),
146
padTop, padBottom, padLeft, padRight,
147
BORDER_REFLECT_101);
148
}
149
}
150
}
151
else
152
CV_Error(Error::StsNotImplemented, "Unknown padding type: " + paddingType);
153
}
154
155
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs) CV_OVERRIDE
156
{
157
#ifdef HAVE_HALIDE
158
int inW, inH, inC, inN;
159
int minN = std::max(dstRanges[0].start, 0);
160
int minC = std::max(dstRanges[1].start, 0);
161
int minY = std::max(dstRanges[2].start, 0);
162
int minX = std::max(dstRanges[3].start, 0);
163
Halide::Buffer<float> inputBuffer = halideBuffer(inputs[0]);
164
getCanonicalSize(inputBuffer, &inW, &inH, &inC, &inN);
165
166
Halide::Var x("x"), y("y"), c("c"), n("n");
167
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
168
Halide::Func padded =
169
Halide::BoundaryConditions::constant_exterior(inputBuffer, paddingValue);
170
top(x, y, c, n) = padded(x - minX, y - minY, c - minC, n - minN);
171
return Ptr<BackendNode>(new HalideBackendNode(top));
172
#endif // HAVE_HALIDE
173
return Ptr<BackendNode>();
174
}
175
176
private:
177
std::vector<std::pair<int, int> > paddings; // Pairs pad before, pad after.
178
std::vector<Range> dstRanges;
179
int inputDims;
180
float paddingValue;
181
std::string paddingType;
182
};
183
184
Ptr<PaddingLayer> PaddingLayer::create(const LayerParams &params)
185
{
186
return Ptr<PaddingLayer>(new PaddingLayerImpl(params));
187
}
188
189
}
190
}
191
192