Skip to content

Commit 41b23fd

Browse files
committed
Merge pull request opencv#9524 from dkurt:dnn_torch_openface
2 parents 48cc1b3 + 7dc6b1d commit 41b23fd

File tree

10 files changed

+328
-34
lines changed

10 files changed

+328
-34
lines changed

modules/dnn/include/opencv2/dnn/all_layers.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
245245
bool globalPooling;
246246
bool computeMaxIdx;
247247
String padMode;
248+
bool ceilMode;
248249

249250
static Ptr<PoolingLayer> create(const LayerParams& params);
250251
};
@@ -257,6 +258,14 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
257258
static Ptr<SoftmaxLayer> create(const LayerParams& params);
258259
};
259260

261+
class CV_EXPORTS LPNormalizeLayer : public Layer
262+
{
263+
public:
264+
float pnorm, epsilon;
265+
266+
static Ptr<LPNormalizeLayer> create(const LayerParams& params);
267+
};
268+
260269
class CV_EXPORTS InnerProductLayer : public Layer
261270
{
262271
public:
@@ -294,6 +303,13 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
294303
{
295304
public:
296305
int axis;
306+
/**
307+
* @brief Add zero padding in case of concatenation of blobs with different
308+
* spatial sizes.
309+
*
310+
* Details: https://github.com/torch/nn/blob/master/doc/containers.md#depthconcat
311+
*/
312+
bool padding;
297313

298314
static Ptr<ConcatLayer> create(const LayerParams &params);
299315
};

modules/dnn/src/dnn.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ struct Net::Impl
11371137
// (and so we eliminate the concatenation layer, because the channels
11381138
// are concatenated implicitly).
11391139
Ptr<ConcatLayer> concatLayer = ld.layerInstance.dynamicCast<ConcatLayer>();
1140-
if( !concatLayer.empty() && concatLayer->axis == 1 &&
1140+
if( !concatLayer.empty() && concatLayer->axis == 1 && !concatLayer->padding &&
11411141
ld.outputBlobs.size() == 1 )
11421142
{
11431143
Mat& output = ld.outputBlobs[0];

modules/dnn/src/init.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ void initializeLayerFactory()
9191
CV_DNN_REGISTER_LAYER_CLASS(InnerProduct, InnerProductLayer);
9292
CV_DNN_REGISTER_LAYER_CLASS(Softmax, SoftmaxLayer);
9393
CV_DNN_REGISTER_LAYER_CLASS(MVN, MVNLayer);
94+
CV_DNN_REGISTER_LAYER_CLASS(LPNormalize, LPNormalizeLayer);
9495

9596
CV_DNN_REGISTER_LAYER_CLASS(ReLU, ReLULayer);
9697
CV_DNN_REGISTER_LAYER_CLASS(ChannelsPReLU, ChannelsPReLULayer);

modules/dnn/src/layers/concat_layer.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class ConcatLayerImpl : public ConcatLayer
5656
{
5757
setParamsFrom(params);
5858
axis = params.get<int>("axis", 1);
59+
padding = params.get<bool>("padding", false);
5960
}
6061

6162
virtual bool getMemoryShapes(const std::vector<MatShape> &inputs,
@@ -64,34 +65,41 @@ class ConcatLayerImpl : public ConcatLayer
6465
std::vector<MatShape> &internals) const
6566
{
6667
CV_Assert(inputs.size() > 0);
67-
outputs.clear();
68-
outputs.push_back(inputs[0]);
68+
outputs.resize(1, inputs[0]);
6969
int cAxis = clamp(axis, inputs[0]);
7070

7171
int axisSum = 0;
7272
for (size_t i = 0; i < inputs.size(); i++)
7373
{
7474
MatShape curShape = inputs[i];
7575

76-
CV_Assert(curShape.size() == outputs.back().size());
77-
for (int curAxis = 0; curAxis < outputs.back().size(); curAxis++)
76+
if (padding)
7877
{
79-
if (curAxis != cAxis && outputs.back()[curAxis] != curShape[curAxis])
80-
CV_Error(Error::StsBadSize, "Inconsitent shape for ConcatLayer");
78+
for (int curAxis = 0; curAxis < outputs[0].size(); curAxis++)
79+
{
80+
outputs[0][curAxis] = std::max(outputs[0][curAxis], curShape[curAxis]);
81+
}
82+
}
83+
else
84+
{
85+
CV_Assert(curShape.size() == outputs[0].size());
86+
for (int curAxis = 0; curAxis < outputs[0].size(); curAxis++)
87+
{
88+
if (curAxis != cAxis && outputs[0][curAxis] != curShape[curAxis])
89+
CV_Error(Error::StsBadSize, "Inconsitent shape for ConcatLayer");
90+
}
8191
}
8292

8393
axisSum += curShape[cAxis];
8494
}
85-
86-
outputs.back()[cAxis] = axisSum;
87-
95+
outputs[0][cAxis] = axisSum;
8896
return false;
8997
}
9098

9199
virtual bool supportBackend(int backendId)
92100
{
93101
return backendId == DNN_BACKEND_DEFAULT ||
94-
backendId == DNN_BACKEND_HALIDE && haveHalide() && axis == 1; // By channels
102+
backendId == DNN_BACKEND_HALIDE && haveHalide() && axis == 1 && !padding; // By channels
95103
}
96104

97105
class ChannelConcatInvoker : public ParallelLoopBody
@@ -174,7 +182,10 @@ class ConcatLayerImpl : public ConcatLayer
174182
int cAxis = clamp(axis, inputs[0]->dims);
175183
Mat& outMat = outputs[0];
176184

177-
if( cAxis == 1 && outMat.dims == 4 )
185+
if (padding)
186+
outMat.setTo(0);
187+
188+
if( cAxis == 1 && outMat.dims == 4 && !padding)
178189
{
179190
int nstripes = getNumThreads();
180191
ChannelConcatInvoker::run(inputs, outMat, nstripes);
@@ -187,6 +198,12 @@ class ConcatLayerImpl : public ConcatLayer
187198
for (size_t i = 0; i < inputs.size(); i++)
188199
{
189200
ranges[cAxis].end = ranges[cAxis].start + inputs[i]->size[cAxis];
201+
for (int j = 0; j < outMat.dims; ++j)
202+
{
203+
if (j == cAxis) continue;
204+
ranges[j].start = (outMat.size[j] - inputs[i]->size[j]) / 2;
205+
ranges[j].end = ranges[j].start + inputs[i]->size[j];
206+
}
190207
inputs[i]->copyTo(outMat(&ranges[0]));
191208
ranges[cAxis].start = ranges[cAxis].end;
192209
}

modules/dnn/src/layers/convolution_layer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class ConvolutionLayerImpl : public BaseConvolutionLayerImpl
187187
}
188188

189189
int ngroups = inpCn / blobs[0].size[1];
190-
CV_Assert(inpCn % ngroups == 0 && outCn % ngroups == 0);
190+
CV_Assert(ngroups > 0 && inpCn % ngroups == 0 && outCn % ngroups == 0);
191191

192192
int dims[] = {inputs[0][0], outCn, out.height, out.width};
193193
outputs.resize(inputs.size(), shape(dims));
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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) 2017, Intel Corporation, all rights reserved.
6+
// Third party copyrights are property of their respective owners.
7+
8+
#include "../precomp.hpp"
9+
#include "layers_common.hpp"
10+
#include <iostream>
11+
namespace cv { namespace dnn {
12+
13+
class LPNormalizeLayerImpl : public LPNormalizeLayer
14+
{
15+
public:
16+
17+
LPNormalizeLayerImpl(const LayerParams& params)
18+
{
19+
setParamsFrom(params);
20+
pnorm = params.get<float>("p", 2);
21+
epsilon = params.get<float>("eps", 1e-10f);
22+
CV_Assert(pnorm > 0);
23+
}
24+
25+
bool getMemoryShapes(const std::vector<MatShape> &inputs,
26+
const int requiredOutputs,
27+
std::vector<MatShape> &outputs,
28+
std::vector<MatShape> &internals) const
29+
{
30+
Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals);
31+
if (pnorm != 1 && pnorm != 2)
32+
{
33+
internals.resize(1, inputs[0]);
34+
}
35+
return true;
36+
}
37+
38+
virtual bool supportBackend(int backendId)
39+
{
40+
return backendId == DNN_BACKEND_DEFAULT;
41+
}
42+
43+
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
44+
{
45+
CV_TRACE_FUNCTION();
46+
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
47+
48+
CV_Assert(inputs[0]->total() == outputs[0].total());
49+
float norm;
50+
if (pnorm == 1)
51+
norm = cv::norm(*inputs[0], NORM_L1);
52+
else if (pnorm == 2)
53+
norm = cv::norm(*inputs[0], NORM_L2);
54+
else
55+
{
56+
pow(abs(*inputs[0]), pnorm, internals[0]);
57+
norm = pow(sum(internals[0])[0], 1.0f / pnorm);
58+
}
59+
multiply(*inputs[0], 1.0f / (norm + epsilon), outputs[0]);
60+
}
61+
62+
int64 getFLOPS(const std::vector<MatShape> &inputs,
63+
const std::vector<MatShape> &) const
64+
{
65+
int64 flops = 0;
66+
for (int i = 0; i < inputs.size(); i++)
67+
flops += 3 * total(inputs[i]);
68+
return flops;
69+
}
70+
};
71+
72+
Ptr<LPNormalizeLayer> LPNormalizeLayer::create(const LayerParams& params)
73+
{
74+
return Ptr<LPNormalizeLayer>(new LPNormalizeLayerImpl(params));
75+
}
76+
77+
} // namespace dnn
78+
} // namespace cv

modules/dnn/src/layers/pooling_layer.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ namespace cv
5454
namespace dnn
5555
{
5656

57-
//TODO: add ceil_mode param
5857
class PoolingLayerImpl : public PoolingLayer
5958
{
6059
public:
@@ -79,6 +78,7 @@ class PoolingLayerImpl : public PoolingLayer
7978
getPoolingKernelParams(params, kernel.height, kernel.width, globalPooling,
8079
pad.height, pad.width, stride.height, stride.width, padMode);
8180
setParamsFrom(params);
81+
ceilMode = params.get<bool>("ceil_mode", true);
8282
}
8383

8484
void finalize(const std::vector<Mat*> &inputs, std::vector<Mat> &outputs)
@@ -572,11 +572,10 @@ class PoolingLayerImpl : public PoolingLayer
572572
}
573573
else if (padMode.empty())
574574
{
575-
//Yeah, something strange Caffe scheme-)
576-
out.height = static_cast<int>(ceil(static_cast<float>(in.height + 2 * pad.height -
577-
kernel.height) / stride.height)) + 1;
578-
out.width = static_cast<int>(ceil(static_cast<float>(in.width + 2 * pad.width -
579-
kernel.width) / stride.width)) + 1;
575+
float height = (float)(in.height + 2 * pad.height - kernel.height) / stride.height;
576+
float width = (float)(in.width + 2 * pad.width - kernel.width) / stride.width;
577+
out.height = 1 + (ceilMode ? ceil(height) : floor(height));
578+
out.width = 1 + (ceilMode ? ceil(width) : floor(width));
580579

581580
if (pad.height || pad.width)
582581
{

modules/dnn/src/layers/reshape_layer.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,21 @@ static void computeShapeByReshapeMask(const MatShape &srcShape,
7575
if (explicitMask)
7676
{
7777
int maskTotal = total(maskShape);
78-
for (int i = srcRange.start + 1; i < srcRange.end; ++i)
78+
// Go from the end of mask until we collect required total.
79+
bool matched = false;
80+
for (int i = srcRange.end - 1; i >= srcRange.start; --i)
7981
{
80-
if (total(srcShape, i, srcRange.end) != maskTotal)
82+
if (matched)
8183
{
82-
srcRange.start = i - 1;
83-
break;
84+
if (i == 0 || total(srcShape, i, srcRange.end) != maskTotal)
85+
{
86+
srcRange.start = i + 1;
87+
break;
88+
}
89+
}
90+
else
91+
{
92+
matched = total(srcShape, i, srcRange.end) == maskTotal;
8493
}
8594
}
8695
CV_Assert(total(srcShape, srcRange.start, srcRange.end) == maskTotal);

0 commit comments

Comments
 (0)