Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/dnn/src/layers/max_unpooling_layer.cpp
16337 views
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.
4
5
// Copyright (C) 2016, Intel Corporation, all rights reserved.
6
// Third party copyrights are property of their respective owners.
7
8
/*
9
Implementation of Batch Normalization layer.
10
*/
11
12
#include "../precomp.hpp"
13
#include "layers_common.hpp"
14
#include "../op_halide.hpp"
15
#include <opencv2/dnn/shape_utils.hpp>
16
17
#include <iostream>
18
19
namespace cv
20
{
21
namespace dnn
22
{
23
24
class MaxUnpoolLayerImpl CV_FINAL : public MaxUnpoolLayer
25
{
26
public:
27
MaxUnpoolLayerImpl(const LayerParams& params)
28
{
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"));
33
}
34
35
virtual bool supportBackend(int backendId) CV_OVERRIDE
36
{
37
return backendId == DNN_BACKEND_OPENCV ||
38
backendId == DNN_BACKEND_HALIDE && haveHalide() &&
39
!poolPad.width && !poolPad.height;
40
}
41
42
bool getMemoryShapes(const std::vector<MatShape> &inputs,
43
const int requiredOutputs,
44
std::vector<MatShape> &outputs,
45
std::vector<MatShape> &internals) const CV_OVERRIDE
46
{
47
CV_Assert(inputs.size() == 2);
48
CV_Assert(total(inputs[0]) == total(inputs[1]));
49
50
MatShape outShape = inputs[0];
51
outShape[2] = (outShape[2] - 1) * poolStride.height + poolKernel.height - 2 * poolPad.height;
52
outShape[3] = (outShape[3] - 1) * poolStride.width + poolKernel.width - 2 * poolPad.width;
53
54
outputs.clear();
55
outputs.push_back(outShape);
56
57
return false;
58
}
59
60
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
61
{
62
CV_TRACE_FUNCTION();
63
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
64
65
if (inputs_arr.depth() == CV_16S)
66
{
67
forward_fallback(inputs_arr, outputs_arr, internals_arr);
68
return;
69
}
70
71
std::vector<Mat> inputs, outputs;
72
inputs_arr.getMatVector(inputs);
73
outputs_arr.getMatVector(outputs);
74
75
CV_Assert(inputs.size() == 2);
76
Mat& input = inputs[0];
77
Mat& indices = inputs[1];
78
79
CV_Assert(input.total() == indices.total());
80
CV_Assert(input.size[0] == 1);
81
CV_Assert(input.isContinuous());
82
83
for(int i_n = 0; i_n < outputs.size(); i_n++)
84
{
85
Mat& outBlob = outputs[i_n];
86
outBlob.setTo(0);
87
CV_Assert(input.size[1] == outBlob.size[1]);
88
int outPlaneTotal = outBlob.size[2]*outBlob.size[3];
89
90
for (int i_c = 0; i_c < input.size[1]; i_c++)
91
{
92
Mat outPlane = getPlane(outBlob, 0, i_c);
93
int wh_area = input.size[2]*input.size[3];
94
const float* inptr = input.ptr<float>(0, i_c);
95
const float* idxptr = indices.ptr<float>(0, i_c);
96
float* outptr = outPlane.ptr<float>();
97
98
for(int i_wh = 0; i_wh < wh_area; i_wh++)
99
{
100
int index = idxptr[i_wh];
101
if (!(0 <= index && index < outPlaneTotal))
102
{
103
std::cerr
104
<< "i_n=" << i_n << std::endl
105
<< "i_c=" << i_c << std::endl
106
<< "i_wh=" << i_wh << std::endl
107
<< "index=" << index << std::endl
108
<< "maxval=" << inptr[i_wh] << std::endl
109
<< "outPlaneTotal=" << outPlaneTotal << std::endl
110
<< "input.size=" << input.size << std::endl
111
<< "indices.size=" << indices.size << std::endl
112
<< "outBlob=" << outBlob.size << std::endl
113
;
114
CV_Assert(0 <= index && index < outPlaneTotal);
115
}
116
outptr[index] = inptr[i_wh];
117
}
118
}
119
}
120
}
121
122
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &input) CV_OVERRIDE
123
{
124
#ifdef HAVE_HALIDE
125
// Meaningless operation if false because if kernel > stride
126
// it is not deterministic and if kernel < stride we just
127
// skip a part of input data (you'd better change your model).
128
if (poolKernel.width != poolStride.width ||
129
poolKernel.height != poolStride.height)
130
CV_Error(cv::Error::StsNotImplemented,
131
"Halide backend for maximum unpooling "
132
"is not support cases when kernel != stride");
133
134
Halide::Var x("x"), y("y"), c("c"), n("n");
135
Halide::Func top = (name.empty() ? Halide::Func() : Halide::Func(name));
136
Halide::Buffer<float> inputBuffer = halideBuffer(input[0]);
137
Halide::Buffer<float> indices = halideBuffer(input[1]);
138
139
Halide::Expr pooledX = x / poolKernel.width;
140
Halide::Expr pooledY = y / poolKernel.height;
141
142
const int outW = inputBuffer.width() * poolKernel.width;
143
top(x, y, c, n) = select(y * outW + x == indices(pooledX, pooledY, c, n),
144
inputBuffer(pooledX, pooledY, c, n), 0.0f);
145
return Ptr<BackendNode>(new HalideBackendNode(top));
146
#endif // HAVE_HALIDE
147
return Ptr<BackendNode>();
148
}
149
};
150
151
Ptr<MaxUnpoolLayer> MaxUnpoolLayer::create(const LayerParams& params)
152
{
153
return Ptr<MaxUnpoolLayer>(new MaxUnpoolLayerImpl(params));
154
}
155
156
}
157
}
158
159