1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
11 // For Open Source Computer Vision Library
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.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
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.
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.
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.
43 #include "../precomp.hpp"
44 #include "layers_common.hpp"
54 class PriorBoxLayerImpl : public PriorBoxLayer
57 static bool getParameterDict(const LayerParams ¶ms,
58 const std::string ¶meterName,
61 if (!params.has(parameterName))
66 result = params.get(parameterName);
71 T getParameter(const LayerParams ¶ms,
72 const std::string ¶meterName,
74 const bool required=true,
75 const T& defaultValue=T())
78 bool success = getParameterDict(params, parameterName, dictValue);
83 std::string message = _layerName;
84 message += " layer parameter does not contain ";
85 message += parameterName;
86 message += " parameter.";
87 CV_Error(Error::StsBadArg, message);
94 return dictValue.get<T>(idx);
97 void getAspectRatios(const LayerParams ¶ms)
99 DictValue aspectRatioParameter;
100 bool aspectRatioRetieved = getParameterDict(params, "aspect_ratio", aspectRatioParameter);
101 if (!aspectRatioRetieved)
104 for (int i = 0; i < aspectRatioParameter.size(); ++i)
106 float aspectRatio = aspectRatioParameter.get<float>(i);
107 bool alreadyExists = false;
109 for (size_t j = 0; j < _aspectRatios.size(); ++j)
111 if (fabs(aspectRatio - _aspectRatios[j]) < 1e-6)
113 alreadyExists = true;
119 _aspectRatios.push_back(aspectRatio);
122 _aspectRatios.push_back(1./aspectRatio);
128 static void getParams(const std::string& name, const LayerParams ¶ms,
129 std::vector<float>* values)
132 if (getParameterDict(params, name, dict))
134 values->resize(dict.size());
135 for (int i = 0; i < dict.size(); ++i)
137 (*values)[i] = dict.get<float>(i);
144 void getVariance(const LayerParams ¶ms)
146 DictValue varianceParameter;
147 bool varianceParameterRetrieved = getParameterDict(params, "variance", varianceParameter);
148 CV_Assert(varianceParameterRetrieved);
150 int varianceSize = varianceParameter.size();
151 if (varianceSize > 1)
153 // Must and only provide 4 variance.
154 CV_Assert(varianceSize == 4);
156 for (int i = 0; i < varianceSize; ++i)
158 float variance = varianceParameter.get<float>(i);
159 CV_Assert(variance > 0);
160 _variance.push_back(variance);
165 if (varianceSize == 1)
167 float variance = varianceParameter.get<float>(0);
168 CV_Assert(variance > 0);
169 _variance.push_back(variance);
173 // Set default to 0.1.
174 _variance.push_back(0.1f);
179 PriorBoxLayerImpl(const LayerParams ¶ms)
180 : _boxWidth(0), _boxHeight(0)
182 setParamsFrom(params);
183 _minSize = getParameter<float>(params, "min_size", 0, false, 0);
184 _flip = getParameter<bool>(params, "flip", 0, false, true);
185 _clip = getParameter<bool>(params, "clip", 0, false, true);
188 _aspectRatios.clear();
190 getAspectRatios(params);
192 getParams("scales", params, &_scales);
193 getParams("width", params, &_widths);
194 getParams("height", params, &_heights);
195 _explicitSizes = !_widths.empty();
196 CV_Assert(_widths.size() == _heights.size());
200 CV_Assert(_aspectRatios.empty(), !params.has("min_size"), !params.has("max_size"));
201 _numPriors = _widths.size();
205 CV_Assert(!_aspectRatios.empty(), _minSize > 0);
206 _numPriors = _aspectRatios.size() + 1; // + 1 for an aspect ratio 1.0
210 if (params.has("max_size"))
212 _maxSize = params.get("max_size").get<float>(0);
213 CV_Assert(_maxSize > _minSize);
218 if (params.has("step_h") || params.has("step_w")) {
219 CV_Assert(!params.has("step"));
220 _stepY = getParameter<float>(params, "step_h");
221 CV_Assert(_stepY > 0.);
222 _stepX = getParameter<float>(params, "step_w");
223 CV_Assert(_stepX > 0.);
224 } else if (params.has("step")) {
225 const float step = getParameter<float>(params, "step");
233 if (params.has("offset_h") || params.has("offset_w"))
235 CV_Assert(!params.has("offset"), params.has("offset_h"), params.has("offset_w"));
236 getParams("offset_h", params, &_offsetsY);
237 getParams("offset_w", params, &_offsetsX);
238 CV_Assert(_offsetsX.size() == _offsetsY.size());
239 _numPriors *= std::max((size_t)1, 2 * (_offsetsX.size() - 1));
243 float offset = getParameter<float>(params, "offset", 0, false, 0.5);
244 _offsetsX.assign(1, offset);
245 _offsetsY.assign(1, offset);
249 bool getMemoryShapes(const std::vector<MatShape> &inputs,
250 const int requiredOutputs,
251 std::vector<MatShape> &outputs,
252 std::vector<MatShape> &internals) const
254 CV_Assert(inputs.size() == 2);
256 int layerHeight = inputs[0][2];
257 int layerWidth = inputs[0][3];
259 // Since all images in a batch has same height and width, we only need to
260 // generate one set of priors which can be shared across all images.
262 // 2 channels. First channel stores the mean of each prior coordinate.
263 // Second channel stores the variance of each prior coordinate.
264 size_t outChannels = 2;
266 outputs.resize(1, shape(outNum, outChannels,
267 layerHeight * layerWidth * _numPriors * 4));
272 void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr)
275 CV_TRACE_ARG_VALUE(name, "name", name.c_str());
277 Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
280 void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
283 CV_TRACE_ARG_VALUE(name, "name", name.c_str());
285 size_t real_numPriors = _numPriors / pow(2, _offsetsX.size() - 1);
287 _scales.resize(real_numPriors, 1.0f);
289 CV_Assert(_scales.size() == real_numPriors);
291 int _layerWidth = inputs[0]->size[3];
292 int _layerHeight = inputs[0]->size[2];
294 int _imageWidth = inputs[1]->size[3];
295 int _imageHeight = inputs[1]->size[2];
298 if (_stepX == 0 || _stepY == 0) {
299 stepX = static_cast<float>(_imageWidth) / _layerWidth;
300 stepY = static_cast<float>(_imageHeight) / _layerHeight;
306 int _outChannelSize = _layerHeight * _layerWidth * _numPriors * 4;
308 float* outputPtr = outputs[0].ptr<float>();
309 for (size_t h = 0; h < _layerHeight; ++h)
311 for (size_t w = 0; w < _layerWidth; ++w)
313 // first prior: aspect_ratio = 1, size = min_size
316 _boxWidth = _widths[0] * _scales[0];
317 _boxHeight = _heights[0] * _scales[0];
320 _boxWidth = _boxHeight = _minSize * _scales[0];
322 for (int i = 0; i < _offsetsX.size(); ++i)
324 float center_x = (w + _offsetsX[i]) * stepX;
325 float center_y = (h + _offsetsY[i]) * stepY;
326 outputPtr = addPrior(center_x, center_y, _boxWidth, _boxHeight, _imageWidth, _imageHeight, outputPtr);
330 // second prior: aspect_ratio = 1, size = sqrt(min_size * max_size)
331 _boxWidth = _boxHeight = sqrt(_minSize * _maxSize) * _scales[1];
332 for (int i = 0; i < _offsetsX.size(); ++i)
334 float center_x = (w + _offsetsX[i]) * stepX;
335 float center_y = (h + _offsetsY[i]) * stepY;
336 outputPtr = addPrior(center_x, center_y, _boxWidth, _boxHeight, _imageWidth, _imageHeight, outputPtr);
341 CV_Assert(_aspectRatios.empty() || (_maxSize > 0 ? 2 : 1) + _aspectRatios.size() == _scales.size());
342 for (size_t r = 0; r < _aspectRatios.size(); ++r)
344 float ar = _aspectRatios[r];
345 float scale = _scales[(_maxSize > 0 ? 2 : 1) + r];
346 _boxWidth = _minSize * sqrt(ar) * scale;
347 _boxHeight = _minSize / sqrt(ar) * scale;
348 for (int i = 0; i < _offsetsX.size(); ++i)
350 float center_x = (w + _offsetsX[i]) * stepX;
351 float center_y = (h + _offsetsY[i]) * stepY;
352 outputPtr = addPrior(center_x, center_y, _boxWidth, _boxHeight, _imageWidth, _imageHeight, outputPtr);
357 CV_Assert(_widths.empty() || _widths.size() == _scales.size());
358 for (size_t i = 1; i < _widths.size(); ++i)
360 _boxWidth = _widths[i] * _scales[i];
361 _boxHeight = _heights[i] * _scales[i];
362 for (int j = 0; j < _offsetsX.size(); ++j)
364 float center_x = (w + _offsetsX[j]) * stepX;
365 float center_y = (h + _offsetsY[j]) * stepY;
366 outputPtr = addPrior(center_x, center_y, _boxWidth, _boxHeight, _imageWidth, _imageHeight, outputPtr);
371 // clip the prior's coordidate such that it is within [0, 1]
374 for (size_t d = 0; d < _outChannelSize; ++d)
376 outputPtr[d] = std::min<float>(std::max<float>(outputPtr[d], 0.), 1.);
380 outputPtr = outputs[0].ptr<float>(0, 1);
381 if(_variance.size() == 1)
383 Mat secondChannel(outputs[0].size[2], outputs[0].size[3], CV_32F, outputPtr);
384 secondChannel.setTo(Scalar(_variance[0]));
389 for (size_t h = 0; h < _layerHeight; ++h)
391 for (size_t w = 0; w < _layerWidth; ++w)
393 for (size_t i = 0; i < _numPriors; ++i)
395 for (int j = 0; j < 4; ++j)
397 outputPtr[count] = _variance[j];
406 virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
407 const std::vector<MatShape> &outputs) const
409 (void)outputs; // suppress unused variable warning
412 for (int i = 0; i < inputs.size(); i++)
414 flops += total(inputs[i], 2) * _numPriors * 4;
427 float _stepX, _stepY;
429 std::vector<float> _aspectRatios;
430 std::vector<float> _variance;
431 std::vector<float> _scales;
432 std::vector<float> _widths;
433 std::vector<float> _heights;
434 std::vector<float> _offsetsX;
435 std::vector<float> _offsetsY;
443 static const size_t _numAxes = 4;
444 static const std::string _layerName;
446 static float* addPrior(float center_x, float center_y, float width, float height,
447 float imgWidth, float imgHeight, float* dst)
449 dst[0] = (center_x - width * 0.5f) / imgWidth; // xmin
450 dst[1] = (center_y - height * 0.5f) / imgHeight; // ymin
451 dst[2] = (center_x + width * 0.5f) / imgWidth; // xmax
452 dst[3] = (center_y + height * 0.5f) / imgHeight; // ymax
457 const std::string PriorBoxLayerImpl::_layerName = std::string("PriorBox");
459 Ptr<PriorBoxLayer> PriorBoxLayer::create(const LayerParams ¶ms)
461 return Ptr<PriorBoxLayer>(new PriorBoxLayerImpl(params));