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

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2024-01-15 17:23:10 +03:00
531 changed files with 20900 additions and 12934 deletions
+163
View File
@@ -0,0 +1,163 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2023 Intel Corporation
#include <opencv2/gapi/ot.hpp>
#include <opencv2/gapi/cpu/ot.hpp>
#include <opencv2/gapi/cpu/gcpukernel.hpp>
#include <vas/ot.hpp>
namespace cv
{
namespace gapi
{
namespace ot
{
// Helper functions for OT kernels
namespace {
void GTrackImplSetup(cv::GArrayDesc, cv::GArrayDesc, float,
std::shared_ptr<vas::ot::ObjectTracker>& state,
const ObjectTrackerParams& params) {
vas::ot::ObjectTracker::Builder ot_builder;
ot_builder.max_num_objects = params.max_num_objects;
ot_builder.input_image_format = vas::ColorFormat(params.input_image_format);
ot_builder.tracking_per_class = params.tracking_per_class;
state = ot_builder.Build(vas::ot::TrackingType::ZERO_TERM_IMAGELESS);
}
void GTrackImplPrepare(const std::vector<cv::Rect>& in_rects,
const std::vector<int32_t>& in_class_labels,
float delta,
std::vector<vas::ot::DetectedObject>& detected_objs,
vas::ot::ObjectTracker& state)
{
if (in_rects.size() != in_class_labels.size())
{
cv::util::throw_error(std::invalid_argument("Track() implementation run() method: in_rects and in_class_labels "
"sizes are different."));
}
detected_objs.reserve(in_rects.size());
for (std::size_t i = 0; i < in_rects.size(); ++i)
{
detected_objs.emplace_back(in_rects[i], in_class_labels[i]);
}
state.SetFrameDeltaTime(delta);
}
} // anonymous namespace
GAPI_OCV_KERNEL_ST(GTrackFromMatImpl, cv::gapi::ot::GTrackFromMat, vas::ot::ObjectTracker)
{
static void setup(cv::GMatDesc, cv::GArrayDesc rects_desc,
cv::GArrayDesc labels_desc, float delta,
std::shared_ptr<vas::ot::ObjectTracker>& state,
const cv::GCompileArgs& compile_args)
{
auto params = cv::gapi::getCompileArg<ObjectTrackerParams>(compile_args)
.value_or(ObjectTrackerParams{});
GAPI_Assert(params.input_image_format == 0 && "Only BGR input as cv::GMat is supported for now");
GTrackImplSetup(rects_desc, labels_desc, delta, state, params);
}
static void run(const cv::Mat& in_mat, const std::vector<cv::Rect>& in_rects,
const std::vector<int32_t>& in_class_labels, float delta,
std::vector<cv::Rect>& out_tr_rects,
std::vector<int32_t>& out_rects_classes,
std::vector<uint64_t>& out_tr_ids,
std::vector<int>& out_tr_statuses,
vas::ot::ObjectTracker& state)
{
std::vector<vas::ot::DetectedObject> detected_objs;
GTrackImplPrepare(in_rects, in_class_labels, delta, detected_objs, state);
GAPI_Assert(in_mat.type() == CV_8UC3 && "Input mat is not in BGR format");
auto objects = state.Track(in_mat, detected_objs);
for (auto&& object : objects)
{
out_tr_rects.push_back(object.rect);
out_rects_classes.push_back(object.class_label);
out_tr_ids.push_back(object.tracking_id);
out_tr_statuses.push_back(static_cast<int>(object.status));
}
}
};
GAPI_OCV_KERNEL_ST(GTrackFromFrameImpl, cv::gapi::ot::GTrackFromFrame, vas::ot::ObjectTracker)
{
static void setup(cv::GFrameDesc, cv::GArrayDesc rects_desc,
cv::GArrayDesc labels_desc, float delta,
std::shared_ptr<vas::ot::ObjectTracker>& state,
const cv::GCompileArgs& compile_args)
{
auto params = cv::gapi::getCompileArg<ObjectTrackerParams>(compile_args)
.value_or(ObjectTrackerParams{});
GAPI_Assert(params.input_image_format == 1 && "Only NV12 input as cv::GFrame is supported for now");
GTrackImplSetup(rects_desc, labels_desc, delta, state, params);
}
static void run(const cv::MediaFrame& in_frame, const std::vector<cv::Rect>& in_rects,
const std::vector<int32_t>& in_class_labels, float delta,
std::vector<cv::Rect>& out_tr_rects,
std::vector<int32_t>& out_rects_classes,
std::vector<uint64_t>& out_tr_ids,
std::vector<int>& out_tr_statuses,
vas::ot::ObjectTracker& state)
{
std::vector<vas::ot::DetectedObject> detected_objs;
GTrackImplPrepare(in_rects, in_class_labels, delta, detected_objs, state);
// Extract metadata from MediaFrame and construct cv::Mat atop of it
cv::MediaFrame::View view = in_frame.access(cv::MediaFrame::Access::R);
auto ptrs = view.ptr;
auto strides = view.stride;
auto desc = in_frame.desc();
GAPI_Assert((desc.fmt == cv::MediaFormat::NV12 || desc.fmt == cv::MediaFormat::BGR) \
&& "Input frame is not in NV12 or BGR format");
cv::Mat in;
if (desc.fmt == cv::MediaFormat::NV12) {
GAPI_Assert(ptrs[0] != nullptr && "Y plane pointer is empty");
GAPI_Assert(ptrs[1] != nullptr && "UV plane pointer is empty");
if (strides[0] > 0) {
in = cv::Mat(desc.size, CV_8UC1, ptrs[0], strides[0]);
} else {
in = cv::Mat(desc.size, CV_8UC1, ptrs[0]);
}
}
auto objects = state.Track(in, detected_objs);
for (auto&& object : objects)
{
out_tr_rects.push_back(object.rect);
out_rects_classes.push_back(object.class_label);
out_tr_ids.push_back(object.tracking_id);
out_tr_statuses.push_back(static_cast<int>(object.status));
}
}
};
cv::gapi::GKernelPackage cpu::kernels()
{
return cv::gapi::kernels
<
GTrackFromFrameImpl,
GTrackFromMatImpl
>();
}
} // namespace ot
} // namespace gapi
} // namespace cv
+6 -10
View File
@@ -2082,15 +2082,8 @@ struct InferList2: public cv::detail::KernelTag {
? uu.net.getInputsInfo().at(input_name_0)->getTensorDesc()
: uu.this_network.GetInputsInfo().at(input_name_0)->getTensorDesc();
if (cv::util::holds_alternative<cv::GMatDesc>(mm_0) ||
cv::util::holds_alternative<cv::GFrameDesc>(mm_0)) {
const auto trait = clarifyTrait(mm_0, tensor_desc_0.getDims());
if (trait != cv::gapi::ie::TraitAs::IMAGE) {
util::throw_error(std::runtime_error(
"IE Backend: Only images is"
" supported as the 0th argument"));
}
} else {
if (!(cv::util::holds_alternative<cv::GMatDesc>(mm_0) ||
cv::util::holds_alternative<cv::GFrameDesc>(mm_0))) {
util::throw_error(std::runtime_error(
"IE Backend: Unsupported input meta"
" for 0th argument in IE backend"));
@@ -2107,7 +2100,10 @@ struct InferList2: public cv::detail::KernelTag {
&& "Non-array inputs are not supported");
if (op.k.inKinds[idx] == cv::detail::OpaqueKind::CV_RECT) {
const auto input_trait = cv::gapi::ie::TraitAs::IMAGE;
const auto input_trait = clarifyTrait(mm_0, tensor_desc_0.getDims());
GAPI_Assert(input_trait == cv::gapi::ie::TraitAs::IMAGE
&& "IE Backend: Only image is supported as the 0th argument for an input array of cv::Rect");
// NB: Configuring input precision and network reshape must be done
// only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
@@ -33,6 +33,12 @@ cv::gapi::onnx::PyParams::cfgAddExecutionProvider(cv::gapi::onnx::ep::DirectML e
return *this;
}
cv::gapi::onnx::PyParams&
cv::gapi::onnx::PyParams::cfgAddExecutionProvider(cv::gapi::onnx::ep::CoreML ep) {
m_priv->cfgAddExecutionProvider(std::move(ep));
return *this;
}
cv::gapi::onnx::PyParams&
cv::gapi::onnx::PyParams::cfgAddExecutionProvider(cv::gapi::onnx::ep::CUDA ep) {
m_priv->cfgAddExecutionProvider(std::move(ep));
@@ -0,0 +1,50 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2023 Intel Corporation
#include "backends/onnx/coreml_ep.hpp"
#include "logger.hpp"
#ifdef HAVE_ONNX
#include <onnxruntime_cxx_api.h>
#ifdef HAVE_ONNX_COREML
#include "../providers/coreml/coreml_provider_factory.h"
void cv::gimpl::onnx::addCoreMLExecutionProvider(Ort::SessionOptions *session_options,
const cv::gapi::onnx::ep::CoreML &coreml_ep) {
uint32_t flags = 0u;
if (coreml_ep.use_cpu_only) {
flags |= COREML_FLAG_USE_CPU_ONLY;
}
if (coreml_ep.enable_on_subgraph) {
flags |= COREML_FLAG_ENABLE_ON_SUBGRAPH;
}
if (coreml_ep.enable_only_ane) {
flags |= COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE;
}
try {
OrtSessionOptionsAppendExecutionProvider_CoreML(*session_options, flags);
} catch (const std::exception &e) {
std::stringstream ss;
ss << "ONNX Backend: Failed to enable CoreML"
<< " Execution Provider: " << e.what();
cv::util::throw_error(std::runtime_error(ss.str()));
}
}
#else // HAVE_ONNX_COREML
void cv::gimpl::onnx::addCoreMLExecutionProvider(Ort::SessionOptions*,
const cv::gapi::onnx::ep::CoreML&) {
util::throw_error(std::runtime_error("G-API has been compiled with ONNXRT"
" without CoreML support"));
}
#endif // HAVE_ONNX_COREML
#endif // HAVE_ONNX
@@ -0,0 +1,23 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2023 Intel Corporation
#ifndef OPENCV_GAPI_COREML_EP_HPP
#define OPENCV_GAPI_COREML_EP_HPP
#include "opencv2/gapi/infer/onnx.hpp"
#ifdef HAVE_ONNX
#include <onnxruntime_cxx_api.h>
namespace cv {
namespace gimpl {
namespace onnx {
void addCoreMLExecutionProvider(Ort::SessionOptions *session_options,
const cv::gapi::onnx::ep::CoreML &coreml_ep);
}}}
#endif // HAVE_ONNX
#endif // OPENCV_GAPI_COREML_EP_HPP
+240 -3
View File
@@ -13,13 +13,240 @@
#ifdef HAVE_ONNX_DML
#include "../providers/dml/dml_provider_factory.h"
#ifdef HAVE_DIRECTML
#undef WINVER
#define WINVER 0x0A00
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0A00
#include <initguid.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <dxgi1_4.h>
#include <dxgi.h>
#include <dxcore.h>
#include <dxcore_interface.h>
#include <d3d12.h>
#include <directml.h>
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3d12.lib")
#pragma comment (lib, "dxgi.lib")
#pragma comment (lib, "dxcore.lib")
#pragma comment (lib, "directml.lib")
#endif // HAVE_DIRECTML
static void addDMLExecutionProviderWithAdapterName(Ort::SessionOptions *session_options,
const std::string &adapter_name);
void cv::gimpl::onnx::addDMLExecutionProvider(Ort::SessionOptions *session_options,
const cv::gapi::onnx::ep::DirectML &dml_ep) {
namespace ep = cv::gapi::onnx::ep;
GAPI_Assert(cv::util::holds_alternative<int>(dml_ep.ddesc));
const int device_id = cv::util::get<int>(dml_ep.ddesc);
switch (dml_ep.ddesc.index()) {
case ep::DirectML::DeviceDesc::index_of<int>(): {
const int device_id = cv::util::get<int>(dml_ep.ddesc);
try {
OrtSessionOptionsAppendExecutionProvider_DML(*session_options, device_id);
} catch (const std::exception &e) {
std::stringstream ss;
ss << "ONNX Backend: Failed to enable DirectML"
<< " Execution Provider: " << e.what();
cv::util::throw_error(std::runtime_error(ss.str()));
}
break;
}
case ep::DirectML::DeviceDesc::index_of<std::string>(): {
const std::string adapter_name = cv::util::get<std::string>(dml_ep.ddesc);
addDMLExecutionProviderWithAdapterName(session_options, adapter_name);
break;
}
default:
GAPI_Assert(false && "Invalid DirectML device description");
}
}
#ifdef HAVE_DIRECTML
#define THROW_IF_FAILED(hr, error_msg) \
{ \
if ((hr) != S_OK) \
throw std::runtime_error(error_msg); \
}
template <typename T>
void release(T *ptr) {
if (ptr) {
ptr->Release();
}
}
template <typename T>
using ComPtrGuard = std::unique_ptr<T, decltype(&release<T>)>;
template <typename T>
ComPtrGuard<T> make_com_ptr(T *ptr) {
return ComPtrGuard<T>{ptr, &release<T>};
}
struct AdapterDesc {
ComPtrGuard<IDXCoreAdapter> ptr;
std::string description;
};
static std::vector<AdapterDesc> getAvailableAdapters() {
std::vector<AdapterDesc> all_adapters;
IDXCoreAdapterFactory* factory_ptr;
GAPI_LOG_DEBUG(nullptr, "Create IDXCoreAdapterFactory");
THROW_IF_FAILED(
DXCoreCreateAdapterFactory(
__uuidof(IDXCoreAdapterFactory), (void**)&factory_ptr),
"Failed to create IDXCoreAdapterFactory");
auto factory = make_com_ptr<IDXCoreAdapterFactory>(factory_ptr);
IDXCoreAdapterList* adapter_list_ptr;
const GUID dxGUIDs[] = { DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE };
GAPI_LOG_DEBUG(nullptr, "CreateAdapterList");
THROW_IF_FAILED(
factory->CreateAdapterList(
ARRAYSIZE(dxGUIDs), dxGUIDs, __uuidof(IDXCoreAdapterList), (void**)&adapter_list_ptr),
"Failed to create IDXCoreAdapterList");
auto adapter_list = make_com_ptr<IDXCoreAdapterList>(adapter_list_ptr);
for (UINT i = 0; i < adapter_list->GetAdapterCount(); i++)
{
IDXCoreAdapter* curr_adapter_ptr;
GAPI_LOG_DEBUG(nullptr, "GetAdapter");
THROW_IF_FAILED(
adapter_list->GetAdapter(
i, __uuidof(IDXCoreAdapter), (void**)&curr_adapter_ptr),
"Failed to obtain IDXCoreAdapter"
);
auto curr_adapter = make_com_ptr<IDXCoreAdapter>(curr_adapter_ptr);
bool is_hardware = false;
curr_adapter->GetProperty(DXCoreAdapterProperty::IsHardware, &is_hardware);
// NB: Filter out if not hardware adapter.
if (!is_hardware) {
continue;
}
size_t desc_size = 0u;
char description[256];
curr_adapter->GetPropertySize(DXCoreAdapterProperty::DriverDescription, &desc_size);
curr_adapter->GetProperty(DXCoreAdapterProperty::DriverDescription, desc_size, &description);
all_adapters.push_back(AdapterDesc{std::move(curr_adapter), description});
}
return all_adapters;
};
struct DMLDeviceInfo {
ComPtrGuard<IDMLDevice> device;
ComPtrGuard<ID3D12CommandQueue> cmd_queue;
};
static DMLDeviceInfo createDMLInfo(IDXCoreAdapter* adapter) {
auto pAdapter = make_com_ptr<IUnknown>(adapter);
D3D_FEATURE_LEVEL d3dFeatureLevel = D3D_FEATURE_LEVEL_1_0_CORE;
if (adapter->IsAttributeSupported(DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS))
{
GAPI_LOG_INFO(nullptr, "DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS is supported");
d3dFeatureLevel = D3D_FEATURE_LEVEL::D3D_FEATURE_LEVEL_11_0;
IDXGIFactory4* dxgiFactory4;
GAPI_LOG_DEBUG(nullptr, "CreateDXGIFactory2");
THROW_IF_FAILED(
CreateDXGIFactory2(0, __uuidof(IDXGIFactory4), (void**)&dxgiFactory4),
"Failed to create IDXGIFactory4"
);
// If DXGI factory creation was successful then get the IDXGIAdapter from the LUID
// acquired from the selectedAdapter
LUID adapterLuid;
IDXGIAdapter* spDxgiAdapter;
GAPI_LOG_DEBUG(nullptr, "Get DXCoreAdapterProperty::InstanceLuid property");
THROW_IF_FAILED(
adapter->GetProperty(DXCoreAdapterProperty::InstanceLuid, &adapterLuid),
"Failed to get DXCoreAdapterProperty::InstanceLuid property");
GAPI_LOG_DEBUG(nullptr, "Get IDXGIAdapter by luid");
THROW_IF_FAILED(
dxgiFactory4->EnumAdapterByLuid(
adapterLuid, __uuidof(IDXGIAdapter), (void**)&spDxgiAdapter),
"Failed to get IDXGIAdapter");
pAdapter = make_com_ptr<IUnknown>(spDxgiAdapter);
} else {
GAPI_LOG_INFO(nullptr, "DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS isn't supported");
}
ID3D12Device* d3d12_device_ptr;
GAPI_LOG_DEBUG(nullptr, "Create D3D12Device");
THROW_IF_FAILED(
D3D12CreateDevice(
pAdapter.get(), d3dFeatureLevel, __uuidof(ID3D12Device), (void**)&d3d12_device_ptr),
"Failed to create ID3D12Device");
auto d3d12_device = make_com_ptr<ID3D12Device>(d3d12_device_ptr);
D3D12_COMMAND_LIST_TYPE commandQueueType = D3D12_COMMAND_LIST_TYPE_COMPUTE;
ID3D12CommandQueue* cmd_queue_ptr;
D3D12_COMMAND_QUEUE_DESC commandQueueDesc = {};
commandQueueDesc.Type = commandQueueType;
GAPI_LOG_DEBUG(nullptr, "Create D3D12CommandQueue");
THROW_IF_FAILED(
d3d12_device->CreateCommandQueue(
&commandQueueDesc, __uuidof(ID3D12CommandQueue), (void**)&cmd_queue_ptr),
"Failed to create D3D12CommandQueue"
);
GAPI_LOG_DEBUG(nullptr, "Create D3D12CommandQueue - successful");
auto cmd_queue = make_com_ptr<ID3D12CommandQueue>(cmd_queue_ptr);
IDMLDevice* dml_device_ptr;
GAPI_LOG_DEBUG(nullptr, "Create DirectML device");
THROW_IF_FAILED(
DMLCreateDevice(
d3d12_device.get(), DML_CREATE_DEVICE_FLAG_NONE, IID_PPV_ARGS(&dml_device_ptr)),
"Failed to create IDMLDevice");
GAPI_LOG_DEBUG(nullptr, "Create DirectML device - successful");
auto dml_device = make_com_ptr<IDMLDevice>(dml_device_ptr);
return {std::move(dml_device), std::move(cmd_queue)};
};
static void addDMLExecutionProviderWithAdapterName(Ort::SessionOptions *session_options,
const std::string &adapter_name) {
auto all_adapters = getAvailableAdapters();
std::vector<AdapterDesc> selected_adapters;
std::stringstream log_msg;
for (auto&& adapter : all_adapters) {
log_msg << adapter.description << std::endl;
if (std::strstr(adapter.description.c_str(), adapter_name.c_str())) {
selected_adapters.emplace_back(std::move(adapter));
}
}
GAPI_LOG_INFO(NULL, "\nAvailable DirectML adapters:\n" << log_msg.str());
if (selected_adapters.empty()) {
std::stringstream error_msg;
error_msg << "ONNX Backend: No DirectML adapters found match to \"" << adapter_name << "\"";
cv::util::throw_error(std::runtime_error(error_msg.str()));
} else if (selected_adapters.size() > 1) {
std::stringstream error_msg;
error_msg << "ONNX Backend: More than one adapter matches to \"" << adapter_name << "\":\n";
for (const auto &selected_adapter : selected_adapters) {
error_msg << selected_adapter.description << "\n";
}
cv::util::throw_error(std::runtime_error(error_msg.str()));
}
GAPI_LOG_INFO(NULL, "Selected device: " << selected_adapters.front().description);
auto dml = createDMLInfo(selected_adapters.front().ptr.get());
try {
OrtSessionOptionsAppendExecutionProvider_DML(*session_options, device_id);
OrtSessionOptionsAppendExecutionProviderEx_DML(
*session_options, dml.device.release(), dml.cmd_queue.release());
} catch (const std::exception &e) {
std::stringstream ss;
ss << "ONNX Backend: Failed to enable DirectML"
@@ -28,6 +255,16 @@ void cv::gimpl::onnx::addDMLExecutionProvider(Ort::SessionOptions *session_optio
}
}
#else // HAVE_DIRECTML
static void addDMLExecutionProviderWithAdapterName(Ort::SessionOptions*, const std::string&) {
std::stringstream ss;
ss << "ONNX Backend: Failed to add DirectML Execution Provider with adapter name."
<< " DirectML support is required.";
cv::util::throw_error(std::runtime_error(ss.str()));
}
#endif // HAVE_DIRECTML
#else // HAVE_ONNX_DML
void cv::gimpl::onnx::addDMLExecutionProvider(Ort::SessionOptions*,
@@ -10,6 +10,7 @@
#ifdef HAVE_ONNX
#include "backends/onnx/dml_ep.hpp"
#include "backends/onnx/coreml_ep.hpp"
#include <ade/util/algorithm.hpp> // any_of
#include <ade/util/zip_range.hpp>
@@ -211,6 +212,12 @@ static void addExecutionProvider(Ort::SessionOptions *session_options,
addDMLExecutionProvider(session_options, dml_ep);
break;
}
case ep::EP::index_of<ep::CoreML>(): {
GAPI_LOG_INFO(NULL, "CoreML Execution Provider is added.");
const auto &coreml_ep = cv::util::get<ep::CoreML>(execution_provider);
addCoreMLExecutionProvider(session_options, coreml_ep);
break;
}
case ep::EP::index_of<ep::CUDA>(): {
GAPI_LOG_INFO(NULL, "CUDA Execution Provider is added.");
const auto &cuda_ep = cv::util::get<ep::CUDA>(execution_provider);
+51 -17
View File
@@ -252,7 +252,8 @@ public:
const std::vector<cv::gimpl::RcDesc> & outs,
cv::GRunArg::Meta && meta,
std::vector<cv::gimpl::GIslandExecutable::InObj> && input_objs,
std::vector<cv::gimpl::GIslandExecutable::OutObj> && output_objs);
std::vector<cv::gimpl::GIslandExecutable::OutObj> && output_objs,
const cv::gimpl::ov::Options & options);
const cv::GArgs& inArgs() const;
@@ -281,6 +282,9 @@ public:
std::exception_ptr eptr;
const cv::GRunArg::Meta& getMeta() { return m_meta; };
const cv::gimpl::ov::Options& getOptions() const { return m_options; };
private:
cv::detail::VectorRef& outVecRef(std::size_t idx);
@@ -301,6 +305,8 @@ private:
// Input parameters passed to an inference operation.
cv::GArgs m_args;
cv::GShapes m_in_shapes;
cv::gimpl::ov::Options m_options;
};
OVCallContext::OVCallContext(const OVUnit & unit,
@@ -309,9 +315,11 @@ OVCallContext::OVCallContext(const OVUnit &
const std::vector<cv::gimpl::RcDesc> & outs,
cv::GRunArg::Meta && meta,
std::vector<cv::gimpl::GIslandExecutable::InObj> && input_objs,
std::vector<cv::gimpl::GIslandExecutable::OutObj> && output_objs)
std::vector<cv::gimpl::GIslandExecutable::OutObj> && output_objs,
const cv::gimpl::ov::Options & options)
: uu(unit), out(output), m_meta(std::move(meta)),
m_input_objs(std::move(input_objs)), m_output_objs(std::move(output_objs))
m_input_objs(std::move(input_objs)), m_output_objs(std::move(output_objs)),
m_options(options)
{
for (auto& it : m_input_objs) cv::gimpl::magazine::bindInArg (m_res, it.first, it.second);
for (auto& it : m_output_objs) cv::gimpl::magazine::bindOutArg(m_res, it.first, it.second);
@@ -577,9 +585,10 @@ static void PostOutputs(::ov::InferRequest &infer_request,
ctx->eptr = std::move(eptr);
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
// NB: Copy data back only if execution finished sucessfuly.
// Otherwise just post outputs to keep streaming executor contract.
if (!ctx->eptr) {
// NB: Copy data back only if execution finished sucessfuly
// and inference only mode is disabled.
// Otherwise just post outputs to maintain streaming executor contract.
if (!ctx->eptr && !ctx->getOptions().inference_only) {
const auto& out_name = ctx->uu.params.output_names[i];
copyFromOV(infer_request.get_tensor(out_name),
ctx->outMatR(i));
@@ -765,14 +774,19 @@ public:
if (explicit_in_model_layout) {
input_info.model().set_layout(::ov::Layout(*explicit_in_model_layout));
} else if (m_model->input(input_name).get_shape().size() == 4u) {
// NB: Back compatibility with IR's without any layout information.
// Note that default is only applicable for 4D inputs in order to
// support auto resize for image use cases.
GAPI_LOG_WARNING(NULL, "Failed to find layout for input layer \""
<< input_name << "\" - NCHW is set by default");
const std::string default_layout = "NCHW";
input_info.model().set_layout(::ov::Layout(default_layout));
m_input_model_layout.emplace(input_name, default_layout);
const auto& input_layout = ::ov::layout::get_layout(m_model->input(input_name));
if (!input_layout.empty()) {
GAPI_LOG_INFO(NULL, "Model input layout " << input_name << " found: " << input_layout.to_string() << ".");
} else {
// NB: Back compatibility with IR's without any layout information.
// Note that default is only applicable for 4D inputs in order to
// support auto resize for image use cases.
GAPI_LOG_WARNING(NULL, "Failed to find layout for input layer \""
<< input_name << "\" - NCHW is set by default");
const std::string default_layout = "NCHW";
input_info.model().set_layout(::ov::Layout(default_layout));
m_input_model_layout.emplace(input_name, default_layout);
}
}
const auto explicit_in_tensor_layout = lookUp(m_input_tensor_layout, input_name);
if (explicit_in_tensor_layout) {
@@ -990,6 +1004,11 @@ struct Infer: public cv::detail::KernelTag {
reqPool.getIdleRequest()->execute(
IInferExecutor::Task {
[ctx](::ov::InferRequest &infer_request) {
// NB: No need to populate model inputs with data
// if it's inference only mode.
if (ctx->getOptions().inference_only) {
return;
}
for (auto i : ade::util::iota(ctx->uu.params.num_in)) {
const auto& input_name = ctx->uu.params.input_names[i];
auto input_tensor = infer_request.get_tensor(input_name);
@@ -1069,6 +1088,10 @@ struct InferROI: public cv::detail::KernelTag {
static void run(std::shared_ptr<OVCallContext> ctx,
cv::gimpl::ov::RequestPool &reqPool) {
using namespace std::placeholders;
if (ctx->getOptions().inference_only) {
cv::util::throw_error(
std::logic_error("OV Backend: Inference only mode is not supported for InferROI!"));
}
reqPool.getIdleRequest()->execute(
IInferExecutor::Task {
[ctx](::ov::InferRequest &infer_request) {
@@ -1141,6 +1164,10 @@ struct InferList: public cv::detail::KernelTag {
static void run(std::shared_ptr<OVCallContext> ctx,
cv::gimpl::ov::RequestPool &reqPool) {
if (ctx->getOptions().inference_only) {
cv::util::throw_error(
std::logic_error("OV Backend: Inference only mode is not supported for InferList!"));
}
const auto& in_roi_vec = ctx->inArg<cv::detail::VectorRef>(0u).rref<cv::Rect>();
// NB: In case there is no input data need to post output anyway
if (in_roi_vec.empty()) {
@@ -1257,6 +1284,10 @@ struct InferList2: public cv::detail::KernelTag {
static void run(std::shared_ptr<OVCallContext> ctx,
cv::gimpl::ov::RequestPool &reqPool) {
if (ctx->getOptions().inference_only) {
cv::util::throw_error(
std::logic_error("OV Backend: Inference only mode is not supported for InferList2!"));
}
GAPI_Assert(ctx->inArgs().size() > 1u
&& "This operation must have at least two arguments");
// NB: This blob will be used to make roi from its, so
@@ -1348,9 +1379,9 @@ class GOVBackendImpl final: public cv::gapi::GBackend::Priv {
}
virtual EPtr compile(const ade::Graph &graph,
const cv::GCompileArgs &,
const cv::GCompileArgs &compileArgs,
const std::vector<ade::NodeHandle> &nodes) const override {
return EPtr{new cv::gimpl::ov::GOVExecutable(graph, nodes)};
return EPtr{new cv::gimpl::ov::GOVExecutable(graph, compileArgs, nodes)};
}
virtual cv::GKernelPackage auxiliaryKernels() const override {
@@ -1391,9 +1422,12 @@ createInferRequests(::ov::CompiledModel &compiled_model,
// GOVExecutable implementation //////////////////////////////////////////////
cv::gimpl::ov::GOVExecutable::GOVExecutable(const ade::Graph &g,
const cv::GCompileArgs &compileArgs,
const std::vector<ade::NodeHandle> &nodes)
: m_g(g), m_gm(m_g) {
m_options.inference_only =
cv::gapi::getCompileArg<cv::gapi::wip::ov::benchmark_mode>(compileArgs).has_value();
// FIXME: Currently this backend is capable to run a single inference node only.
// Need to extend our island fusion with merge/not-to-merge decision making parametrization
GConstGOVModel ovm(g);
@@ -1471,7 +1505,7 @@ void cv::gimpl::ov::GOVExecutable::run(cv::gimpl::GIslandExecutable::IInput &in
const auto &op = m_gm.metadata(this_nh).get<Op>();
auto ctx = std::make_shared<OVCallContext>(uu, out, op.args, op.outs,
std::move(stub_meta), std::move(input_objs), std::move(output_objs));
std::move(stub_meta), std::move(input_objs), std::move(output_objs), m_options);
const auto &kk = giem.metadata(this_nh).get<OVCallable>();
@@ -26,6 +26,12 @@ struct OVCompiled {
class RequestPool;
struct Options {
// Only performs inference of the model
// without i/o data transfer if enabled.
bool inference_only = false;
};
class GOVExecutable final: public GIslandExecutable
{
const ade::Graph &m_g;
@@ -42,8 +48,12 @@ class GOVExecutable final: public GIslandExecutable
// To manage multiple async requests
std::unique_ptr<RequestPool> m_reqPool;
// To manage additional execution options
Options m_options;
public:
GOVExecutable(const ade::Graph &graph,
const cv::GCompileArgs &compileArgs,
const std::vector<ade::NodeHandle> &nodes);
virtual inline bool canReshape() const override { return false; }