Skip to content

Add python bindings for G-API onnx#22017

Merged
asmorkalov merged 1 commit intoopencv:4.xfrom
xiong-jie-y:py_onnx
Oct 4, 2022
Merged

Add python bindings for G-API onnx#22017
asmorkalov merged 1 commit intoopencv:4.xfrom
xiong-jie-y:py_onnx

Conversation

@xiong-jie-y
Copy link
Copy Markdown
Contributor

@xiong-jie-y xiong-jie-y commented May 20, 2022

Motivation

I think that the feature to run modle on onnxruntime is worth exposing to python G-API considering that

  • Onnxruntime supports many ML runtimes
  • Onnxruntime itself is very easy to install

This PR is the first step to expose onnxruntime features to python and support of execution providers will follow later.
This PR is draft, so let's have a discussion if necessary 🙂

Remaining tasks

  • Adding python unit test for onnx runtime
  • Create the same preprocess as openvino one to be able to accept the input with same shape as openvino. Currently transposing and reshaping is necessary like this in the user code.
    -> I will not implement this because it seems that the implementation in the onnx seems right from this line.

Questions

  • How do you manage models for testing in opencv? I coudln't find the model used in infer_ssd_onnx.cpp test.

Example Code

https://github.com/xiong-jie-y/g_api_examples/blob/main/low_light_enhancement_onnx/enhance_low_light.py

Pull Request Readiness Checklist

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's no bug report.
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
    I don't thik performance test is necessary this time, because it's just a binding.
  • The feature is well documented and sample code can be built with the project CMake

@fengyuentau
Copy link
Copy Markdown
Member

How do you manage models for testing in opencv? I coudln't find the model used in infer_ssd_onnx.cpp test.

You can clone opencv_extra and run this script to get the models for testing.

@xiong-jie-y
Copy link
Copy Markdown
Contributor Author

@fengyuentau
Thank you!
I wrote a test and it's ready for a detailed review 🙂

Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

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

@xiong-jie-y Thank you for the contribution!

@dmatveev Could you please take a look on this proposal?

@xiong-jie-y
Copy link
Copy Markdown
Contributor Author

Does someone know how to fix this CI error?
In my understanding, I need to call onnx model downloader somewhere, but I couldn't find appropriate ci code 🙁
https://pullrequest.opencv.org/buildbot/builders/precommit_linux64/builds/100283/steps/test_python3/logs/stdio

class test_gapi_infer(NewOpenCVTests):
def test_onnx_classification(self):
model_path = self.find_file(
"vision/classification/squeezenet/model/squeezenet1.0-9.onnx",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

DNN models are optional (available if OPENCV_DNN_TEST_DATA_PATH is specified).
Test should "skip" if file is not available.

Check this helper function: https://github.com/opencv/opencv/blob/4.5.5/modules/dnn/misc/python/test/test_dnn.py#L105-L110

There is missing onnx_models/ prefix also

model_path = self.find_file(
    "onnx_models/vision/classification/squeezenet/model/squeezenet1.0-9.onnx",
    [os.environ.get('OPENCV_DNN_TEST_DATA_PATH', os.getcwd()),
        os.environ['OPENCV_TEST_DATA_PATH']],
    required=False)

if model_path is None:
    raise unittest.SkipTest("Missing DNN test file")

Finally, test should not fail with message G-API has been compiled without ONNX support.
Test should catch this cv.error, check its message and "skip" as unsupported configuration.


BTW, download .py file from "gapi" is not accurate. It doesn't support launching from opencv_extra. It must be launched from location pointed by OPENCV_DNN_TEST_DATA_PATH.

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.

Thank you! Done! 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@alalek, is behavior of download gapi .py incorrect? What is expected?

I’m out of context, sorry.

@xiong-jie-y
Copy link
Copy Markdown
Contributor Author

@alalek @dmatveev
Sorry, I found a bug and fixed it about input_names and output_names.
Could you proceed the review if possible?

Also new features passes these tests.

./bin/opencv_test_gapi --gtest_filter="ONNX*"
./bin/opencv_test_core

@xiong-jie-y
Copy link
Copy Markdown
Contributor Author

Hi @alalek,

Thank you for the previous review comment!

This PR is not very emergent, but I want to merge this PR soon because I have more PRs that depends on this PR.
Is there a way to finish this PR faster?
If there's any problem on my code, design...etc, feel free to tell me 🙂

Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

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

Thank you for contribution!


std::vector<std::string> names_to_remap; //!< Names of output layers that will be processed in PostProc function.

bool is_generic;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please add documentation for this flag.

Does it really needed? (I see only false initial value)

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 believe it may be related to "generic infer" (with no network type defined), but let's @TolyaTalamanov to confirm

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.

Yes, it's needed, because only generic infer can be exposed to python

@xiong-jie-y
Copy link
Copy Markdown
Contributor Author

@alalek Thank you for the review!

Is it possible to assign one of the G-API developer as a second reviewer? 🙂
@dmatveev seems to unable to review now.

@dmatveev dmatveev self-assigned this Aug 2, 2022
@dmatveev
Copy link
Copy Markdown
Contributor

dmatveev commented Aug 2, 2022

@TolyaTalamanov @mpashchenkov do you have any comments here?

Copy link
Copy Markdown
Contributor

@dmatveev dmatveev left a comment

Choose a reason for hiding this comment

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

Looks good to me. Thanks @xiong-jie-y for your work!


std::vector<std::string> names_to_remap; //!< Names of output layers that will be processed in PostProc function.

bool is_generic;
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 believe it may be related to "generic infer" (with no network type defined), but let's @TolyaTalamanov to confirm

@param model_path path to model file (.onnx file).
*/
Params(const std::string& tag, const std::string& model_path)
: desc{model_path, 0u, 0u, {}, {}, {}, {}, {}, {}, {}, {}, {}, true}, m_tag(tag) {}
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.

@alalek here is where is_generic is set to true (in the tail)

@dmatveev
Copy link
Copy Markdown
Contributor

dmatveev commented Aug 2, 2022

Sorry for delay @xiong-jie-y , we're all on sort-of-leave now

Copy link
Copy Markdown
Contributor

@TolyaTalamanov TolyaTalamanov left a comment

Choose a reason for hiding this comment

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

Technically implementation is correct, but I'd ask @mpashchenkov to check if generic onnx infer is handled properly.


GModel::Graph model(gr);
auto& op = model.metadata(nh).get<Op>();
if (pp.is_generic) {
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.

@mpashchenkov Could review this part, please?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks like true (analogue of IE generic). But I think that tests are required.


testdata_required = bool(os.environ.get('OPENCV_DNN_TEST_REQUIRE_TESTDATA', False))

class test_gapi_infer(NewOpenCVTests):
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.

test_gapi_infer already exists, I'd change to test_gapi_onnx_infer

* @see struct Generic
*/
template<>
class Params<cv::gapi::Generic> {
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.

It'd be great to add test for generic onnx inference because it becomes core functionality for c++ users.


std::vector<std::string> names_to_remap; //!< Names of output layers that will be processed in PostProc function.

bool is_generic;
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.

Yes, it's needed, because only generic infer can be exposed to python

}

void ONNXCompiled::setOutput(int i, cv::Mat &m) {
void ONNXCompiled::setOutput(int i, cv::Mat &m)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unnecessary change.

}
// Adding const input is necessary because the definition of input_names
// includes const input.
for (const auto& a : pp.const_inputs)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is it necessary to add test for const input (generic case)?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ONNXbackend doesn’t have tests for generic infer.

class test_gapi_infer(NewOpenCVTests):
def test_onnx_classification(self):
model_path = self.find_file(
"vision/classification/squeezenet/model/squeezenet1.0-9.onnx",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@alalek, is behavior of download gapi .py incorrect? What is expected?

I’m out of context, sorry.

if (pp.is_generic) {
auto& info = cv::util::any_cast<cv::detail::InOutInfo>(op.params);

for (const auto& a : info.in_names)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Why do you use loops for assignment?


GModel::Graph model(gr);
auto& op = model.metadata(nh).get<Op>();
if (pp.is_generic) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks like true (analogue of IE generic). But I think that tests are required.

@asmorkalov
Copy link
Copy Markdown
Contributor

@xiong-jie-y @mvskg Friendly reminder

@mvskg
Copy link
Copy Markdown

mvskg commented Oct 3, 2022

ONNX part looks like true but for "possible unexpected cases in the future" tests for generic part need to be added.

@dmatveev
Copy link
Copy Markdown
Contributor

dmatveev commented Oct 4, 2022

Is there anything else blocking this PR from merge?

@TolyaTalamanov
Copy link
Copy Markdown
Contributor

Is there anything else blocking this PR from merge?

I guess only lack of tests. This PR introduces cv::gapi::Generic would be great to have c++ tests as well.
But on the other hand it works in python (based on tests).

@dmatveev
Copy link
Copy Markdown
Contributor

dmatveev commented Oct 4, 2022

I believe if there is python tests, that should be enough.
Anyway I doubt we have any ONNX builders now in the CI to test.

@TolyaTalamanov TolyaTalamanov self-requested a review October 4, 2022 06:36
Copy link
Copy Markdown
Contributor

@TolyaTalamanov TolyaTalamanov left a comment

Choose a reason for hiding this comment

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

Thank you! 👍

@asmorkalov asmorkalov merged commit fef8d4c into opencv:4.x Oct 4, 2022
@alalek alalek mentioned this pull request Jan 8, 2023
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.

7 participants