Skip to content

Commit 77fa59c

Browse files
l-batalalek
authored andcommitted
Merge pull request opencv#14301 from l-bat:conv3d
Support Convolution3D layer on IE backend (opencv#14301) * Add Convolution3D layer * Disable CXX11 * Fixed tests * Add Pooling3D layer * Merge Conv2d with Conv3d and Pool2d with Pool3d layers * Split pads * Add Deconvolution layer * Refactoring * Deduplication * Refactoring * Add utils for Convolution and Pooling layers
1 parent 3bcbd2a commit 77fa59c

File tree

10 files changed

+411
-288
lines changed

10 files changed

+411
-288
lines changed

modules/dnn/include/opencv2/dnn/all_layers.hpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,10 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
210210
class CV_EXPORTS BaseConvolutionLayer : public Layer
211211
{
212212
public:
213-
Size kernel, stride, pad, dilation, adjustPad;
213+
CV_DEPRECATED_EXTERNAL Size kernel, stride, pad, dilation, adjustPad;
214+
std::vector<size_t> adjust_pads;
215+
std::vector<size_t> kernel_size, strides, dilations;
216+
std::vector<size_t> pads_begin, pads_end;
214217
String padMode;
215218
int numOutput;
216219
};
@@ -243,9 +246,10 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
243246
{
244247
public:
245248
int type;
246-
Size kernel, stride;
247-
int pad_l, pad_t, pad_r, pad_b;
248-
CV_DEPRECATED_EXTERNAL Size pad;
249+
std::vector<size_t> kernel_size, strides;
250+
std::vector<size_t> pads_begin, pads_end;
251+
CV_DEPRECATED_EXTERNAL Size kernel, stride, pad;
252+
CV_DEPRECATED_EXTERNAL int pad_l, pad_t, pad_r, pad_b;
249253
bool globalPooling;
250254
bool computeMaxIdx;
251255
String padMode;

modules/dnn/src/dnn.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,6 +2263,7 @@ struct Net::Impl
22632263
if (isAsync)
22642264
CV_Error(Error::StsNotImplemented, "Default implementation fallbacks in asynchronous mode");
22652265

2266+
CV_Assert(layer->supportBackend(DNN_BACKEND_OPENCV));
22662267
if (preferableBackend == DNN_BACKEND_OPENCV && IS_DNN_OPENCL_TARGET(preferableTarget))
22672268
{
22682269
std::vector<UMat> umat_inputBlobs = OpenCLBackendWrapper::getUMatVector(ld.inputBlobsWrappers);

modules/dnn/src/layers/convolution_layer.cpp

Lines changed: 111 additions & 87 deletions
Large diffs are not rendered by default.

modules/dnn/src/layers/layers_common.cpp

Lines changed: 76 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -57,47 +57,39 @@ std::string makeName(const std::string& str1, const std::string& str2)
5757
}
5858

5959
bool getParameter(const LayerParams &params, const std::string& nameBase, const std::string& nameAll,
60-
int &parameterH, int &parameterW, bool hasDefault = false, const int& defaultValue = 0)
60+
std::vector<size_t>& parameter, bool hasDefault = false, const std::vector<size_t>& defaultValue = std::vector<size_t>(2, 0))
6161
{
6262
std::string nameH = makeName(nameBase, std::string("_h"));
6363
std::string nameW = makeName(nameBase, std::string("_w"));
6464
std::string nameAll_ = nameAll;
65-
if(nameAll_ == "")
66-
{
65+
if (nameAll_ == "")
6766
nameAll_ = nameBase;
68-
}
6967

7068
if (params.has(nameH) && params.has(nameW))
7169
{
72-
parameterH = params.get<int>(nameH);
73-
parameterW = params.get<int>(nameW);
70+
CV_Assert(params.get<int>(nameH) >= 0 && params.get<int>(nameW) >= 0);
71+
parameter.push_back(params.get<int>(nameH));
72+
parameter.push_back(params.get<int>(nameW));
7473
return true;
7574
}
7675
else
7776
{
7877
if (params.has(nameAll_))
7978
{
8079
DictValue param = params.get(nameAll_);
81-
parameterH = param.get<int>(0);
82-
if (param.size() == 1)
83-
{
84-
parameterW = parameterH;
85-
}
86-
else if (param.size() == 2)
87-
{
88-
parameterW = param.get<int>(1);
89-
}
90-
else
91-
{
92-
return false;
80+
for (int i = 0; i < param.size(); i++) {
81+
CV_Assert(param.get<int>(i) >= 0);
82+
parameter.push_back(param.get<int>(i));
9383
}
84+
if (parameter.size() == 1)
85+
parameter.resize(2, parameter[0]);
9486
return true;
9587
}
9688
else
9789
{
98-
if(hasDefault)
90+
if (hasDefault)
9991
{
100-
parameterH = parameterW = defaultValue;
92+
parameter = defaultValue;
10193
return true;
10294
}
10395
else
@@ -108,46 +100,55 @@ bool getParameter(const LayerParams &params, const std::string& nameBase, const
108100
}
109101
}
110102

111-
void getKernelSize(const LayerParams &params, int &kernelH, int &kernelW)
103+
void getKernelSize(const LayerParams &params, std::vector<size_t>& kernel)
112104
{
113-
if(!util::getParameter(params, "kernel", "kernel_size", kernelH, kernelW))
114-
{
105+
if (!util::getParameter(params, "kernel", "kernel_size", kernel))
115106
CV_Error(cv::Error::StsBadArg, "kernel_size (or kernel_h and kernel_w) not specified");
116-
}
117107

118-
CV_Assert(kernelH > 0 && kernelW > 0);
108+
for (int i = 0; i < kernel.size(); i++)
109+
CV_Assert(kernel[i] > 0);
119110
}
120111

121-
void getStrideAndPadding(const LayerParams &params, int &padT, int &padL, int &padB, int &padR, int &strideH, int &strideW, cv::String& padMode)
112+
void getStrideAndPadding(const LayerParams &params, std::vector<size_t>& pads_begin, std::vector<size_t>& pads_end,
113+
std::vector<size_t>& strides, cv::String& padMode, size_t kernel_size = 2)
122114
{
123115
if (params.has("pad_l") && params.has("pad_t") && params.has("pad_r") && params.has("pad_b")) {
124-
padT = params.get<int>("pad_t");
125-
padL = params.get<int>("pad_l");
126-
padB = params.get<int>("pad_b");
127-
padR = params.get<int>("pad_r");
116+
CV_Assert(params.get<int>("pad_t") >= 0 && params.get<int>("pad_l") >= 0 &&
117+
params.get<int>("pad_b") >= 0 && params.get<int>("pad_r") >= 0);
118+
pads_begin.push_back(params.get<int>("pad_t"));
119+
pads_begin.push_back(params.get<int>("pad_l"));
120+
pads_end.push_back(params.get<int>("pad_b"));
121+
pads_end.push_back(params.get<int>("pad_r"));
128122
}
129123
else {
130-
util::getParameter(params, "pad", "pad", padT, padL, true, 0);
131-
padB = padT;
132-
padR = padL;
124+
util::getParameter(params, "pad", "pad", pads_begin, true, std::vector<size_t>(kernel_size, 0));
125+
if (pads_begin.size() < 4)
126+
pads_end = pads_begin;
127+
else
128+
{
129+
pads_end = std::vector<size_t>(pads_begin.begin() + pads_begin.size() / 2, pads_begin.end());
130+
pads_begin.resize(pads_begin.size() / 2);
131+
}
132+
CV_Assert(pads_begin.size() == pads_end.size());
133133
}
134-
util::getParameter(params, "stride", "stride", strideH, strideW, true, 1);
134+
util::getParameter(params, "stride", "stride", strides, true, std::vector<size_t>(kernel_size, 1));
135135

136136
padMode = "";
137137
if (params.has("pad_mode"))
138138
{
139139
padMode = params.get<String>("pad_mode");
140140
}
141141

142-
CV_Assert(padT >= 0 && padL >= 0 && padB >= 0 && padR >= 0 && strideH > 0 && strideW > 0);
142+
for (int i = 0; i < strides.size(); i++)
143+
CV_Assert(strides[i] > 0);
143144
}
144145
}
145146

146-
147-
void getPoolingKernelParams(const LayerParams &params, int &kernelH, int &kernelW, bool &globalPooling,
148-
int &padT, int &padL, int &padB, int &padR, int &strideH, int &strideW, cv::String &padMode)
147+
void getPoolingKernelParams(const LayerParams &params, std::vector<size_t>& kernel, bool &globalPooling,
148+
std::vector<size_t>& pads_begin, std::vector<size_t>& pads_end,
149+
std::vector<size_t>& strides, cv::String &padMode)
149150
{
150-
util::getStrideAndPadding(params, padT, padL, padB, padR, strideH, strideW, padMode);
151+
util::getStrideAndPadding(params, pads_begin, pads_end, strides, padMode);
151152

152153
globalPooling = params.has("global_pooling") &&
153154
params.get<bool>("global_pooling");
@@ -158,25 +159,30 @@ void getPoolingKernelParams(const LayerParams &params, int &kernelH, int &kernel
158159
{
159160
CV_Error(cv::Error::StsBadArg, "In global_pooling mode, kernel_size (or kernel_h and kernel_w) cannot be specified");
160161
}
161-
if(padT != 0 || padL != 0 || padB != 0 || padR != 0 || strideH != 1 || strideW != 1)
162-
{
163-
CV_Error(cv::Error::StsBadArg, "In global_pooling mode, pads must be = 0, and stride_h and stride_w must be = 1");
162+
for (int i = 0; i < pads_begin.size(); i++) {
163+
if (pads_begin[i] != 0 || pads_end[i] != 0)
164+
CV_Error(cv::Error::StsBadArg, "In global_pooling mode, pads must be = 0");
165+
}
166+
for (int i = 0; i < strides.size(); i++) {
167+
if (strides[i] != 1)
168+
CV_Error(cv::Error::StsBadArg, "In global_pooling mode, strides must be = 1");
164169
}
165170
}
166171
else
167172
{
168-
util::getKernelSize(params, kernelH, kernelW);
173+
util::getKernelSize(params, kernel);
169174
}
170175
}
171176

172-
void getConvolutionKernelParams(const LayerParams &params, int &kernelH, int &kernelW, int &padT, int &padL, int &padB, int &padR,
173-
int &strideH, int &strideW, int &dilationH, int &dilationW, cv::String &padMode)
177+
void getConvolutionKernelParams(const LayerParams &params, std::vector<size_t>& kernel, std::vector<size_t>& pads_begin,
178+
std::vector<size_t>& pads_end, std::vector<size_t>& strides, std::vector<size_t>& dilations, cv::String &padMode)
174179
{
175-
util::getKernelSize(params, kernelH, kernelW);
176-
util::getStrideAndPadding(params, padT, padL, padB, padR, strideH, strideW, padMode);
177-
util::getParameter(params, "dilation", "dilation", dilationH, dilationW, true, 1);
180+
util::getKernelSize(params, kernel);
181+
util::getStrideAndPadding(params, pads_begin, pads_end, strides, padMode, kernel.size());
182+
util::getParameter(params, "dilation", "dilation", dilations, true, std::vector<size_t>(kernel.size(), 1));
178183

179-
CV_Assert(dilationH > 0 && dilationW > 0);
184+
for (int i = 0; i < dilations.size(); i++)
185+
CV_Assert(dilations[i] > 0);
180186
}
181187

182188
// From TensorFlow code:
@@ -188,42 +194,46 @@ void getConvolutionKernelParams(const LayerParams &params, int &kernelH, int &ke
188194
// We pad Pr/2 on the left and Pr - Pr/2 on the right, Pc/2 on the top
189195
// and Pc - Pc/2 on the bottom. When Pr or Pc is odd, this means
190196
// we pad more on the right and bottom than on the top and left.
191-
void getConvPoolOutParams(const Size& inp, const Size &kernel,
192-
const Size &stride, const String &padMode,
193-
const Size &dilation, Size& out)
197+
void getConvPoolOutParams(const std::vector<int>& inp, const std::vector<size_t>& kernel,
198+
const std::vector<size_t>& stride, const String &padMode,
199+
const std::vector<size_t>& dilation, std::vector<int>& out)
194200
{
195201
if (padMode == "VALID")
196202
{
197-
out.height = (inp.height - (dilation.height * (kernel.height - 1) + 1) + stride.height) / stride.height;
198-
out.width = (inp.width - (dilation.width * (kernel.width - 1) + 1) + stride.width) / stride.width;
203+
for (int i = 0; i < inp.size(); i++)
204+
out.push_back((inp[i] - dilation[i] * (kernel[i] - 1) - 1 + stride[i]) / stride[i]);
199205
}
200206
else if (padMode == "SAME")
201207
{
202-
out.height = (inp.height - 1 + stride.height) / stride.height;
203-
out.width = (inp.width - 1 + stride.width) / stride.width;
208+
for (int i = 0; i < inp.size(); i++)
209+
out.push_back((inp[i] - 1 + stride[i]) / stride[i]);
204210
}
205211
else
206212
{
207213
CV_Error(Error::StsError, "Unsupported padding mode");
208214
}
209215
}
210216

211-
void getConvPoolPaddings(const Size& inp, const Size& out,
212-
const Size &kernel, const Size &stride,
213-
const String &padMode, const Size &dilation, int &padT, int &padL, int &padB, int &padR)
217+
void getConvPoolPaddings(const std::vector<int>& inp, const std::vector<int>& out,
218+
const std::vector<size_t>& kernel, const std::vector<size_t>& strides,
219+
const String &padMode, const std::vector<size_t>& dilation,
220+
std::vector<size_t>& pads_begin, std::vector<size_t>& pads_end)
214221
{
215222
if (padMode == "VALID")
216223
{
217-
padT = padL = padB = padR = 0;
224+
pads_begin.assign(kernel.size(), 0);
225+
pads_end.assign(kernel.size(), 0);
218226
}
219227
else if (padMode == "SAME")
220228
{
221-
int Ph = std::max(0, (out.height - 1) * stride.height + (dilation.height * (kernel.height - 1) + 1) - inp.height);
222-
int Pw = std::max(0, (out.width - 1) * stride.width + (dilation.width * (kernel.width - 1) + 1) - inp.width);
223-
// For odd values of total padding, add more padding at the 'right'
224-
// side of the given dimension.
225-
padT= padB = Ph / 2;
226-
padL = padR = Pw / 2;
229+
CV_Assert_N(kernel.size() == dilation.size(), kernel.size() == strides.size(),
230+
kernel.size() == inp.size(), kernel.size() == out.size());
231+
pads_begin.resize(kernel.size());
232+
pads_end.resize(kernel.size());
233+
for (int i = 0; i < pads_begin.size(); i++) {
234+
int pad = ((out[i] - 1) * strides[i] + dilation[i] * (kernel[i] - 1) + 1 - inp[i]) / 2;
235+
pads_begin[i] = pads_end[i] = std::max(0, pad);
236+
}
227237
}
228238
}
229239

modules/dnn/src/layers/layers_common.hpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,20 @@ namespace cv
5959
{
6060
namespace dnn
6161
{
62+
void getConvolutionKernelParams(const LayerParams &params, std::vector<size_t>& kernel, std::vector<size_t>& pads_begin,
63+
std::vector<size_t>& pads_end, std::vector<size_t>& strides, std::vector<size_t>& dilations, cv::String &padMode);
6264

63-
void getConvolutionKernelParams(const LayerParams &params, int &kernelH, int &kernelW, int &padT, int &padL, int &padB, int &padR,
64-
int &strideH, int &strideW, int &dilationH, int &dilationW, cv::String& padMode);
65+
void getPoolingKernelParams(const LayerParams &params, std::vector<size_t>& kernel, bool &globalPooling,
66+
std::vector<size_t>& pads_begin, std::vector<size_t>& pads_end, std::vector<size_t>& strides, cv::String &padMode);
6567

66-
void getPoolingKernelParams(const LayerParams &params, int &kernelH, int &kernelW, bool &globalPooling,
67-
int &padT, int &padL, int &padB, int &padR, int &strideH, int &strideW, cv::String& padMode);
68-
69-
void getConvPoolOutParams(const Size& inp, const Size &kernel,
70-
const Size &stride, const String &padMode,
71-
const Size &dilation, Size& out);
72-
73-
74-
void getConvPoolPaddings(const Size& inp, const Size& out,
75-
const Size &kernel, const Size &stride,
76-
const String &padMode, const Size &dilation, int &padT, int &padL, int &padB, int &padR);
68+
void getConvPoolOutParams(const std::vector<int>& inp, const std::vector<size_t>& kernel,
69+
const std::vector<size_t>& stride, const String &padMode,
70+
const std::vector<size_t>& dilation, std::vector<int>& out);
7771

72+
void getConvPoolPaddings(const std::vector<int>& inp, const std::vector<int>& out,
73+
const std::vector<size_t>& kernel, const std::vector<size_t>& strides,
74+
const String &padMode, const std::vector<size_t>& dilation,
75+
std::vector<size_t>& pads_begin, std::vector<size_t>& pads_end);
7876
}
7977
}
8078

0 commit comments

Comments
 (0)