Path: blob/master/modules/dnn/src/layers/layers_common.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2013, OpenCV Foundation, all rights reserved.13// Copyright (C) 2017, Intel Corporation, all rights reserved.14// Third party copyrights are property of their respective owners.15//16// Redistribution and use in source and binary forms, with or without modification,17// are permitted provided that the following conditions are met:18//19// * Redistribution's of source code must retain the above copyright notice,20// this list of conditions and the following disclaimer.21//22// * Redistribution's in binary form must reproduce the above copyright notice,23// this list of conditions and the following disclaimer in the documentation24// and/or other materials provided with the distribution.25//26// * The name of the copyright holders may not be used to endorse or promote products27// derived from this software without specific prior written permission.28//29// This software is provided by the copyright holders and contributors "as is" and30// any express or implied warranties, including, but not limited to, the implied31// warranties of merchantability and fitness for a particular purpose are disclaimed.32// In no event shall the Intel Corporation or contributors be liable for any direct,33// indirect, incidental, special, exemplary, or consequential damages34// (including, but not limited to, procurement of substitute goods or services;35// loss of use, data, or profits; or business interruption) however caused36// and on any theory of liability, whether in contract, strict liability,37// or tort (including negligence or otherwise) arising in any way out of38// the use of this software, even if advised of the possibility of such damage.39//40//M*/4142#include "../precomp.hpp"43#include "layers_common.hpp"4445namespace cv46{47namespace dnn48{4950namespace util51{5253std::string makeName(const std::string& str1, const std::string& str2)54{55return str1 + str2;56}5758bool getParameter(const LayerParams ¶ms, const std::string& nameBase, const std::string& nameAll,59int ¶meterH, int ¶meterW, bool hasDefault = false, const int& defaultValue = 0)60{61std::string nameH = makeName(nameBase, std::string("_h"));62std::string nameW = makeName(nameBase, std::string("_w"));63std::string nameAll_ = nameAll;64if(nameAll_ == "")65{66nameAll_ = nameBase;67}6869if (params.has(nameH) && params.has(nameW))70{71parameterH = params.get<int>(nameH);72parameterW = params.get<int>(nameW);73return true;74}75else76{77if (params.has(nameAll_))78{79DictValue param = params.get(nameAll_);80parameterH = param.get<int>(0);81if (param.size() == 1)82{83parameterW = parameterH;84}85else if (param.size() == 2)86{87parameterW = param.get<int>(1);88}89else90{91return false;92}93return true;94}95else96{97if(hasDefault)98{99parameterH = parameterW = defaultValue;100return true;101}102else103{104return false;105}106}107}108}109110void getKernelSize(const LayerParams ¶ms, int &kernelH, int &kernelW)111{112if(!util::getParameter(params, "kernel", "kernel_size", kernelH, kernelW))113{114CV_Error(cv::Error::StsBadArg, "kernel_size (or kernel_h and kernel_w) not specified");115}116117CV_Assert(kernelH > 0 && kernelW > 0);118}119120void getStrideAndPadding(const LayerParams ¶ms, int &padT, int &padL, int &padB, int &padR, int &strideH, int &strideW, cv::String& padMode)121{122if (params.has("pad_l") && params.has("pad_t") && params.has("pad_r") && params.has("pad_b")) {123padT = params.get<int>("pad_t");124padL = params.get<int>("pad_l");125padB = params.get<int>("pad_b");126padR = params.get<int>("pad_r");127}128else {129util::getParameter(params, "pad", "pad", padT, padL, true, 0);130padB = padT;131padR = padL;132}133util::getParameter(params, "stride", "stride", strideH, strideW, true, 1);134135padMode = "";136if (params.has("pad_mode"))137{138padMode = params.get<String>("pad_mode");139}140141CV_Assert(padT >= 0 && padL >= 0 && padB >= 0 && padR >= 0 && strideH > 0 && strideW > 0);142}143}144145146void getPoolingKernelParams(const LayerParams ¶ms, int &kernelH, int &kernelW, bool &globalPooling,147int &padT, int &padL, int &padB, int &padR, int &strideH, int &strideW, cv::String &padMode)148{149util::getStrideAndPadding(params, padT, padL, padB, padR, strideH, strideW, padMode);150151globalPooling = params.has("global_pooling") &&152params.get<bool>("global_pooling");153154if (globalPooling)155{156if(params.has("kernel_h") || params.has("kernel_w") || params.has("kernel_size"))157{158CV_Error(cv::Error::StsBadArg, "In global_pooling mode, kernel_size (or kernel_h and kernel_w) cannot be specified");159}160if(padT != 0 || padL != 0 || padB != 0 || padR != 0 || strideH != 1 || strideW != 1)161{162CV_Error(cv::Error::StsBadArg, "In global_pooling mode, pads must be = 0, and stride_h and stride_w must be = 1");163}164}165else166{167util::getKernelSize(params, kernelH, kernelW);168}169}170171void getConvolutionKernelParams(const LayerParams ¶ms, int &kernelH, int &kernelW, int &padT, int &padL, int &padB, int &padR,172int &strideH, int &strideW, int &dilationH, int &dilationW, cv::String &padMode)173{174util::getKernelSize(params, kernelH, kernelW);175util::getStrideAndPadding(params, padT, padL, padB, padR, strideH, strideW, padMode);176util::getParameter(params, "dilation", "dilation", dilationH, dilationW, true, 1);177178CV_Assert(dilationH > 0 && dilationW > 0);179}180181// From TensorFlow code:182// Total padding on rows and cols is183// Pr = (R' - 1) * S + Kr - R184// Pc = (C' - 1) * S + Kc - C185// where (R', C') are output dimensions, (R, C) are input dimensions, S186// is stride, (Kr, Kc) are filter dimensions.187// We pad Pr/2 on the left and Pr - Pr/2 on the right, Pc/2 on the top188// and Pc - Pc/2 on the bottom. When Pr or Pc is odd, this means189// we pad more on the right and bottom than on the top and left.190void getConvPoolOutParams(const Size& inp, const Size &kernel,191const Size &stride, const String &padMode,192const Size &dilation, Size& out)193{194if (padMode == "VALID")195{196out.height = (inp.height - (dilation.height * (kernel.height - 1) + 1) + stride.height) / stride.height;197out.width = (inp.width - (dilation.width * (kernel.width - 1) + 1) + stride.width) / stride.width;198}199else if (padMode == "SAME")200{201out.height = (inp.height - 1 + stride.height) / stride.height;202out.width = (inp.width - 1 + stride.width) / stride.width;203}204else205{206CV_Error(Error::StsError, "Unsupported padding mode");207}208}209210void getConvPoolPaddings(const Size& inp, const Size& out,211const Size &kernel, const Size &stride,212const String &padMode, const Size &dilation, int &padT, int &padL, int &padB, int &padR)213{214if (padMode == "VALID")215{216padT = padL = padB = padR = 0;217}218else if (padMode == "SAME")219{220int Ph = std::max(0, (out.height - 1) * stride.height + (dilation.height * (kernel.height - 1) + 1) - inp.height);221int Pw = std::max(0, (out.width - 1) * stride.width + (dilation.width * (kernel.width - 1) + 1) - inp.width);222// For odd values of total padding, add more padding at the 'right'223// side of the given dimension.224padT= padB = Ph / 2;225padL = padR = Pw / 2;226}227}228229}230}231232233