Skip to content

[G-API] Implement OpenVINO 2.0 backend#23595

Merged
asmorkalov merged 25 commits intoopencv:4.xfrom
TolyaTalamanov:at/implement-openvino-backend
Jun 2, 2023
Merged

[G-API] Implement OpenVINO 2.0 backend#23595
asmorkalov merged 25 commits intoopencv:4.xfrom
TolyaTalamanov:at/implement-openvino-backend

Conversation

@TolyaTalamanov
Copy link
Copy Markdown
Contributor

@TolyaTalamanov TolyaTalamanov commented May 9, 2023

Pull Request Readiness Checklist

Implemented basic functionality for OpenVINO 2.0 G-API backend.

Overview

  • Implement Infer kernel with some of essential configurable parameters + IR/Blob models format support.
  • Implement the rest of kernels: InferList, InferROI, Infer2 + other configurable params (e.g reshape)
  • Asyncrhonous execution support
  • Remote context support

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • 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
  • 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.
  • The feature is well documented and sample code can be built with the project CMake

EXPECT_LE(normInf, lInf) << comment;
}

ov::Core getCore() {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it fine to use the different ov::Core than it's in GOVBackend? (I think so)

static constexpr const char* tag = "age-gender-generic";
using Params = cv::gapi::ov::Params<cv::gapi::Generic>;

static Params params(const std::string &xml,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be variadic with by passing all parameters

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cosmetic, ignore so far

explicit OVUnit(const ParamDesc &pd)
: params(pd) {

if (cv::util::holds_alternative<ParamDesc::IR>(params.kind)) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably we need this logic encapsulated somewhere not to check it everywhere!!!

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);
copyToOV(ctx->inMat(i), input_tensor);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in fact it might be faster for "some" plugins to copy to pre-allocated buffer instead of creating another one over the cv::Mat memory without copy. The same for output - let plugin write to its own buffer and them copy from there.

They way of how to set/get data from openvino can be the strategy... (worth to add TODO at least)

@TolyaTalamanov
Copy link
Copy Markdown
Contributor Author

@dmatveev, @smirnov-alexey Folks! Could you have a look, please?

@dmatveev dmatveev added this to the 4.8.0 milestone May 23, 2023
@TolyaTalamanov TolyaTalamanov force-pushed the at/implement-openvino-backend branch from c992b85 to fce1678 Compare May 29, 2023 06:28
@TolyaTalamanov
Copy link
Copy Markdown
Contributor Author

@asmorkalov @opencv-alalek

Could you help me to understand what exactly goes wrong with that error:

/build/precommit_docs/4.x/opencv/modules/python/src2/typing_stubs_generator.py:52: UserWarning: Typing stubs generation has failed. Reason: Failed to resolve "cv2" namespace against "None". Errors: ['Failed to resolve "cv2.gapi" namespace against "cv2". Errors: ['Failed to resolve "cv2.gapi.ov" namespace against "cv2". Errors: [\'Failed to resolve "cv2.gapi.ov.PyParams" class against "cv2". Errors: [\\\'Failed to resolve "cv2.gapi.ov.PyParams.cfgPluginConfig" function against "cv2". Errors: [0]: Failed to resolve "config" argument: Failed to resolve "map_string_and_string" exposed as "map_string_and_string"\\\', \\\'Failed to resolve "cv2.gapi.ov.PyParams.cfgInputTensorLayout" function against "cv2". Errors: [0]: Failed to resolve "layout_map" argument: Failed to resolve "map_string_and_string" exposed as "map_string_and_string"\\\', \\\'Failed to resolve "cv2.gapi.ov.PyParams.cfgInputModelLayout" function against "cv2". Errors: [0]: Failed to resolve "layout_map" argument: Failed to resolve "map_string_and_string" exposed as "map_string_and_string"\\\', \\\'Failed to resolve "cv2.gapi.ov.PyParams.cfgOutputTensorLayout" function against "cv2". Errors: [0]: Failed to resolve "layout_map" argument: Failed to resolve "map_string_and_string" exposed as "map_string_and_string"\\\', \\\'Failed to resolve "cv2.gapi.ov.PyParams.cfgOutputModelLayout" function against "cv2". Errors: [0]: Failed to resolve "layout_map" argument: Failed to resolve "map_string_and_string" exposed as "map_string_and_string"\\\', \\\'Failed to resolve "cv2.gapi.ov.PyParams.cfgOutputTensorPrecision" function against "cv2". Errors: [0]: Failed to resolve "precision_map" argument: Failed to resolve "map_string_and_int" exposed as "map_string_and_int"\\\', \\\'Failed to resolve "cv2.gapi.ov.PyParams.cfgReshape" function against "cv2". Errors: [0]: Failed to resolve "new_shape_map" argument: Failed to resolve "map_string_and_vector_size_t" exposed as "map_string_and_vector_size_t"\\\']\']']']

@dkurt
Copy link
Copy Markdown
Member

dkurt commented May 29, 2023

@TolyaTalamanov, seems related to #20370 (probably, need to be added something here: https://github.com/opencv/opencv/pull/20370/files#diff-d7f280d2a075f044f0b9720fa39e3fff9a6346c3a8eccb0cf588f0b7e52a9f6bR132-R138)

auto batch_layout = (matdesc.dims[1] == 3 || matdesc.dims[1] == 1)
? ::ov::Layout("NCHW") : ::ov::Layout("NHWC");

cv::Size spatial_size = (matdesc.dims[1] == 3 || matdesc.dims[1] == 1)
Copy link
Copy Markdown
Contributor Author

@TolyaTalamanov TolyaTalamanov May 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or spatial_size can be obtained from tensor_layout if such explicitly specified by user

Supported algorithms: #INTER_NEAREST, #INTER_LINEAR, #INTER_CUBIC.
@return reference to this parameter structure.
*/
Params<Net>& cfgResize(int interpolation) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a default value here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, probably but then there won't be any default value for map case?

}

/** @see ov::Params::cfgPluginConfig. */
Params& cfgPluginConfig(const detail::ParamDesc::PluginConfigT &config) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, is there a way to avoid copy-paste for generic params?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find, template specialization or inheritance won't work there because it returns Params&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRTP would?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But don't do it now to expedite merge, just leave a TODO.

skip_if_openvino_not_available()

root_path = '/omz_intel_models/intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013'
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we utilize other models here? E.g. .onnx?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using a couple of them for ONNX backend tests.

# Check
self.assertEqual(0.0, cv.norm(ov_gender, gapi_gender, cv.NORM_INF))
self.assertEqual(0.0, cv.norm(ov_age, gapi_age, cv.NORM_INF))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about testing invalid cases? Where we get G-API or OV throwing an exception

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, there is not much invalid cases. The validation is only happens for Image case where the layout is being validated to be NHWC for other case there should be check that mat dims matches to tensor dims I added TODO for that

if (desc.planar) os << "p";
os << " ";
os << desc.size.width << "x" << desc.size.height;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't it break our serialization? Is there a >> operator?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, as S11N is not using i/ostream as LHS operand for <<.

}

cv::gapi::ov::PyParams&
cv::gapi::ov::PyParams::cfgPluginConfig(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we have both general params and generic ones?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What stands for general?
In C++ we have templated params and their specialization for generic case.
For python there is only generic params are relevant.

// NB: These functions are EXPORTed to make them accessible by the
// test suite only.
GAPI_EXPORTS std::vector<int> to_ocv(const ::ov::Shape &shape);
GAPI_EXPORTS int to_ocv(const ::ov::element::Type &type);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest implementing those in utils.cpp or hiding if it's not being used outside

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's only for our tests. Is there any difference in terms of where implementation should be placed?
govbackend.cpp our sources that are not exposed to user.

@@ -227,6 +227,12 @@ inline void convertInt64ToInt32(const int64_t* src, int* dst, size_t size)
[](int64_t el) { return static_cast<int>(el); });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggesting int32_t here2, just in case

// (and constructed by either bindIn/Out or resetInternal)
case cv::GShape::GOPAQUE: return cv::GArg(m_res.slot<cv::detail::OpaqueRef>().at(ref.id));

case cv::GShape::GFRAME: return cv::GArg(m_res.slot<cv::MediaFrame>().at(ref.id));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove it from here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, make sense


const cv::MediaFrame& OVCallContext::inFrame(std::size_t input) const {
return inArg<cv::MediaFrame>(input);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove it for now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea

m_request.set_callback([](std::exception_ptr){});
m_notify();
throw;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we notify in the end?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we notify in the callback but here execution failed earlier


IInferExecutor::Ptr cv::gimpl::ov::RequestPool::getIdleRequest() {
size_t id = 0u;
m_idle_ids.pop(id);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we set those to 0?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setup() fills m_idle_ids

return (model_shape.size() == 4u) &&
(!desc.isND()) /* dims == 2 */ &&
(desc.chan == 1 || desc.chan == 3) &&
(desc.size.height != 1 && desc.size.width != 1) &&
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw do you remember if we might have any non-1 dims in some of our cases which are still tensors? (e.g. 2, 3, other small numbers which are definitely are not images)

Copy link
Copy Markdown
Contributor Author

@TolyaTalamanov TolyaTalamanov May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can have Mat({15, 14}, CV_8UC1) but in this case model apparently will have 2D dimensions for that input so that it would be TENSOR for us

Copy link
Copy Markdown
Contributor Author

@TolyaTalamanov TolyaTalamanov May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point here is that 2D mats may work with 4D model shape only in case of IMAGE.
For TENSOR number of dims must match model shape size. (good point for comment)


static bool isImage(const cv::GMatDesc &desc,
const ::ov::Shape &model_shape) {
return (model_shape.size() == 4u) &&
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it be 3? Let's say if users/opencv doesn't provide N somehow?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User doesn't provide anything. model_shape comes from IR / ov::Model and in all cases for real image models have 4D layout in OpenVINO.

// NB: Double check that user provided correct layout.
// In fact, there is only one correct for image.
if (explicit_in_tensor_layout) {
if (*explicit_in_tensor_layout != "NHWC") {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can combine those 2 ifs

? ::ov::Layout(*explicit_in_tensor_layout) : model_layout;
const auto H_idx = ::ov::layout::height_idx(layout);
const auto W_idx = ::ov::layout::width_idx(layout);
// NB: It still possible if layout is "??HW".
Copy link
Copy Markdown
Contributor

@smirnov-alexey smirnov-alexey May 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document that in our doc and/or code

input_info.preprocess().resize(toOVInterp(*explicit_resize));
}
} else {
// NB: 2D case - know exactly where H and W...
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add some debug messages here other that throws? I mean what we assume in which case

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here = part with image/tensor logic. Messages = at least comments you put here

Copy link
Copy Markdown
Contributor

@smirnov-alexey smirnov-alexey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks great! Although, please answer my comments

@TolyaTalamanov
Copy link
Copy Markdown
Contributor Author

I hope I addressed everthing...
Let's wait for the CI and merge

@dmatveev
Copy link
Copy Markdown
Contributor

dmatveev commented Jun 1, 2023

@asmorkalov could you please have a look at this one?

The CI failure looks irrelevant

[  PASSED  ] 453 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] Imgcodecs_Tiff.decode_tile16384x16384

@asmorkalov
Copy link
Copy Markdown
Contributor

Restarted the failed build. Looks like we need to tune limits. Windows host is overbooked time to time.

@asmorkalov asmorkalov merged commit 5330112 into opencv:4.x Jun 2, 2023
@dmatveev
Copy link
Copy Markdown
Contributor

dmatveev commented Jun 2, 2023

Yay! Thanks & congrats! A big step forward!

@asmorkalov asmorkalov mentioned this pull request Jul 12, 2023
thewoz pushed a commit to thewoz/opencv that referenced this pull request Jan 4, 2024
…vino-backend

[G-API] Implement OpenVINO 2.0 backend opencv#23595

### Pull Request Readiness Checklist

Implemented basic functionality for `OpenVINO` 2.0 G-API backend.

#### Overview
- [x] Implement `Infer` kernel with some of essential configurable parameters + IR/Blob models format support.
- [ ] Implement the rest of kernels: `InferList`, `InferROI`, `Infer2` + other configurable params (e.g reshape)
- [x] Asyncrhonous execution support
- [ ] Remote context support

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
- [ ] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [x] 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
thewoz pushed a commit to thewoz/opencv that referenced this pull request May 29, 2024
…vino-backend

[G-API] Implement OpenVINO 2.0 backend opencv#23595

### Pull Request Readiness Checklist

Implemented basic functionality for `OpenVINO` 2.0 G-API backend.

#### Overview
- [x] Implement `Infer` kernel with some of essential configurable parameters + IR/Blob models format support.
- [ ] Implement the rest of kernels: `InferList`, `InferROI`, `Infer2` + other configurable params (e.g reshape)
- [x] Asyncrhonous execution support
- [ ] Remote context support

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
- [ ] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [x] 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants