Skip to content

Adoptions of TFLife fixes to new engine #27439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 55 additions & 41 deletions modules/dnn/src/tflite/tflite_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class TFLiteImporter {
int addReshapeLayer(const std::vector<int>& shape, int axis, int num_axes,
const std::string& name, const std::pair<int, int>& inpId, int dtype, int inpTensorId);
int addFlattenLayer(int axis, int end_axis, const std::string& name, const std::pair<int, int>& 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);
Expand Down Expand Up @@ -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<const Conv2DOptions*>(op.builtin_options());
Expand Down Expand Up @@ -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());
}

Expand Down Expand Up @@ -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);
}
}
}

Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
}
}

Expand Down Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion modules/dnn/test/test_tflite_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading
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