Path: blob/master/modules/dnn/src/layers/max_unpooling_layer.cpp
16337 views
// This file is part of OpenCV project.1// It is subject to the license terms in the LICENSE file found in the top-level directory2// of this distribution and at http://opencv.org/license.html.34// Copyright (C) 2016, Intel Corporation, all rights reserved.5// Third party copyrights are property of their respective owners.67/*8Implementation of Batch Normalization layer.9*/1011#include "../precomp.hpp"12#include "layers_common.hpp"13#include "../op_halide.hpp"14#include <opencv2/dnn/shape_utils.hpp>1516#include <iostream>1718namespace cv19{20namespace dnn21{2223class MaxUnpoolLayerImpl CV_FINAL : public MaxUnpoolLayer24{25public:26MaxUnpoolLayerImpl(const LayerParams& params)27{28setParamsFrom(params);29poolKernel = Size(params.get<int>("pool_k_w"), params.get<int>("pool_k_h"));30poolPad = Size(params.get<int>("pool_pad_w"), params.get<int>("pool_pad_h"));31poolStride = Size(params.get<int>("pool_stride_w"), params.get<int>("pool_stride_h"));32}3334virtual bool supportBackend(int backendId) CV_OVERRIDE35{36return backendId == DNN_BACKEND_OPENCV ||37backendId == DNN_BACKEND_HALIDE && haveHalide() &&38!poolPad.width && !poolPad.height;39}4041bool getMemoryShapes(const std::vector<MatShape> &inputs,42const int requiredOutputs,43std::vector<MatShape> &outputs,44std::vector<MatShape> &internals) const CV_OVERRIDE45{46CV_Assert(inputs.size() == 2);47CV_Assert(total(inputs[0]) == total(inputs[1]));4849MatShape outShape = inputs[0];50outShape[2] = (outShape[2] - 1) * poolStride.height + poolKernel.height - 2 * poolPad.height;51outShape[3] = (outShape[3] - 1) * poolStride.width + poolKernel.width - 2 * poolPad.width;5253outputs.clear();54outputs.push_back(outShape);5556return false;57}5859void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE60{61CV_TRACE_FUNCTION();62CV_TRACE_ARG_VALUE(name, "name", name.c_str());6364if (inputs_arr.depth() == CV_16S)65{66forward_fallback(inputs_arr, outputs_arr, internals_arr);67return;68}6970std::vector<Mat> inputs, outputs;71inputs_arr.getMatVector(inputs);72outputs_arr.getMatVector(outputs);7374CV_Assert(inputs.size() == 2);75Mat& input = inputs[0];76Mat& indices = inputs[1];7778CV_Assert(input.total() == indices.total());79CV_Assert(input.size[0] == 1);80CV_Assert(input.isContinuous());8182for(int i_n = 0; i_n < outputs.size(); i_n++)83{84Mat& outBlob = outputs[i_n];85outBlob.setTo(0);86CV_Assert(input.size[1] == outBlob.size[1]);87int outPlaneTotal = outBlob.size[2]*outBlob.size[3];8889for (int i_c = 0; i_c < input.size[1]; i_c++)90{91Mat outPlane = getPlane(outBlob, 0, i_c);92int wh_area = input.size[2]*input.size[3];93const float* inptr = input.ptr<float>(0, i_c);94const float* idxptr = indices.ptr<float>(0, i_c);95float* outptr = outPlane.ptr<float>();9697for(int i_wh = 0; i_wh < wh_area; i_wh++)98{99int index = idxptr[i_wh];100if (!(0 <= index && index < outPlaneTotal))101{102std::cerr103<< "i_n=" << i_n << std::endl104<< "i_c=" << i_c << std::endl105<< "i_wh=" << i_wh << std::endl106<< "index=" << index << std::endl107<< "maxval=" << inptr[i_wh] << std::endl108<< "outPlaneTotal=" << outPlaneTotal << std::endl109<< "input.size=" << input.size << std::endl110<< "indices.size=" << indices.size << std::endl111<< "outBlob=" << outBlob.size << std::endl112;113CV_Assert(0 <= index && index < outPlaneTotal);114}115outptr[index] = inptr[i_wh];116}117}118}119}120121virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &input) CV_OVERRIDE122{123#ifdef HAVE_HALIDE124// Meaningless operation if false because if kernel > stride125// it is not deterministic and if kernel < stride we just126// skip a part of input data (you'd better change your model).127if (poolKernel.width != poolStride.width ||128poolKernel.height != poolStride.height)129CV_Error(cv::Error::StsNotImplemented,130"Halide backend for maximum unpooling "131"is not support cases when kernel != stride");132133Halide::Var x("x"), y("y"), c("c"), n("n");134Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));135Halide::Buffer<float> inputBuffer = halideBuffer(input[0]);136Halide::Buffer<float> indices = halideBuffer(input[1]);137138Halide::Expr pooledX = x / poolKernel.width;139Halide::Expr pooledY = y / poolKernel.height;140141const int outW = inputBuffer.width() * poolKernel.width;142top(x, y, c, n) = select(y * outW + x == indices(pooledX, pooledY, c, n),143inputBuffer(pooledX, pooledY, c, n), 0.0f);144return Ptr<BackendNode>(new HalideBackendNode(top));145#endif // HAVE_HALIDE146return Ptr<BackendNode>();147}148};149150Ptr<MaxUnpoolLayer> MaxUnpoolLayer::create(const LayerParams& params)151{152return Ptr<MaxUnpoolLayer>(new MaxUnpoolLayerImpl(params));153}154155}156}157158159