From 15e3cf3cc5eb05a2aaf64ebde451be6870538fa9 Mon Sep 17 00:00:00 2001 From: Andrei Tamas Date: Tue, 22 Jul 2025 17:09:39 +0300 Subject: [PATCH] Merge pull request #27549 from atamas19:tensor_naming_functionality G-API: Implement cfgEnsureNamedTensors option to OpenVINO Params #27549 Added the option cfgEnsureNamedTensors to be applied on OpenVINO models with nameless tensors. If a tensor doesn't have a name, it sets a default one. The default name is created using OpenVINO's standard `make_default_tensor_name` . `make_default_tensor_name` had to be rewritten because it is only available in OpenVINO's dev_api. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- .../gapi/include/opencv2/gapi/infer/ov.hpp | 26 +++++++++++++++++++ modules/gapi/src/backends/ov/govbackend.cpp | 25 ++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/modules/gapi/include/opencv2/gapi/infer/ov.hpp b/modules/gapi/include/opencv2/gapi/infer/ov.hpp index 782792489b..9515744cac 100644 --- a/modules/gapi/include/opencv2/gapi/infer/ov.hpp +++ b/modules/gapi/include/opencv2/gapi/infer/ov.hpp @@ -99,6 +99,8 @@ struct ParamDesc { PluginConfigT config; size_t nireq = 1; + + bool ensure_named_tensors = false; }; // NB: Just helper to avoid code duplication. @@ -205,6 +207,24 @@ public: return *this; } + /** @brief Ensures the model has named tensors. + + This function is used to ensure that all tensors in the model have names. + It goes through all input and output nodes of the model and sets the names + if they are not set. This is neccessary for models with nameless tensors. + + If a tensor does not have a name, it will be assigned a default name + based on the producer node's friendly name. If the producer node has multiple + outputs, the name will be in the form "node_name:N", where N is the output index. + + @param flag If true, then it guarantees that all tensors will have names. + @return reference to this parameter structure. + */ + Params& cfgEnsureNamedTensors(bool flag = true) { + m_desc.ensure_named_tensors = flag; + return *this; + } + /** @brief Specifies tensor layout for an input layer. The function is used to set tensor layout for an input layer. @@ -524,6 +544,12 @@ public: return *this; } + /** @see ov::Params::cfgEnsureNamedTensors. */ + Params& cfgEnsureNamedTensors(bool flag = true) { + m_desc.ensure_named_tensors = flag; + return *this; + } + /** @see ov::Params::cfgInputTensorLayout. */ Params& cfgInputTensorLayout(std::string layout) { detail::getModelToSetAttrOrThrow(m_desc.kind, "input tensor layout") diff --git a/modules/gapi/src/backends/ov/govbackend.cpp b/modules/gapi/src/backends/ov/govbackend.cpp index ed2b6fd94e..dbaba382db 100644 --- a/modules/gapi/src/backends/ov/govbackend.cpp +++ b/modules/gapi/src/backends/ov/govbackend.cpp @@ -69,6 +69,27 @@ ov::Core cv::gapi::ov::wrap::getCore() { ? create_OV_Core_pointer() : create_OV_Core_instance(); } +static std::string make_default_tensor_name(const ov::Output& output) { + auto default_name = output.get_node()->get_friendly_name(); + if (output.get_node()->get_output_size() > 1) { + default_name += ':' + std::to_string(output.get_index()); + } + return default_name; +} + +static void ensureNamedTensors(std::shared_ptr model) { + for (auto& input : model->inputs()) { + if (input.get_names().empty()) { + input.set_names({make_default_tensor_name(input)}); + } + } + for (auto& output : model->outputs()) { + if (output.get_names().empty()) { + output.set_names({make_default_tensor_name(output)}); + } + } +} + static ov::AnyMap toOV(const ParamDesc::PluginConfigT &config) { return {config.begin(), config.end()}; } @@ -236,6 +257,10 @@ struct OVUnit { .read_model(desc.model_path, desc.bin_path); GAPI_Assert(model); + if (params.ensure_named_tensors) { + ensureNamedTensors(model); + } + if (params.num_in == 1u && params.input_names.empty()) { params.input_names = { model->inputs().begin()->get_any_name() }; }