Skip to content

GSoC Add ONNX Support for GatherElements#1082

Merged
asmorkalov merged 2 commits intoopencv:4.xfrom
Aser-Abdelfatah:GSoC_Support_GatherElements_ONNX
Oct 17, 2023
Merged

GSoC Add ONNX Support for GatherElements#1082
asmorkalov merged 2 commits intoopencv:4.xfrom
Aser-Abdelfatah:GSoC_Support_GatherElements_ONNX

Conversation

@Aser-Abdelfatah
Copy link
Copy Markdown
Contributor

@Aser-Abdelfatah Aser-Abdelfatah commented Aug 9, 2023

Merge with opencv/opencv#24092

This pull request serves as an addition to the pull request "GSoC Add ONNX Support for GatherElements #24092", which is submitted to the original OpenCV repository. It contains three tests to the GatherElements operator.
The three tests are sourced from:


Reference outputs for optical_flow_estimation_raft_2023aug.onnx is generated with the following script:

import cv2 as cv
import numpy as np

img1 = cv.imread("./opencv_extra/testdata/gpu/opticalflow/frame0.png")
img2 = cv.imread("./opencv_extra/testdata/gpu/opticalflow/frame1.png")

img1_blob = cv.cvtColor(img1, cv.COLOR_BGR2RGB)
img1_blob = cv.resize(img1_blob, (480, 360))
# source: (1, 3, 388, 584)
# target: 1, 3, 360, 480
img1_blob = cv.dnn.blobFromImage(img1_blob)
# source:  (1, 3, 388, 584)
# target: 1, 3, 360, 480
img2_blob = cv.cvtColor(img2, cv.COLOR_BGR2RGB)
img2_blob = cv.resize(img2_blob, (480, 360))
img2_blob = cv.dnn.blobFromImage(img2_blob)
print(img1_blob.shape, img2_blob.shape)

import onnxruntime as ort
net = ort.InferenceSession("optical_flow_estimation_raft_2023aug.onnx", providers=["CPUExecutionProvider"])
output = net.run(["12007", "12006"], {"0": img1_blob, "1": img2_blob})
np.save("output_optical_flow_estimation_raft_2023aug_0.npy", output[0])
np.save("output_optical_flow_estimation_raft_2023aug_1.npy", output[1])
print(output[0].shape)
print(output[1].shape)

models = [
Model(
name='RAFT',
url='https://drive.google.com/u/0/uc?id=1yWIbF4birkpZMhNNhqzy75d4EvJW-UXE&export=download',
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 share a source of that link in comment (i.e. origin repository)

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
Member

Choose a reason for hiding this comment

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

I mean it there an officially distributed model? There is a little chance that custom file will be available for a long time.

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.

This share link is actually from the opencv.org google drive. I uploaded it to OpenCV Shared -> Deep Models if you have access to it.


Source of the model is from https://github.com/PINTO0309/PINTO_model_zoo/tree/main/252_RAFT, where it uses external cloud drive called wasabi stoarge.

Copy link
Copy Markdown
Member

@dkurt dkurt Aug 29, 2023

Choose a reason for hiding this comment

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

Too big file. What are the data type and dimensions?

Copy link
Copy Markdown
Member

@dkurt dkurt left a comment

Choose a reason for hiding this comment

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

input_RAFT_0.npy and input_RAFT_1.npy sizes too big

@fengyuentau
Copy link
Copy Markdown
Member

Could you use one of the existing image in this repo, such as https://github.com/opencv/opencv_extra/blob/4.x/testdata/dnn/dog_orig_size.png? You can resize it to the target scale, run inference, then collect the corresponding output, so that the total size can be cut by half, which passes the limit check.

@Aser-Abdelfatah
Copy link
Copy Markdown
Contributor Author

Could you use one of the existing image in this repo, such as https://github.com/opencv/opencv_extra/blob/4.x/testdata/dnn/dog_orig_size.png? You can resize it to the target scale, run inference, then collect the corresponding output, so that the total size can be cut by half, which passes the limit check.

Sorry for getting back late to this. Since it's an optical flow model, the input should be two images. I can use the same image twice for both inputs, but it wouldn't really make much sense. Another approach would be finding two lightweight images, but a question is what is the limit check?

@dkurt
Copy link
Copy Markdown
Member

dkurt commented Sep 1, 2023

@Aser-Abdelfatah, you may use images from https://github.com/opencv/opencv_extra/tree/4.x/testdata/gpu/opticalflow. Preprocess them in runtime.

@Aser-Abdelfatah
Copy link
Copy Markdown
Contributor Author

@dkurt I didn't get the part about pre-processing in runtime. The testing code in opencv/modules/dnn/test/test_onnx_importer.cpp is essentially,

TEST_P(Test_ONNX_layers, RAFT) { testONNXModels("RAFT", npy, 0, 0, false, true, 2); }
So, the model expects two pre-processed inputs.
And of course, when I pre-process the images using a separate python code and convert the pre-processed numpy array to an npy file, the size of each input is the same, essentially 2.0 mega bytes.

@Aser-Abdelfatah
Copy link
Copy Markdown
Contributor Author

And sorry for keeping getting back late to this. The time difference is crazy

@dkurt
Copy link
Copy Markdown
Member

dkurt commented Sep 2, 2023

And of course, when I pre-process the images using a separate python code and convert the pre-processed numpy array to an npy file

So you can do the same in C++ - imread two images and preprocess using OpenCV methods.

@Aser-Abdelfatah
Copy link
Copy Markdown
Contributor Author

I'm struggling with the C++ implementation. Essentially, I can't find a way to export the 4-dimensional opencv Mat to npy file in C++.

@fengyuentau
Copy link
Copy Markdown
Member

You can do it in Python with OpenCV and NumPy.

import cv2 as cv
import numpy as np

img1 = cv.imread("/path/to/img1")
img2 = cv.imread("/path/to/img2")

import onnxruntime as ort
net = ort.InferenceSession("/path/to/raft/model")
output = net.run(["output_name"], {"input1_name": img1, "input2_name": img2})
np.save("output_file_name.npy", output[0])

Maybe you need to debug a little bit to run the code above, but it should be mostly correct.

@Aser-Abdelfatah
Copy link
Copy Markdown
Contributor Author

I did it before. The problem is that the resulting npy file is also 2 mega bytes

@fengyuentau
Copy link
Copy Markdown
Member

2MB is fine. IIRC, the limit is 3MB.

@dkurt
Copy link
Copy Markdown
Member

dkurt commented Sep 5, 2023

2MB is fine. IIRC, the limit is 3MB.

@fengyuentau, this is not fine. The preprocessing might be done in C++ without any issues. Such 2MB will be added to git history forever.

I'm struggling with the C++ implementation.

@Aser-Abdelfatah, share Python implementation for preprocessing. Show how .npy are saved so we can propose an alternative C++ impl.

@fengyuentau
Copy link
Copy Markdown
Member

How is it possible to test model accuracy if the output reference is not preserved in this repository?

What I am saying is we don't need to check the exact correct results as what common users expect, we don't need to perform preprocessings to make results correct and meaningful. Just put two input images that has the input scale that the model requires, save outputs as a npy file, put the output file here, and thats it.

@dkurt
Copy link
Copy Markdown
Member

dkurt commented Sep 5, 2023

There is no problem with output - it takes just 21Kb (see testdata/dnn/onnx/data/output_RAFT.npy). This is a reference for test. I propose the following:

  1. Use two images in Python and native RAFT to get output reference. Keep only output in .npy file
  2. Use the same images in C++ test with the same preprocessing which was done in Python.

No need to add preprocessed input .npy to this PR.

@dkurt
Copy link
Copy Markdown
Member

dkurt commented Sep 5, 2023

Sorry, seems like there is a misunderstanding. Proposed solution by @fengyuentau at #1082 (comment) is correct. I don't understand what is testdata/dnn/onnx/data/output_RAFT.npy and why it's 21Kb but not 2MB as @Aser-Abdelfatah mentioned. Let's upload actual files first.

@asmorkalov asmorkalov added the DNN dnn related tests and data label Sep 5, 2023
@Aser-Abdelfatah
Copy link
Copy Markdown
Contributor Author

import onnxruntime as ort
import onnx
from imread_from_url import imread_from_url
import cv2 as cv


img1 = imread_from_url("https://github.com/opencv/opencv_extra/blob/4.x/testdata/gpu/opticalflow/frame0.png?raw=true")
img2 = imread_from_url("https://github.com/opencv/opencv_extra/blob/4.x/testdata/gpu/opticalflow/frame1.png?raw=true")
input_width = 480
input_height = 360

image1 = cv.cvtColor(img1, cv.COLOR_BGR2RGB)
img_input1 = cv.resize(image1, (input_width, input_height))
img_input1 = img_input1.transpose(2, 0, 1)
img_input1 = img_input1[np.newaxis,:,:,:]
img_input1 = img_input1.astype(np.float32)

image2 = cv.cvtColor(img2, cv.COLOR_BGR2RGB)
img_input2 = cv.resize(image2, (input_width, input_height))
img_input2 = img_input2.transpose(2, 0, 1)
img_input2 = img_input2[np.newaxis,:,:,:]
img_input2 = img_input2.astype(np.float32)


model = ort.InferenceSession("path\\to\\model\\optical_flow_estimation_raft_2023aug.onnx", providers=['CUDAExecutionProvider', 'CPUExecutionProvider']) // the model is here https://github.com/Aser-Abdelfatah/opencv_zoo/blob/gsoc_RAFT_Model_ONNX/models/optical_flow_estimation_raft/optical_flow_estimation_raft_2023aug.onnx


model_inputs = model.get_inputs()
input_names = [model_inputs[i].name for i in range(len(model_inputs))]
model_outputs = model.get_outputs()
output_names = [model_outputs[i].name for i in range(len(model_outputs))]

y = model.run(output_names, {input_names[0]: img_input1, input_names[1]: img_input2})

np.save("input_RAFT_0.npy", img_input1)
np.save("input_RAFT_1.npy", img_input2)
np.save("output_RAFT.npy", y[0])

This is the python code for pre-processing, inference, and saving output. The input files are numpy float arrays of dimension (1, 3, 360, 480). The output is an optical flow map not an image.

@dkurt
Copy link
Copy Markdown
Member

dkurt commented Sep 5, 2023

@Aser-Abdelfatah, thanks! This is C++ function you need to use:

Mat image1 = cv::imread("frame0.png");
Mat input1 = cv::dnn::blobFromImage(image1, 1.0, Size(input_width, input_height), Scalar(), true);

@fengyuentau fengyuentau force-pushed the GSoC_Support_GatherElements_ONNX branch from 4680481 to 41de2d7 Compare October 7, 2023 07:05
@fengyuentau fengyuentau force-pushed the GSoC_Support_GatherElements_ONNX branch from 5ed338a to 127d9f1 Compare October 12, 2023 07:59
@asmorkalov asmorkalov merged commit f509aed into opencv:4.x Oct 17, 2023
asmorkalov pushed a commit to opencv/opencv that referenced this pull request Oct 18, 2023
…ments_ONNX

GSoC Add ONNX Support for GatherElements #24092

Merge with: opencv/opencv_extra#1082
Adds support to the ONNX operator GatherElements [operator docs](https://github.com/onnx/onnx/blob/main/docs/Operators.md#GatherElements)
Added tests to opencv_extra at pull request opencv/opencv_extra#1082

### 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
- [x] 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
@asmorkalov asmorkalov mentioned this pull request Nov 2, 2023
IskXCr pushed a commit to Haosonn/opencv that referenced this pull request Dec 20, 2023
…herElements_ONNX

GSoC Add ONNX Support for GatherElements opencv#24092

Merge with: opencv/opencv_extra#1082
Adds support to the ONNX operator GatherElements [operator docs](https://github.com/onnx/onnx/blob/main/docs/Operators.md#GatherElements)
Added tests to opencv_extra at pull request opencv/opencv_extra#1082

### 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
- [x] 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 Jan 4, 2024
…herElements_ONNX

GSoC Add ONNX Support for GatherElements opencv#24092

Merge with: opencv/opencv_extra#1082
Adds support to the ONNX operator GatherElements [operator docs](https://github.com/onnx/onnx/blob/main/docs/Operators.md#GatherElements)
Added tests to opencv_extra at pull request opencv/opencv_extra#1082

### 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
- [x] 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
…herElements_ONNX

GSoC Add ONNX Support for GatherElements opencv#24092

Merge with: opencv/opencv_extra#1082
Adds support to the ONNX operator GatherElements [operator docs](https://github.com/onnx/onnx/blob/main/docs/Operators.md#GatherElements)
Added tests to opencv_extra at pull request opencv/opencv_extra#1082

### 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
- [x] 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

Labels

DNN dnn related tests and data

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants