1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
5 // Copyright (C) 2016, Intel Corporation, all rights reserved.
6 // Third party copyrights are property of their respective owners.
9 Implementation of Batch Normalization layer.
12 #include "../precomp.hpp"
13 #include "layers_common.hpp"
14 #include "../op_halide.hpp"
15 #include <opencv2/dnn/shape_utils.hpp>
24 class MaxUnpoolLayerImpl CV_FINAL : public MaxUnpoolLayer
27 MaxUnpoolLayerImpl(const LayerParams& params)
29 setParamsFrom(params);
30 poolKernel = Size(params.get<int>("pool_k_w"), params.get<int>("pool_k_h"));
31 poolPad = Size(params.get<int>("pool_pad_w"), params.get<int>("pool_pad_h"));
32 poolStride = Size(params.get<int>("pool_stride_w"), params.get<int>("pool_stride_h"));
35 virtual bool supportBackend(int backendId) CV_OVERRIDE
37 return backendId == DNN_BACKEND_OPENCV ||
38 (backendId == DNN_BACKEND_HALIDE && haveHalide() && !poolPad.width && !poolPad.height);
41 bool getMemoryShapes(const std::vector<MatShape> &inputs,
42 const int requiredOutputs,
43 std::vector<MatShape> &outputs,
44 std::vector<MatShape> &internals) const CV_OVERRIDE
46 CV_Assert(inputs.size() == 2 || inputs.size() == 3);
47 CV_Assert(total(inputs[0]) == total(inputs[1]));
50 if (inputs.size() == 2)
53 outShape[2] = (outShape[2] - 1) * poolStride.height + poolKernel.height - 2 * poolPad.height;
54 outShape[3] = (outShape[3] - 1) * poolStride.width + poolKernel.width - 2 * poolPad.width;
60 outputs.push_back(outShape);
65 void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
68 CV_TRACE_ARG_VALUE(name, "name", name.c_str());
70 if (inputs_arr.depth() == CV_16S)
72 forward_fallback(inputs_arr, outputs_arr, internals_arr);
76 std::vector<Mat> inputs, outputs;
77 inputs_arr.getMatVector(inputs);
78 outputs_arr.getMatVector(outputs);
80 CV_Assert(inputs.size() == 2 || inputs.size() == 3);
81 Mat& input = inputs[0];
82 Mat& indices = inputs[1];
84 CV_Assert(input.total() == indices.total());
85 CV_Assert(input.size[0] == 1);
86 CV_Assert(input.isContinuous());
88 for(int i_n = 0; i_n < outputs.size(); i_n++)
90 Mat& outBlob = outputs[i_n];
92 CV_Assert(input.size[1] == outBlob.size[1]);
93 int outPlaneTotal = outBlob.size[2]*outBlob.size[3];
95 for (int i_c = 0; i_c < input.size[1]; i_c++)
97 Mat outPlane = getPlane(outBlob, 0, i_c);
98 int wh_area = input.size[2]*input.size[3];
99 const float* inptr = input.ptr<float>(0, i_c);
100 const float* idxptr = indices.ptr<float>(0, i_c);
101 float* outptr = outPlane.ptr<float>();
103 for(int i_wh = 0; i_wh < wh_area; i_wh++)
105 int index = idxptr[i_wh];
106 if (!(0 <= index && index < outPlaneTotal))
109 << "i_n=" << i_n << std::endl
110 << "i_c=" << i_c << std::endl
111 << "i_wh=" << i_wh << std::endl
112 << "index=" << index << std::endl
113 << "maxval=" << inptr[i_wh] << std::endl
114 << "outPlaneTotal=" << outPlaneTotal << std::endl
115 << "input.size=" << input.size << std::endl
116 << "indices.size=" << indices.size << std::endl
117 << "outBlob=" << outBlob.size << std::endl
119 CV_Assert(0 <= index && index < outPlaneTotal);
121 outptr[index] = inptr[i_wh];
127 virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &input) CV_OVERRIDE
130 // Meaningless operation if false because if kernel > stride
131 // it is not deterministic and if kernel < stride we just
132 // skip a part of input data (you'd better change your model).
133 if (poolKernel.width != poolStride.width ||
134 poolKernel.height != poolStride.height)
135 CV_Error(cv::Error::StsNotImplemented,
136 "Halide backend for maximum unpooling "
137 "is not support cases when kernel != stride");
139 Halide::Var x("x"), y("y"), c("c"), n("n");
140 Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
141 Halide::Buffer<float> inputBuffer = halideBuffer(input[0]);
142 Halide::Buffer<float> indices = halideBuffer(input[1]);
144 Halide::Expr pooledX = x / poolKernel.width;
145 Halide::Expr pooledY = y / poolKernel.height;
147 const int outW = inputBuffer.width() * poolKernel.width;
148 top(x, y, c, n) = select(y * outW + x == indices(pooledX, pooledY, c, n),
149 inputBuffer(pooledX, pooledY, c, n), 0.0f);
150 return Ptr<BackendNode>(new HalideBackendNode(top));
151 #endif // HAVE_HALIDE
152 return Ptr<BackendNode>();
156 Ptr<MaxUnpoolLayer> MaxUnpoolLayer::create(const LayerParams& params)
158 return Ptr<MaxUnpoolLayer>(new MaxUnpoolLayerImpl(params));