1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

Merge pull request #27273 from dkurt:dnn_tflite_slice

* TFLite StridedSllice (without strides but just Slice)

* Enable strides for TF importers. Update OpenVINO backend for StridedSlice
This commit is contained in:
Dmitry Kurtaev
2025-05-03 14:47:45 +03:00
committed by GitHub
parent 806eb4767c
commit 0ea3c156a4
4 changed files with 56 additions and 6 deletions
+7 -3
View File
@@ -228,7 +228,7 @@ public:
{
#ifdef HAVE_INF_ENGINE
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
return sliceRanges.size() == 1 && !hasSteps && neg_step_dims.empty();
return sliceRanges.size() == 1 && neg_step_dims.empty();
#endif
#ifdef HAVE_CUDA
if (backendId == DNN_BACKEND_CUDA)
@@ -765,19 +765,23 @@ public:
auto& ieInpNode = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
CV_Assert(finalSliceRanges[0].size() == ieInpNode.get_shape().size());
std::vector<int64_t> offsets, dims;
std::vector<int64_t> offsets, dims, steps;
for (int i = 0; i < finalSliceRanges[0].size(); ++i)
{
offsets.push_back(finalSliceRanges[0][i].start);
dims.push_back(finalSliceRanges[0][i].end);
}
if (hasSteps)
steps = std::vector<int64_t>(sliceSteps[0].begin(), sliceSteps[0].end());
else
steps = std::vector<int64_t>((int64_t)dims.size(), 1);
auto lower_bounds = std::make_shared<ov::op::v0::Constant>(ov::element::i64,
ov::Shape{offsets.size()}, offsets.data());
auto upper_bounds = std::make_shared<ov::op::v0::Constant>(ov::element::i64,
ov::Shape{dims.size()}, dims.data());
auto strides = std::make_shared<ov::op::v0::Constant>(ov::element::i64,
ov::Shape{dims.size()}, std::vector<int64_t>((int64_t)dims.size(), 1));
ov::Shape{dims.size()}, steps);
auto slice = std::make_shared<ov::op::v1::StridedSlice>(ieInpNode,
lower_bounds, upper_bounds, strides, std::vector<int64_t>{}, std::vector<int64_t>{});
+3 -3
View File
@@ -1688,9 +1688,6 @@ void TFImporter::parseStridedSlice(tensorflow::GraphDef& net, const tensorflow::
{
if (end_mask & (1 << i))
ends.at<int>(i) = INT_MAX;
if (strides.at<int>(i) != 1)
CV_Error(Error::StsNotImplemented,
format("StridedSlice with stride %d", strides.at<int>(i)));
}
if (begins.total() == 4 && getDataLayout(name, data_layouts) == DNN_LAYOUT_NHWC)
{
@@ -1699,9 +1696,12 @@ void TFImporter::parseStridedSlice(tensorflow::GraphDef& net, const tensorflow::
std::swap(begins.at<int>(1), begins.at<int>(2));
std::swap(ends.at<int>(2), ends.at<int>(3));
std::swap(ends.at<int>(1), ends.at<int>(2));
std::swap(strides.at<int>(2), strides.at<int>(3));
std::swap(strides.at<int>(1), strides.at<int>(2));
}
layerParams.set("begin", DictValue::arrayInt((int*)begins.data, begins.total()));
layerParams.set("end", DictValue::arrayInt((int*)ends.data, ends.total()));
layerParams.set("steps", DictValue::arrayInt((int*)strides.data, strides.total()));
Pin inp = parsePin(layer.input(0));
if (value_id.find(inp.name) != value_id.end())
@@ -67,6 +67,7 @@ private:
void parseDetectionPostProcess(const Operator& op, const std::string& opcode, LayerParams& layerParams);
void parseActivation(const Operator& op, const std::string& opcode, LayerParams& layerParams);
void parseSplit(const Operator& op, const std::string& opcode, LayerParams& layerParams);
void parseStridedSlice(const Operator& op, const std::string& opcode, LayerParams& layerParams);
void parseFullyConnected(const Operator& op, const std::string& opcode, LayerParams& layerParams);
void parseSoftmax(const Operator& op, const std::string& opcode, LayerParams& layerParams);
void parseCast(const Operator& op, const std::string& opcode, LayerParams& layerParams);
@@ -290,6 +291,7 @@ TFLiteImporter::DispatchMap TFLiteImporter::buildDispatchMap()
dispatch["TFLite_Detection_PostProcess"] = &TFLiteImporter::parseDetectionPostProcess;
dispatch["TRANSPOSE"] = &TFLiteImporter::parseTranspose;
dispatch["MEAN"] = dispatch["REDUCE_MAX"] = &TFLiteImporter::parseGlobalPooling;
dispatch["STRIDED_SLICE"] = &TFLiteImporter::parseStridedSlice;
return dispatch;
}
@@ -919,6 +921,46 @@ void TFLiteImporter::parseSplit(const Operator& op, const std::string& opcode, L
addLayer(layerParams, op);
}
void TFLiteImporter::parseStridedSlice(const Operator& op, const std::string& opcode, LayerParams& layerParams) {
layerParams.type = "Slice";
auto options = op.builtin_options_as_StridedSliceOptions();
CV_Assert(options);
int endMask = options->end_mask();
if (options->new_axis_mask())
CV_Error(Error::StsNotImplemented, "New axis during StridedSlice");
if (options->shrink_axis_mask())
CV_Error(Error::StsNotImplemented, "Shrink axis during StridedSlice");
Mat begins = allTensors[op.inputs()->Get(1)];
Mat ends = allTensors[op.inputs()->Get(2)];
Mat strides = allTensors[op.inputs()->Get(3)];
CV_CheckTypeEQ(begins.type(), CV_32SC1, "");
CV_CheckTypeEQ(ends.type(), CV_32SC1, "");
CV_CheckTypeEQ(strides.type(), CV_32SC1, "");
const int num = begins.total();
CV_Assert_N(num == ends.total(), num == strides.total());
for (int i = 0; i < num; ++i)
{
if (endMask & (1 << i))
ends.at<int>(i) = INT_MAX;
}
if (begins.total() == 4 && layouts[op.inputs()->Get(0)] == DNN_LAYOUT_NHWC)
{
// Swap NHWC parameters' order to NCHW.
std::swap(begins.at<int>(2), begins.at<int>(3));
std::swap(begins.at<int>(1), begins.at<int>(2));
std::swap(ends.at<int>(2), ends.at<int>(3));
std::swap(ends.at<int>(1), ends.at<int>(2));
std::swap(strides.at<int>(2), strides.at<int>(3));
std::swap(strides.at<int>(1), strides.at<int>(2));
}
layerParams.set("begin", DictValue::arrayInt((int*)begins.data, begins.total()));
layerParams.set("end", DictValue::arrayInt((int*)ends.data, ends.total()));
layerParams.set("steps", DictValue::arrayInt((int*)strides.data, strides.total()));
addLayer(layerParams, op);
}
void TFLiteImporter::parseFullyConnected(const Operator& op, const std::string& opcode, LayerParams& layerParams) {
layerParams.type = "Gemm";
auto options = op.builtin_options_as_FullyConnectedOptions();
@@ -272,6 +272,10 @@ TEST_P(Test_TFLite, leakyRelu) {
testLayer("leakyRelu");
}
TEST_P(Test_TFLite, StridedSlice) {
testLayer("strided_slice");
}
INSTANTIATE_TEST_CASE_P(/**/, Test_TFLite, dnnBackendsAndTargets());
}} // namespace