2
2
// It is subject to the license terms in the LICENSE file found in the top-level directory
3
3
// of this distribution and at http://opencv.org/license.html.
4
4
5
- // Copyright (C) 2016 , Intel Corporation, all rights reserved.
5
+ // Copyright (C) 2017 , Intel Corporation, all rights reserved.
6
6
// Third party copyrights are property of their respective owners.
7
7
8
8
/*
@@ -24,104 +24,105 @@ class PaddingLayerImpl : public PaddingLayer
24
24
PaddingLayerImpl (const LayerParams ¶ms)
25
25
{
26
26
setParamsFrom (params);
27
- paddingDim = params.get <int >(" padding_dim" );
28
- padding = params.get <int >(" padding" );
29
- inputDims = params.get <int >(" input_dims" , 0 );
30
- index = params.get <int >(" index" , 0 );
31
- paddingValue = params.get <double >(" value" , 0 );
32
-
33
- if (paddingDim < 0 || padding < 0 )
34
- CV_Error (cv::Error::StsNotImplemented, " Negative padding and dim aren't supported" );
27
+ paddingValue = params.get <float >(" value" , 0 );
28
+ inputDims = params.get <int >(" input_dims" , -1 );
29
+
30
+ CV_Assert (params.has (" paddings" ));
31
+ const DictValue& paddingsParam = params.get (" paddings" );
32
+ CV_Assert ((paddingsParam.size () & 1 ) == 0 );
33
+
34
+ paddings.resize (paddingsParam.size () / 2 );
35
+ for (int i = 0 ; i < paddings.size (); ++i)
36
+ {
37
+ paddings[i].first = paddingsParam.get <int >(i * 2 ); // Pad before.
38
+ paddings[i].second = paddingsParam.get <int >(i * 2 + 1 ); // Pad after.
39
+ CV_Assert (paddings[i].first >= 0 , paddings[i].second >= 0 );
40
+ }
35
41
}
36
42
37
43
bool getMemoryShapes (const std::vector<MatShape> &inputs,
38
44
const int requiredOutputs,
39
45
std::vector<MatShape> &outputs,
40
46
std::vector<MatShape> &internals) const
41
47
{
42
- outputs.clear ();
43
- for (int i = 0 ; i < inputs.size (); i++)
48
+ CV_Assert (inputs.size () == 1 );
49
+ const MatShape& inpShape = inputs[0 ];
50
+ CV_Assert (inpShape.size () >= paddings.size ());
51
+ CV_Assert (inputDims == -1 || inpShape.size () == inputDims || inpShape.size () > paddings.size ());
52
+
53
+ outputs.resize (1 , inpShape);
54
+ int offset = (inputDims == -1 ? 0 : (inpShape.size () > inputDims ? 1 : 0 ));
55
+ for (int i = 0 ; i < paddings.size (); ++i)
44
56
{
45
- MatShape shape = inputs[i];
46
- int dim = getPadDim (shape);
47
- CV_Assert (dim < shape.size ());
57
+ outputs[0 ][offset + i] = inpShape[offset + i] + paddings[i].first + paddings[i].second ;
58
+ }
59
+ return false ;
60
+ }
48
61
49
- shape[dim] += padding;
50
- outputs.push_back (shape);
62
+ void finalize (const std::vector<Mat*> &inputs, std::vector<Mat> &outputs)
63
+ {
64
+ // Compute dstRanges.
65
+ const MatSize& inpShape = inputs[0 ]->size ;
66
+ dstRanges.resize (paddings.size ());
67
+
68
+ int offset = 0 ;
69
+ if (inputDims != -1 && inputs[0 ]->dims != inputDims)
70
+ {
71
+ dstRanges.insert (dstRanges.begin (), Range::all ());
72
+ offset = 1 ;
51
73
}
52
74
53
- return false ;
75
+ for (int i = 0 ; i < paddings.size (); ++i)
76
+ {
77
+ dstRanges[offset + i].start = paddings[i].first ;
78
+ dstRanges[offset + i].end = paddings[i].first + inpShape[offset + i];
79
+ }
80
+
81
+ // Add the rest of dimensions.
82
+ for (int i = dstRanges.size (); i < inputs[0 ]->dims ; ++i)
83
+ dstRanges.push_back (Range::all ());
54
84
}
55
85
56
86
virtual bool supportBackend (int backendId)
57
87
{
58
88
return backendId == DNN_BACKEND_DEFAULT ||
59
- backendId == DNN_BACKEND_HALIDE && haveHalide ();
89
+ backendId == DNN_BACKEND_HALIDE && haveHalide () && dstRanges. size () == 4 ;
60
90
}
61
91
62
92
void forward (std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
63
93
{
64
94
CV_TRACE_FUNCTION ();
65
95
CV_TRACE_ARG_VALUE (name, " name" , name.c_str ());
66
96
67
- for (int i = 0 ; i < inputs.size (); i++)
68
- {
69
- outputs[i] = paddingValue;
70
- const Mat& inp = *inputs[i];
71
- Mat& out = outputs[i];
72
- int dims = inp.dims ;
73
- MatShape inShape (inp.size .p , inp.size .p + dims);
74
- MatShape outShape (out.size .p , out.size .p + dims);
75
- int dim = getPadDim (inShape);
76
-
77
- int actualIndex = index;
78
- if (index == 0 )
79
- actualIndex = inShape[dim];
80
-
81
- std::vector<std::pair<Range, Range> > srcDstRanges;
82
- srcDstRanges.push_back (std::make_pair (Range (0 , actualIndex), Range (0 , actualIndex)));
83
- srcDstRanges.push_back (std::make_pair (Range (actualIndex, inShape[dim]),
84
- Range (actualIndex + padding, outShape[dim])));
85
-
86
- std::vector<Range> srcRanges (dims, Range::all ()), dstRanges = srcRanges;
87
-
88
- for (int j = 0 ; j < srcDstRanges.size (); j++)
89
- {
90
- if (!srcDstRanges[j].first .empty ())
91
- {
92
- srcRanges[dim] = srcDstRanges[j].first ;
93
- dstRanges[dim] = srcDstRanges[j].second ;
94
- Mat dst = out (&dstRanges[0 ]);
95
- Mat src = inp (&srcRanges[0 ]).clone ();
96
- src.copyTo (dst);
97
- }
98
- }
99
- }
100
- }
101
-
102
- int getPadDim (const MatShape& shape) const
103
- {
104
- return inputDims > 0 && (int )shape.size () > inputDims ? paddingDim + 1 : paddingDim;
97
+ outputs[0 ].setTo (paddingValue);
98
+ inputs[0 ]->copyTo (outputs[0 ](dstRanges));
105
99
}
106
100
107
101
virtual Ptr<BackendNode> initHalide (const std::vector<Ptr<BackendWrapper> > &inputs)
108
102
{
109
103
#ifdef HAVE_HALIDE
110
104
int inW, inH, inC, inN;
105
+ int minN = std::max (dstRanges[0 ].start , 0 );
106
+ int minC = std::max (dstRanges[1 ].start , 0 );
107
+ int minY = std::max (dstRanges[2 ].start , 0 );
108
+ int minX = std::max (dstRanges[3 ].start , 0 );
111
109
Halide::Buffer<float > inputBuffer = halideBuffer (inputs[0 ]);
112
110
getCanonicalSize (inputBuffer, &inW, &inH, &inC, &inN);
113
111
114
112
Halide::Var x (" x" ), y (" y" ), c (" c" ), n (" n" );
115
113
Halide::Func top = (name.empty () ? Halide::Func () : Halide::Func (name));
116
114
Halide::Func padded =
117
115
Halide::BoundaryConditions::constant_exterior (inputBuffer, paddingValue);
118
- top (x, y, c, n) = padded (x, y, c, n);
116
+ top (x, y, c, n) = padded (x - minX , y - minY , c - minC , n - minN );
119
117
return Ptr<BackendNode>(new HalideBackendNode (top));
120
118
#endif // HAVE_HALIDE
121
119
return Ptr<BackendNode>();
122
120
}
123
121
124
- int paddingDim, padding, inputDims, index;
122
+ private:
123
+ std::vector<std::pair<int , int > > paddings; // Pairs pad before, pad after.
124
+ std::vector<Range> dstRanges;
125
+ int inputDims;
125
126
float paddingValue;
126
127
};
127
128
0 commit comments