diff --git a/modules/dnn/src/tflite/tflite_importer.cpp b/modules/dnn/src/tflite/tflite_importer.cpp index e44dd669270b..dd74d6ead0e7 100644 --- a/modules/dnn/src/tflite/tflite_importer.cpp +++ b/modules/dnn/src/tflite/tflite_importer.cpp @@ -86,7 +86,7 @@ class TFLiteImporter { int addReshapeLayer(const std::vector& shape, int axis, int num_axes, const std::string& name, const std::pair& inpId, int dtype, int inpTensorId); int addFlattenLayer(int axis, int end_axis, const std::string& name, const std::pair& inpId, int dtype, int outTensorId); - int addConstLayer(const Mat& data, const std::string& name); + void addConstLayer(const Mat& data, int tensorIdx); inline bool isInt8(const Operator& op); inline void getQuantParams(const Operator& op, float& inpScale, int& inpZero, float& outScale, int& outZero); @@ -488,11 +488,13 @@ void TFLiteImporter::parseConvolution(const Operator& op, const std::string& opc layerParams.type = "Convolution"; int inpId = op.inputs()->Get(0); + bool additionalPreLayer = false; if (layouts[inpId] == DNN_LAYOUT_UNKNOWN && modelTensors->Get(inpId)->shape()->size() == 4) { int permId = addPermuteLayer({0, 3, 1, 2}, layerParams.name + "/permute_input", layerIds[inpId], isInt8(op) ? CV_8S : CV_32F, op.inputs()->Get(0)); // NHWC -> NCHW layerIds[inpId] = std::make_pair(permId, 0); layouts[op.outputs()->Get(0)] = DNN_LAYOUT_NHWC; + additionalPreLayer = true; } auto options = reinterpret_cast(op.builtin_options()); @@ -554,7 +556,7 @@ void TFLiteImporter::parseConvolution(const Operator& op, const std::string& opc std::string fusedActivationType = EnumNameActivationFunctionType(options->fused_activation_function()); bool haveFusedActivation = fusedActivationType != "NONE"; - addLayer(layerParams, op, false, haveFusedActivation); + addLayer(layerParams, op, additionalPreLayer, haveFusedActivation); parseFusedActivation(op, options->fused_activation_function()); } @@ -720,27 +722,33 @@ void TFLiteImporter::parseEltwise(const Operator& op, const std::string& opcode, if (layouts[op.inputs()->Get(0)] == DNN_LAYOUT_NHWC && blob.dims == 1) { blob = blob.reshape(1, {1, (int)blob.total(), 1, 1}); } - int constId = addConstLayer(blob, modelTensors->Get(idx)->name()->str()); - layerIds[idx] = std::make_pair(constId, 0); + addConstLayer(blob, idx); } std::string fusedActivationType = EnumNameActivationFunctionType(activ); bool haveFusedActivation = fusedActivationType != "NONE"; - addLayer(layerParams, op, false, haveFusedActivation); + addLayer(layerParams, op, false, haveFusedActivation || opcode == "SQUARED_DIFFERENCE" || opcode == "RSQRT"); parseFusedActivation(op, activ); - // Layers that split on multiple operations - if (opcode == "SQUARED_DIFFERENCE") { - LayerParams lp; - lp.set("power", 2); - int id = dstNet.addLayerToPrev(layerParams.name + "/square", "Power", isOpInt8 ? CV_8S : CV_32F, lp); - layerIds[op.outputs()->Get(0)] = std::make_pair(id, 0); - } - else if (opcode == "RSQRT") { + if (opcode == "SQUARED_DIFFERENCE" || opcode == "RSQRT") { + if (haveFusedActivation) + CV_LOG_WARNING(NULL, format("%s with fused activation on new engine is not tested", opcode.c_str())); LayerParams lp; - int id = dstNet.addLayerToPrev(layerParams.name + "/inv", "Reciprocal", isOpInt8 ? CV_8S : CV_32F, lp); - layerIds[op.outputs()->Get(0)] = std::make_pair(id, 0); + if (opcode == "RSQRT") + lp.type = "Reciprocal"; + else { + lp.type = "Power"; + lp.set("power", 2); + } + if (newEngine) { + std::string tensorName = modelTensors->Get(op.outputs()->Get(0))->name()->str(); + addLayer(lp, {tensorName + "_additional_post_layer"}, {tensorName}); + layerIds[op.outputs()->Get(0)] = std::make_pair(-1, -1); + } else { + int id = dstNet.addLayerToPrev(layerParams.name + "/post", lp.type, isOpInt8 ? CV_8S : CV_32F, lp); + layerIds[op.outputs()->Get(0)] = std::make_pair(id, 0); + } } } @@ -866,8 +874,7 @@ void TFLiteImporter::parseConcat(const Operator& op, const std::string& opcode, transposeND(blob, {0, 3, 1, 2}, nchwBlob); blob = nchwBlob; } - int constId = addConstLayer(blob, modelTensors->Get(idx)->name()->str()); - layerIds[idx] = std::make_pair(constId, 0); + addConstLayer(blob, idx); } std::string fusedActivationType = EnumNameActivationFunctionType(options->fused_activation_function()); @@ -1079,11 +1086,23 @@ int TFLiteImporter::addFlattenLayer(int axis, int end_axis, const std::string& n } } -int TFLiteImporter::addConstLayer(const Mat& blob, const std::string& name) +void TFLiteImporter::addConstLayer(const Mat& blob, int tensorIdx) { + const std::string& name = modelTensors->Get(tensorIdx)->name()->str(); LayerParams lp; lp.blobs.push_back(blob.u ? blob : blob.clone()); // some tensors are owned by OpenCV - return dstNet.addLayer(name, "Const", lp); + if (newEngine) + { + lp.type = "Const"; + lp.name = name; + addLayer(lp, {}, {name}); + layerIds[tensorIdx] = std::make_pair(-1, -1); + } + else + { + int constId = dstNet.addLayer(name, "Const", lp); + layerIds[tensorIdx] = std::make_pair(constId, 0); + } } void TFLiteImporter::parseDeconvolution(const Operator& op, const std::string& opcode, LayerParams& layerParams) { @@ -1218,21 +1237,31 @@ void TFLiteImporter::parseStridedSlice(const Operator& op, const std::string& op lastShrinkAxis = axis; } std::string layerName = layerParams.name; - if (lastShrinkAxis != -1) + if (!newEngine && lastShrinkAxis != -1) { layerParams.name += "/slice"; } - addLayer(layerParams, op); + addLayer(layerParams, op, false, lastShrinkAxis != -1); for (int axis = 0; axis < num; ++axis) { if (!(shrinkMask & (1 << axis))) continue; - std::string name = (axis == lastShrinkAxis) ? layerName : format("%s/shrink_axis_%d", layerName.c_str(), axis); - int layerId = addFlattenLayer(axis, axis + 1, name, - layerIds[op.outputs()->Get(0)], isInt8(op) ? CV_8S : CV_32F, op.inputs()->Get(0)); - layerIds[op.inputs()->Get(0)] = std::make_pair(layerId, 0); + if (newEngine) + { + if (axis != lastShrinkAxis) + CV_LOG_WARNING(NULL, "StridedSlice with multiple axes shrink in new engine is not tested"); + addFlattenLayer(axis, axis + 1, layerName, + layerIds[op.outputs()->Get(0)], isInt8(op) ? CV_8S : CV_32F, op.outputs()->Get(0)); + } + else + { + std::string name = (axis == lastShrinkAxis) ? layerName : format("%s/shrink_axis_%d", layerName.c_str(), axis); + int layerId = addFlattenLayer(axis, axis + 1, name, + layerIds[op.outputs()->Get(0)], isInt8(op) ? CV_8S : CV_32F, op.inputs()->Get(0)); + layerIds[op.inputs()->Get(0)] = std::make_pair(layerId, 0); + } } } @@ -1328,22 +1357,7 @@ void TFLiteImporter::parseDetectionPostProcess(const Operator& op, const std::st layerParams.set("variance_encoded_in_target", true); } - LayerParams priorsLP; - priorsLP.name = layerParams.name + "/priors"; - priorsLP.type = "Const"; - priorsLP.blobs.resize(1, priors); - - if (newEngine) - { - std::string outTensorName = modelTensors->Get(op.inputs()->Get(2))->name()->str(); - addLayer(priorsLP, {}, {outTensorName}); - layerIds[op.inputs()->Get(2)] = std::make_pair(-1, -1); - } - else - { - int priorsId = dstNet.addLayer(priorsLP.name, priorsLP.type, priorsLP); - layerIds[op.inputs()->Get(2)] = std::make_pair(priorsId, 0); - } + addConstLayer(priors, op.inputs()->Get(2)); addLayer(layerParams, op); } diff --git a/modules/dnn/test/test_tflite_importer.cpp b/modules/dnn/test/test_tflite_importer.cpp index 52e5ecef275e..b4e89ee46cdd 100644 --- a/modules/dnn/test/test_tflite_importer.cpp +++ b/modules/dnn/test/test_tflite_importer.cpp @@ -283,7 +283,7 @@ TEST_P(Test_TFLite, StridedSlice) { testLayer("strided_slice"); } -TEST_P(Test_TFLite, DISABLED_face_blendshapes) +TEST_P(Test_TFLite, face_blendshapes) { Mat inp = blobFromNPY(findDataFile("dnn/tflite/face_blendshapes_inp.npy")); testModel("face_blendshapes", inp); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy