Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/dnn/src/layers/layers_common.cpp
16337 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
14
// Copyright (C) 2017, Intel Corporation, all rights reserved.
15
// Third party copyrights are property of their respective owners.
16
//
17
// Redistribution and use in source and binary forms, with or without modification,
18
// are permitted provided that the following conditions are met:
19
//
20
// * Redistribution's of source code must retain the above copyright notice,
21
// this list of conditions and the following disclaimer.
22
//
23
// * Redistribution's in binary form must reproduce the above copyright notice,
24
// this list of conditions and the following disclaimer in the documentation
25
// and/or other materials provided with the distribution.
26
//
27
// * The name of the copyright holders may not be used to endorse or promote products
28
// derived from this software without specific prior written permission.
29
//
30
// This software is provided by the copyright holders and contributors "as is" and
31
// any express or implied warranties, including, but not limited to, the implied
32
// warranties of merchantability and fitness for a particular purpose are disclaimed.
33
// In no event shall the Intel Corporation or contributors be liable for any direct,
34
// indirect, incidental, special, exemplary, or consequential damages
35
// (including, but not limited to, procurement of substitute goods or services;
36
// loss of use, data, or profits; or business interruption) however caused
37
// and on any theory of liability, whether in contract, strict liability,
38
// or tort (including negligence or otherwise) arising in any way out of
39
// the use of this software, even if advised of the possibility of such damage.
40
//
41
//M*/
42
43
#include "../precomp.hpp"
44
#include "layers_common.hpp"
45
46
namespace cv
47
{
48
namespace dnn
49
{
50
51
namespace util
52
{
53
54
std::string makeName(const std::string& str1, const std::string& str2)
55
{
56
return str1 + str2;
57
}
58
59
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)
61
{
62
std::string nameH = makeName(nameBase, std::string("_h"));
63
std::string nameW = makeName(nameBase, std::string("_w"));
64
std::string nameAll_ = nameAll;
65
if(nameAll_ == "")
66
{
67
nameAll_ = nameBase;
68
}
69
70
if (params.has(nameH) && params.has(nameW))
71
{
72
parameterH = params.get<int>(nameH);
73
parameterW = params.get<int>(nameW);
74
return true;
75
}
76
else
77
{
78
if (params.has(nameAll_))
79
{
80
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;
93
}
94
return true;
95
}
96
else
97
{
98
if(hasDefault)
99
{
100
parameterH = parameterW = defaultValue;
101
return true;
102
}
103
else
104
{
105
return false;
106
}
107
}
108
}
109
}
110
111
void getKernelSize(const LayerParams &params, int &kernelH, int &kernelW)
112
{
113
if(!util::getParameter(params, "kernel", "kernel_size", kernelH, kernelW))
114
{
115
CV_Error(cv::Error::StsBadArg, "kernel_size (or kernel_h and kernel_w) not specified");
116
}
117
118
CV_Assert(kernelH > 0 && kernelW > 0);
119
}
120
121
void getStrideAndPadding(const LayerParams &params, int &padT, int &padL, int &padB, int &padR, int &strideH, int &strideW, cv::String& padMode)
122
{
123
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");
128
}
129
else {
130
util::getParameter(params, "pad", "pad", padT, padL, true, 0);
131
padB = padT;
132
padR = padL;
133
}
134
util::getParameter(params, "stride", "stride", strideH, strideW, true, 1);
135
136
padMode = "";
137
if (params.has("pad_mode"))
138
{
139
padMode = params.get<String>("pad_mode");
140
}
141
142
CV_Assert(padT >= 0 && padL >= 0 && padB >= 0 && padR >= 0 && strideH > 0 && strideW > 0);
143
}
144
}
145
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)
149
{
150
util::getStrideAndPadding(params, padT, padL, padB, padR, strideH, strideW, padMode);
151
152
globalPooling = params.has("global_pooling") &&
153
params.get<bool>("global_pooling");
154
155
if (globalPooling)
156
{
157
if(params.has("kernel_h") || params.has("kernel_w") || params.has("kernel_size"))
158
{
159
CV_Error(cv::Error::StsBadArg, "In global_pooling mode, kernel_size (or kernel_h and kernel_w) cannot be specified");
160
}
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");
164
}
165
}
166
else
167
{
168
util::getKernelSize(params, kernelH, kernelW);
169
}
170
}
171
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)
174
{
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);
178
179
CV_Assert(dilationH > 0 && dilationW > 0);
180
}
181
182
// From TensorFlow code:
183
// Total padding on rows and cols is
184
// Pr = (R' - 1) * S + Kr - R
185
// Pc = (C' - 1) * S + Kc - C
186
// where (R', C') are output dimensions, (R, C) are input dimensions, S
187
// is stride, (Kr, Kc) are filter dimensions.
188
// We pad Pr/2 on the left and Pr - Pr/2 on the right, Pc/2 on the top
189
// and Pc - Pc/2 on the bottom. When Pr or Pc is odd, this means
190
// 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)
194
{
195
if (padMode == "VALID")
196
{
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;
199
}
200
else if (padMode == "SAME")
201
{
202
out.height = (inp.height - 1 + stride.height) / stride.height;
203
out.width = (inp.width - 1 + stride.width) / stride.width;
204
}
205
else
206
{
207
CV_Error(Error::StsError, "Unsupported padding mode");
208
}
209
}
210
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)
214
{
215
if (padMode == "VALID")
216
{
217
padT = padL = padB = padR = 0;
218
}
219
else if (padMode == "SAME")
220
{
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;
227
}
228
}
229
230
}
231
}
232
233