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:
@@ -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>{});
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user