Path: blob/master/modules/dnn/src/layers/reshape_layer.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"44#include "../op_inf_engine.hpp"45#include <opencv2/dnn/shape_utils.hpp>4647namespace cv48{49namespace dnn50{5152static void computeShapeByReshapeMask(const MatShape &srcShape,53const MatShape &maskShape,54Range srcRange /*= Range::all()*/,55MatShape& dstShape)56{57int srcShapeSize = (int)srcShape.size();58int maskShapeSize = (int)maskShape.size();5960if (srcRange == Range::all())61srcRange = Range(0, srcShapeSize);62else63{64int sz = srcRange.size();65srcRange.start = clamp(srcRange.start, srcShapeSize);66srcRange.end = srcRange.end == INT_MAX ? srcShapeSize : srcRange.start + sz;67}6869bool explicitMask = !maskShape.empty(); // All mask values are positive.70for (int i = 0, n = maskShape.size(); i < n && explicitMask; ++i)71{72explicitMask = maskShape[i] > 0;73}74// Working range of source shape is a range where area(src) == area(mask).75if (explicitMask)76{77int maskTotal = total(maskShape);78// Go from the end of mask until we collect required total.79bool matched = false;80for (int i = srcRange.end - 1; i >= srcRange.start; --i)81{82if (matched)83{84if (total(srcShape, i, srcRange.end) != maskTotal)85{86srcRange.start = i + 1;87break;88}89else if (i == 0)90{91srcRange.start = 0;92break;93}94}95else96{97matched = total(srcShape, i, srcRange.end) == maskTotal;98}99}100while (total(srcShape, srcRange.start, srcRange.end) != maskTotal && srcRange.start > 0)101{102srcRange.start -= 1;103}104CV_Assert(total(srcShape, srcRange.start, srcRange.end) == maskTotal);105}106107CV_Assert(0 <= srcRange.start && srcRange.start <= srcRange.end && srcRange.end <= srcShapeSize);108int dstShapeSize = srcShapeSize - srcRange.size() + maskShapeSize;109dstShape.resize(dstShapeSize);110111std::copy(srcShape.begin(), srcShape.begin() + srcRange.start, dstShape.begin());112std::copy(srcShape.begin() + srcRange.end, srcShape.begin() + srcShapeSize, dstShape.begin() + srcRange.start + maskShapeSize);113114int inferDim = -1;115for (int i = 0; i < maskShapeSize; i++)116{117if (maskShape[i] > 0)118{119dstShape[srcRange.start + i] = maskShape[i];120}121else if (maskShape[i] == 0)122{123if (srcRange.start + i >= srcShapeSize)124CV_Error(Error::StsBadArg, format("Copy dim[%d] (which has zero size) is out of the source shape bounds", srcRange.start + i));125dstShape[srcRange.start + i] = srcShape[srcRange.start + i];126}127else if (maskShape[i] == -1)128{129if (inferDim != -1)130CV_Error(Error::StsAssert, "Duplicate of inferred dim (which is denoted by -1)");131inferDim = srcRange.start + i;132dstShape[inferDim] = 1;133}134else135CV_Error(Error::StsBadArg, "maskShape[i] >= -1");136}137138size_t srcTotal = total(srcShape);139size_t dstTotal = total(dstShape);140141if (inferDim != -1)142{143if (srcTotal % dstTotal != 0)144CV_Error(Error::StsBackTrace, "Can't infer a dim denoted by -1");145146dstShape[inferDim] = (int)(srcTotal / dstTotal);147}148else149{150CV_Assert(srcTotal == dstTotal);151}152}153154155class ReshapeLayerImpl CV_FINAL : public ReshapeLayer156{157public:158ReshapeLayerImpl(const LayerParams& params)159{160setParamsFrom(params);161int axis = params.get<int>("axis", 0);162int numAxes = params.get<int>("num_axes", -1);163CV_Assert(numAxes >= -1);164newShapeRange = (numAxes == -1) ? Range(axis, INT_MAX) : Range(axis, axis + numAxes);165166newShapeDesc.clear();167if (params.has("dim"))168{169const DictValue ¶mShape = params.get("dim");170int i, dims = paramShape.size();171newShapeDesc.resize(dims);172for (i = 0; i < dims; i++)173newShapeDesc[i] = paramShape.get<int>(i);174}175}176177virtual bool supportBackend(int backendId) CV_OVERRIDE178{179return backendId == DNN_BACKEND_OPENCV ||180backendId == DNN_BACKEND_INFERENCE_ENGINE && haveInfEngine();181}182183bool getMemoryShapes(const std::vector<MatShape> &inputs,184const int requiredOutputs,185std::vector<MatShape> &outputs,186std::vector<MatShape> &internals) const CV_OVERRIDE187{188if (inputs.size() == 1 || inputs.size() == requiredOutputs)189{190outputs.clear();191for (size_t i = 0; i < inputs.size(); i++)192{193outputs.push_back(MatShape());194computeShapeByReshapeMask(inputs[i], newShapeDesc, newShapeRange, outputs.back());195}196}197else198{199CV_Assert_N(inputs.size() == 2, total(inputs[0]) == total(inputs[1]));200outputs.assign(1, inputs[1]);201}202return true;203}204205bool forward_ocl(InputArrayOfArrays inps, OutputArrayOfArrays outs, OutputArrayOfArrays internals)206{207std::vector<UMat> inputs;208std::vector<UMat> outputs;209210inps.getUMatVector(inputs);211outs.getUMatVector(outputs);212213for (size_t i = 0; i < outputs.size(); i++)214{215UMat srcBlob = inputs[i];216void *src_handle = inputs[i].handle(ACCESS_READ);217void *dst_handle = outputs[i].handle(ACCESS_WRITE);218if (src_handle != dst_handle)219{220MatShape outShape = shape(outputs[i]);221UMat umat = srcBlob.reshape(1, (int)outShape.size(), &outShape[0]);222umat.copyTo(outputs[i]);223}224}225outs.assign(outputs);226227return true;228}229230void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE231{232CV_TRACE_FUNCTION();233CV_TRACE_ARG_VALUE(name, "name", name.c_str());234235CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),236forward_ocl(inputs_arr, outputs_arr, internals_arr))237238std::vector<Mat> inputs, outputs;239inputs_arr.getMatVector(inputs);240outputs_arr.getMatVector(outputs);241for (size_t i = 0; i < outputs.size(); i++)242{243Mat srcBlob = inputs[i];244if (outputs[i].data != srcBlob.data)245srcBlob.reshape(1, shape(outputs[i])).copyTo(outputs[i]);246}247}248249virtual Ptr<BackendNode> initInfEngine(const std::vector<Ptr<BackendWrapper> >& inputs) CV_OVERRIDE250{251#ifdef HAVE_INF_ENGINE252InferenceEngine::LayerParams lp;253lp.name = name;254lp.type = "Reshape";255lp.precision = InferenceEngine::Precision::FP32;256std::shared_ptr<InferenceEngine::ReshapeLayer> ieLayer(new InferenceEngine::ReshapeLayer(lp));257if (!newShapeDesc.empty())258ieLayer->shape = newShapeDesc;259else260{261CV_Assert(inputs.size() == 2);262InferenceEngine::DataPtr shapeSrc = infEngineDataNode(inputs[1]);263// NOTE: shapeSrc->dims are reversed264ieLayer->shape = std::vector<int>(shapeSrc->dims.rbegin(), shapeSrc->dims.rend());265}266return Ptr<BackendNode>(new InfEngineBackendNode(ieLayer));267#endif // HAVE_INF_ENGINE268return Ptr<BackendNode>();269}270};271272Ptr<ReshapeLayer> ReshapeLayer::create(const LayerParams& params)273{274return Ptr<ReshapeLayer>(new ReshapeLayerImpl(params));275}276277278}279}280281282