Skip to content

Commit 0f92db7

Browse files
committed
Enable padding subgraph
1 parent e1f14fc commit 0f92db7

4 files changed

Lines changed: 65 additions & 25 deletions

File tree

modules/dnn/src/layers/permute_layer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ class PermuteLayerImpl CV_FINAL : public PermuteLayer
342342
CV_Assert(out.dims == numAxes && out.size == outputs[0].size);
343343

344344
CV_Assert(inp.isContinuous() && out.isContinuous());
345-
CV_Assert(inp.type() == CV_32F && out.type() == CV_32F);
345+
// CV_Assert(inp.type() == CV_32F && out.type() == CV_32F);
346346

347347
if( numAxes == 4 )
348348
{

modules/dnn/src/onnx/onnx_graph_simplifier.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ template<typename T1, typename T2>
2828
void convertInt64ToInt32(const T1& src, T2& dst, int size)
2929
{
3030
for (int i = 0; i < size; i++) {
31-
if (src[i] < std::numeric_limits<int32_t>::min() || src[i] > std::numeric_limits<int32_t>::max()) {
32-
CV_Error(Error::StsOutOfRange, "Input is out of OpenCV 32S range");
33-
}
3431
dst[i] = saturate_cast<int32_t>(src[i]);
3532
}
3633
}

modules/dnn/src/onnx/onnx_importer.cpp

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class ONNXImporter
3939
struct LayerInfo {
4040
int layerId;
4141
int outputId;
42-
LayerInfo(int _layerId, int _outputId) : layerId(_layerId), outputId(_outputId) {}
42+
LayerInfo(int _layerId = 0, int _outputId = 0) : layerId(_layerId), outputId(_outputId) {}
4343
};
4444

4545
std::map<std::string, Mat> getGraphTensors(
@@ -300,6 +300,15 @@ void ONNXImporter::addLayer(Net& dstNet, LayerParams& layerParams,
300300
}
301301
}
302302

303+
static void addConstant(const std::string& name,
304+
const Mat& blob,
305+
std::map<std::string, Mat>& constBlobs,
306+
std::map<std::string, MatShape>& outShapes)
307+
{
308+
constBlobs.insert(std::make_pair(name, blob));
309+
outShapes.insert(std::make_pair(name, shape(blob)));
310+
}
311+
303312
void ONNXImporter::populateNet(Net dstNet)
304313
{
305314
CV_Assert(model_proto.has_graph());
@@ -533,6 +542,23 @@ void ONNXImporter::populateNet(Net dstNet)
533542
if (inp_size == 5) {
534543
CV_Assert(constBlobs.find(node_proto.input(4)) != constBlobs.end());
535544
Mat step_blob = getBlob(node_proto, constBlobs, 4);
545+
546+
// Very strange application for Slice op with tensor reversing.
547+
// We just workaround it for 2d constants.
548+
if (constBlobs.find(node_proto.input(0)) != constBlobs.end() &&
549+
axis == 0 &&
550+
start_blob.at<int>(0) == -1 && step_blob.at<int>(0) == -1 &&
551+
end_blob.at<int>(0) == std::numeric_limits<int32_t>::min())
552+
{
553+
Mat inp = getBlob(node_proto, constBlobs, 0);
554+
if (inp.dims == 2)
555+
{
556+
Mat flipped;
557+
flip(inp, flipped, 0);
558+
addConstant(layerParams.name, flipped, constBlobs, outShapes);
559+
continue;
560+
}
561+
}
536562
CV_CheckEQ(countNonZero(step_blob != 1), 0, "Slice layer only supports steps = 1");
537563
}
538564
}
@@ -547,8 +573,7 @@ void ONNXImporter::populateNet(Net dstNet)
547573
inputs.push_back(inp);
548574
runLayer(layerParams, inputs, sliced);
549575
CV_Assert(sliced.size() == 1);
550-
constBlobs.insert(std::make_pair(layerParams.name, sliced[0]));
551-
outShapes[layerParams.name] = shape(sliced[0]);
576+
addConstant(layerParams.name, sliced[0], constBlobs, outShapes);
552577
continue;
553578
}
554579
}
@@ -585,7 +610,7 @@ void ONNXImporter::populateNet(Net dstNet)
585610
Mat blob_1 = getBlob(node_proto, constBlobs, 1);
586611
CV_Assert(blob_0.size == blob_1.size);
587612
Mat output = isSub ? (blob_0 - blob_1) : (blob_0 + blob_1);
588-
constBlobs.insert(std::make_pair(layerParams.name, output));
613+
addConstant(layerParams.name, output, constBlobs, outShapes);
589614
continue;
590615
}
591616
else if (is_const_0 || is_const_1)
@@ -670,7 +695,7 @@ void ONNXImporter::populateNet(Net dstNet)
670695
{
671696
CV_Assert(node_proto.input_size() == 0);
672697
CV_Assert(layerParams.blobs.size() == 1);
673-
constBlobs.insert(std::make_pair(layerParams.name, layerParams.blobs[0]));
698+
addConstant(layerParams.name, layerParams.blobs[0], constBlobs, outShapes);
674699
continue;
675700
}
676701
else if (layer_type == "LSTM")
@@ -965,7 +990,7 @@ void ONNXImporter::populateNet(Net dstNet)
965990

966991
out = out.reshape(1, inp0.dims, inp0.size);
967992
out.dims = inp0.dims; // to workaround dims == 1
968-
constBlobs.insert(std::make_pair(layerParams.name, out));
993+
addConstant(layerParams.name, out, constBlobs, outShapes);
969994
continue;
970995
}
971996
}
@@ -1033,7 +1058,7 @@ void ONNXImporter::populateNet(Net dstNet)
10331058
std::vector<Mat> inputs(1, getBlob(node_proto, constBlobs, 0)), transposed;
10341059
runLayer(layerParams, inputs, transposed);
10351060
CV_Assert(transposed.size() == 1);
1036-
constBlobs.insert(std::make_pair(layerParams.name, transposed[0]));
1061+
addConstant(layerParams.name, transposed[0], constBlobs, outShapes);
10371062
continue;
10381063
}
10391064
}
@@ -1069,8 +1094,7 @@ void ONNXImporter::populateNet(Net dstNet)
10691094
Mat inp = getBlob(node_proto, constBlobs, 0);
10701095
Mat out = inp.reshape(1, outShape);
10711096
out.dims = outShape.size(); // to workaround dims == 1
1072-
constBlobs.insert(std::make_pair(layerParams.name, out));
1073-
outShapes[layerParams.name] = shape(out);
1097+
addConstant(layerParams.name, out, constBlobs, outShapes);
10741098
continue;
10751099
}
10761100
}
@@ -1085,7 +1109,7 @@ void ONNXImporter::populateNet(Net dstNet)
10851109
std::vector<int> out_size(&input.size[0], &input.size[0] + axis);
10861110
out_size.push_back(input.total(axis));
10871111
Mat output = input.reshape(1, out_size);
1088-
constBlobs.insert(std::make_pair(layerParams.name, output));
1112+
addConstant(layerParams.name, output, constBlobs, outShapes);
10891113
continue;
10901114
}
10911115
}
@@ -1108,7 +1132,7 @@ void ONNXImporter::populateNet(Net dstNet)
11081132
}
11091133

11101134
Mat out = input.reshape(0, dims);
1111-
constBlobs.insert(std::make_pair(layerParams.name, out));
1135+
addConstant(layerParams.name, out, constBlobs, outShapes);
11121136
continue;
11131137
}
11141138

@@ -1210,7 +1234,7 @@ void ONNXImporter::populateNet(Net dstNet)
12101234
if (layer_id.find(node_proto.input(0)) == layer_id.end()) {
12111235
std::vector<Mat> inputs(1, getBlob(node_proto, constBlobs, 0)), outputs;
12121236
runLayer(layerParams, inputs, outputs);
1213-
constBlobs.insert(std::make_pair(layerParams.name, outputs[0]));
1237+
addConstant(layerParams.name, outputs[0], constBlobs, outShapes);
12141238
continue;
12151239
}
12161240
}
@@ -1224,7 +1248,7 @@ void ONNXImporter::populateNet(Net dstNet)
12241248
if (layer_id.find(node_proto.input(0)) == layer_id.end()) {
12251249
Mat input = getBlob(node_proto, constBlobs, 0);
12261250
Mat out = input.reshape(0, dim);
1227-
constBlobs.insert(std::make_pair(layerParams.name, out));
1251+
addConstant(layerParams.name, out, constBlobs, outShapes);
12281252
continue;
12291253
}
12301254
replaceLayerParam(layerParams, "shape", "dim");
@@ -1233,6 +1257,17 @@ void ONNXImporter::populateNet(Net dstNet)
12331257
else if (layer_type == "Pad")
12341258
{
12351259
layerParams.type = "Padding";
1260+
if (node_proto.input_size() == 3)
1261+
{
1262+
// Paddings are in order begin0, begin1, .. beginN, end0, end1, ..., endN.
1263+
// We need to shuffle it to begin0, end0, begin1, end1, ...
1264+
Mat paddings = getBlob(node_proto, constBlobs, 1).reshape(1, 2);
1265+
paddings = paddings.t();
1266+
layerParams.set("paddings", DictValue::arrayInt(paddings.ptr<int>(), paddings.total()));
1267+
1268+
Mat value = getBlob(node_proto, constBlobs, 2);
1269+
layerParams.set("value", value.at<float>(0));
1270+
}
12361271
}
12371272
else if (layer_type == "Shape")
12381273
{
@@ -1246,7 +1281,7 @@ void ONNXImporter::populateNet(Net dstNet)
12461281
shapeMat.at<int>(j) = inpShape[j];
12471282
shapeMat.dims = 1;
12481283

1249-
constBlobs.insert(std::make_pair(layerParams.name, shapeMat));
1284+
addConstant(layerParams.name, shapeMat, constBlobs, outShapes);
12501285
continue;
12511286
}
12521287
else if (layer_type == "Cast")
@@ -1268,29 +1303,32 @@ void ONNXImporter::populateNet(Net dstNet)
12681303
default: type = blob.type();
12691304
}
12701305
blob.convertTo(blob, type);
1271-
constBlobs.insert(std::make_pair(layerParams.name, blob));
1306+
addConstant(layerParams.name, blob, constBlobs, outShapes);
12721307
continue;
12731308
}
12741309
else
12751310
layerParams.type = "Identity";
12761311
}
12771312
else if (layer_type == "ConstantOfShape" || layer_type == "ConstantFill")
12781313
{
1314+
int depth = CV_32F;
12791315
float fill_value;
12801316
if (!layerParams.blobs.empty())
12811317
{
12821318
CV_Assert(!layerParams.has("value"));
1283-
fill_value = layerParams.blobs[0].at<float>(0, 0);
1319+
depth = layerParams.blobs[0].depth();
1320+
Mat floats;
1321+
layerParams.blobs[0].convertTo(floats, CV_32F);
1322+
fill_value = floats.at<float>(0, 0);
12841323
}
12851324
else
12861325
fill_value = layerParams.get("value", 0);
12871326

12881327
MatShape inpShape = getBlob(node_proto, constBlobs, 0);
12891328
for (int i = 0; i < inpShape.size(); i++)
12901329
CV_CheckGT(inpShape[i], 0, "");
1291-
Mat tensor(inpShape.size(), &inpShape[0], CV_32F, Scalar(fill_value));
1292-
constBlobs.insert(std::make_pair(layerParams.name, tensor));
1293-
outShapes[node_proto.output(0)] = shape(tensor);
1330+
Mat tensor(inpShape.size(), &inpShape[0], depth, Scalar(fill_value));
1331+
addConstant(layerParams.name, tensor, constBlobs, outShapes);
12941332
continue;
12951333
}
12961334
else if (layer_type == "Gather")
@@ -1320,7 +1358,7 @@ void ONNXImporter::populateNet(Net dstNet)
13201358
out = input.reshape(1, 1).colRange(index, index + 1);
13211359
out.dims = dims;
13221360
}
1323-
constBlobs.insert(std::make_pair(layerParams.name, out));
1361+
addConstant(layerParams.name, out, constBlobs, outShapes);
13241362
continue;
13251363
}
13261364
else if (layer_type == "Concat")
@@ -1345,7 +1383,7 @@ void ONNXImporter::populateNet(Net dstNet)
13451383
runLayer(layerParams, inputs, concatenated);
13461384

13471385
CV_Assert(concatenated.size() == 1);
1348-
constBlobs.insert(std::make_pair(layerParams.name, concatenated[0]));
1386+
addConstant(layerParams.name, concatenated[0], constBlobs, outShapes);
13491387
continue;
13501388
}
13511389
}

modules/dnn/test/test_onnx_importer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,11 @@ TEST_P(Test_ONNX_nets, Inception_v1)
773773
testONNXModels("inception_v1", pb);
774774
}
775775

776+
TEST_P(Test_ONNX_nets, ZeroPad2d)
777+
{
778+
testONNXModels("ZeroPad2d");
779+
}
780+
776781
TEST_P(Test_ONNX_nets, Shufflenet)
777782
{
778783
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)

0 commit comments

Comments
 (0)