normalize_bbox_layer.cpp 6.53 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "../precomp.hpp"
#include "layers_common.hpp"
#include "normalize_bbox_layer.hpp"
#include "op_blas.hpp"

#include <float.h>
#include <algorithm>

namespace cv
{
namespace dnn
{

Anna Petrovicheva's avatar
Anna Petrovicheva committed
55 56
const std::string NormalizeBBoxLayer::_layerName = std::string("NormalizeBBox");

57 58 59
bool NormalizeBBoxLayer::getParameterDict(const LayerParams &params,
                                          const std::string &parameterName,
                                          DictValue& result)
60 61 62
{
    if (!params.has(parameterName))
    {
63
        return false;
Anna Petrovicheva's avatar
Anna Petrovicheva committed
64 65
    }

66 67
    result = params.get(parameterName);
    return true;
68 69
}

Anna Petrovicheva's avatar
Anna Petrovicheva committed
70 71 72
template<typename T>
T NormalizeBBoxLayer::getParameter(const LayerParams &params,
                                   const std::string &parameterName,
73 74 75
                                   const size_t &idx,
                                   const bool required,
                                   const T& defaultValue)
76
{
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
    DictValue dictValue;
    bool success = getParameterDict(params, parameterName, dictValue);
    if(!success)
    {
        if(required)
        {
            std::string message = _layerName;
            message += " layer parameter does not contain ";
            message += parameterName;
            message += " parameter.";
            CV_Error(Error::StsBadArg, message);
        }
        else
        {
            return defaultValue;
        }
    }
    return dictValue.get<T>(idx);
Anna Petrovicheva's avatar
Anna Petrovicheva committed
95 96 97 98
}

NormalizeBBoxLayer::NormalizeBBoxLayer(LayerParams &params) : Layer(params)
{
apetrovichev's avatar
apetrovichev committed
99
    _eps = getParameter<float>(params, "eps", 0, false, 1e-10f);
Anna Petrovicheva's avatar
Anna Petrovicheva committed
100 101
    _across_spatial = getParameter<bool>(params, "across_spatial");
    _channel_shared = getParameter<bool>(params, "channel_shared");
102 103 104 105 106
}

void NormalizeBBoxLayer::checkInputs(const std::vector<Blob*> &inputs)
{
    CV_Assert(inputs.size() > 0);
107
    for (size_t i = 1; i < inputs.size(); i++)
108
    {
Anna Petrovicheva's avatar
Anna Petrovicheva committed
109
        for (size_t j = 0; j < _numAxes; j++)
110
        {
Anna Petrovicheva's avatar
Anna Petrovicheva committed
111
            CV_Assert(inputs[i]->shape()[j] == inputs[0]->shape()[j]);
112 113 114 115 116 117 118 119 120 121
        }
    }
    CV_Assert(inputs[0]->dims() > 2);
}

void NormalizeBBoxLayer::allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs)
{
    checkInputs(inputs);

    _num = inputs[0]->num();
Anna Petrovicheva's avatar
Anna Petrovicheva committed
122 123 124
    _channels = inputs[0]->shape()[1];
    _rows = inputs[0]->shape()[2];
    _cols = inputs[0]->shape()[3];
125 126 127 128

    _channelSize = _rows * _cols;
    _imageSize = _channelSize * _channels;

129
    _buffer = Mat(_channels, _channelSize, CV_32F);
130

131 132
    _sumChannelMultiplier = Mat(_channels, 1, CV_32F, Scalar(1.0));
    _sumSpatialMultiplier = Mat(1, _channelSize, CV_32F, Scalar(1.0));
133

134
    _scale = blobs[0];
135 136 137 138 139 140 141 142 143

    for(size_t i = 0; i < inputs.size(); i++)
    {
        outputs[i].create(BlobShape(inputs[0]->shape()));
    }
}

void NormalizeBBoxLayer::forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs)
{
144 145
    Mat zeroBuffer(_channels, _channelSize, CV_32F, Scalar(0));
    Mat absDiff;
146 147 148

    for (size_t j = 0; j < inputs.size(); j++)
    {
Anna Petrovicheva's avatar
Anna Petrovicheva committed
149
        for (size_t n = 0; n < _num; ++n)
150
        {
151 152
            Mat src = Mat(_channels, _channelSize, CV_32F, inputs[j]->ptrf(n));
            Mat dst = Mat(_channels, _channelSize, CV_32F, outputs[j].ptrf(n));
153

154
            _buffer = src.mul(src);
155 156 157

            if (_across_spatial)
            {
158
                absdiff(_buffer, zeroBuffer, absDiff);
159

160 161
                // add eps to avoid overflow
                double absSum = sum(absDiff)[0] + _eps;
162

163 164
                float norm = sqrt(absSum);
                dst = src / norm;
165 166 167
            }
            else
            {
168
                Mat norm(_channelSize, 1, _buffer.type()); // 1 x _channelSize
169 170 171

                // (_channels x_channelSize)T * _channels x 1 -> _channelSize x 1
                gemmCPU(_buffer, _sumChannelMultiplier, 1, norm, 0, GEMM_1_T);
172 173

                // compute norm
174
                pow(norm, 0.5f, norm);
175 176

                // scale the layer
177 178
                // _channels x 1 * (_channelSize x 1)T -> _channels x _channelSize
                gemmCPU(_sumChannelMultiplier, norm, 1, _buffer, 0, GEMM_2_T);
179

180
                dst = src / _buffer;
181 182 183 184 185
            }

            // scale the output
            if (_channel_shared)
            {
186
                // _scale: 1 x 1
187
                dst *= _scale.matRefConst().at<float>(0, 0);
188 189 190
            }
            else
            {
191 192
                // _scale: _channels x 1
                // _channels x 1 * 1 x _channelSize -> _channels x _channelSize
193
                gemmCPU(_scale.matRefConst(), _sumSpatialMultiplier, 1, _buffer, 0);
194 195 196

                dst = dst.mul(_buffer);
           }
197 198 199 200 201
        }
    }
}
}
}