Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

导出onnx #29

Open
jxhoh opened this issue Jul 24, 2024 · 16 comments
Open

导出onnx #29

jxhoh opened this issue Jul 24, 2024 · 16 comments

Comments

@jxhoh
Copy link

jxhoh commented Jul 24, 2024

话说,作者有想过导出onnx,然后c++调用吗

@wyf2020
Copy link
Contributor

wyf2020 commented Jul 24, 2024

我们暂时没有计划支持ONNX,并提供C++ inference,也许可以参考这两个仓库实现ONNXc++ inference

@jxhoh
Copy link
Author

jxhoh commented Jul 24, 2024

我们暂时没有计划支持ONNX,并提供C++ inference,也许可以参考这两个仓库实现ONNXc++ inference

好的好的,我看了这两个,我跑的不是很顺利,谢谢

@MachineEyes001
Copy link

@jxhoh 大佬,你转onnx成功了吗

@jxhoh
Copy link
Author

jxhoh commented Sep 5, 2024

@jxhoh 大佬,你转onnx成功了吗

我成功倒是成功了

@jxhoh
Copy link
Author

jxhoh commented Sep 5, 2024

@jxhoh 大佬,你转onnx成功了吗

按照作者来说的,看那两个仓库
就可以

@MachineEyes001
Copy link

好的,感谢,我试试

@jxhoh
Copy link
Author

jxhoh commented Sep 5, 2024

@wyf2020 @MachineEyes001
`import os
os.chdir("..")
from copy import deepcopy

import torch
import cv2
import numpy as np
import matplotlib.cm as cm
from src.utils.plotting import make_matching_figure
from src.loftr import LoFTR, full_default_cfg, opt_default_cfg, reparameter

You can choose model type in ['full', 'opt']

model_type = 'opt' # 'full' for best quality, 'opt' for best efficiency

You can choose numerical precision in ['fp32', 'mp', 'fp16']. 'fp16' for best efficiency

precision = 'fp32' # Enjoy near-lossless precision with Mixed Precision (MP) / FP16 computation if you have a modern GPU (recommended NVIDIA architecture >= SM_70).

You can also change the default values like thr. and npe (based on input image size)

if model_type == 'full':
_default_cfg = deepcopy(full_default_cfg)
elif model_type == 'opt':
_default_cfg = deepcopy(opt_default_cfg)

if precision == 'mp':
_default_cfg['mp'] = True
elif precision == 'fp16':
_default_cfg['half'] = True

print(_default_cfg)
matcher = LoFTR(config=_default_cfg)

matcher.load_state_dict(torch.load(r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloftr_outdoor.ckpt")['state_dict'])
matcher = reparameter(matcher) # no reparameterization will lead to low performance

if precision == 'fp16':
matcher = matcher.half()

matcher = matcher.eval().cuda()

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-35.jpg"
img1_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-50.jpg"
img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE)
img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE)
img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//3232, img0_raw.shape[0]//3232)) # input size shuold be divisible by 32
img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//3232, img1_raw.shape[0]//3232))

if precision == 'fp16':
img0 = torch.from_numpy(img0_raw)[None][None].half().cuda() / 255.
img1 = torch.from_numpy(img1_raw)[None][None].half().cuda() / 255.
else:
img0 = torch.from_numpy(img0_raw)[None][None].cuda() / 255.
img1 = torch.from_numpy(img1_raw)[None][None].cuda() / 255.

Inference with EfficientLoFTR and get prediction

#导出地址

eloftr_path = r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx"

dynamic_axes = {
"image0": {2: "height0", 3: "width0"},
"image1": {2: "height1", 3: "width1"},
"mkpts0": {0: "points_0"},
"mkpts1": {0: "points_1"},
"mconf": {0: "nums"},
}

torch.onnx.export(
matcher,
(img0,img1),
eloftr_path,
input_names=["image0", "image1"],
output_names=[
"mkpts0",
"mkpts1",
"mconf",
],
opset_version=17,
dynamic_axes=dynamic_axes,
)

`

这是我导出的代码

`import numpy as np
import onnxruntime as ort
import cv2
import os
os.chdir("..")
from copy import deepcopy

import torch
import cv2
import numpy as np
import matplotlib.cm as cm
from src.utils.plotting import make_matching_figure
import sqlite3
import time
trt = True

Load ONNX models

providers = ["CUDAExecutionProvider", "CPUExecutionProvider"]
if trt:
providers = [
(
"TensorrtExecutionProvider",
{
"trt_fp16_enable": True,
"trt_engine_cache_enable": True,
"trt_engine_cache_path": "weights/cache",
},
)
] + providers

import matplotlib.pyplot as plt

Load example images

img0_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4254.JPG"

img1_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4255.JPG"

#3443 1591
img0_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102822_resize.jpg"

img1_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102827_resize.jpg"

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-35.jpg"

img1_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-50.jpg"

img0_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\4.jpg"

img1_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\1.jpg"

img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE)
img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE)

img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//3232, img0_raw.shape[0]//3232)) # input size shuold be divisible by 32
img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//3232, img1_raw.shape[0]//3232))
input_data_0 = np.expand_dims(img0_raw, axis=0).astype(np.float32) / 255.0
input_data_1 = np.expand_dims(img1_raw, axis=0).astype(np.float32) / 255.0

eloftr_path = r'D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx'
#session = ort.InferenceSession(eloftr_path)

sess_options = ort.SessionOptions()
eloftr = ort.InferenceSession(
eloftr_path, sess_options=sess_options, providers=providers
)

将输入数据转换为 ONNX Runtime 需要的格式

input_name = eloftr.get_inputs()[0].name
input_tensor_0 = np.array(input_data_0).astype(np.float32)
input_tensor_1 = np.array(input_data_1).astype(np.float32)

假设 eloftr 和其他相关变量已经定义和初始化

kpts0, kpts1, mconf = ...

记录开始时间

start_time = time.time()

执行你的代码

kpts0, kpts1, mconf = eloftr.run(
None, {
'image0': input_tensor_0[None],
'image1': input_tensor_1[None],
})

记录结束时间

end_time = time.time()

计算总时间差

elapsed_time = end_time - start_time

打印执行时间

print(f"Elapsed time: {elapsed_time} seconds")

mkpts0 = kpts0
mkpts1 = kpts1
mconf = mconf

H, mask = cv2.findHomography(mkpts0, mkpts1, method=cv2.RANSAC, ransacReprojThreshold=10.0)

inliers_count = np.sum(mask)

total_matches = mkpts0.shape[0]

inliers_ratio = inliers_count / total_matches

print(f"inlines_ratio:{inliers_ratio},inlines_count:{inliers_count},total_matches:{total_matches}")

mask = mask.squeeze()

mkpts0 = mkpts0[mask == 1]

mkpts1 = mkpts1[mask == 1]

mconf = mconf[mask == 1]

mconf = (mconf - min(20.0, mconf.min())) / (max(30.0, mconf.max()) - min(20.0, mconf.min()))

color = cm.jet(mconf)
text = [
'LoFTR',
'Matches: {}'.format(len(mkpts0)),
]
fig = make_matching_figure(img0_raw, img1_raw, mkpts0, mkpts1, color, text=text)
这是测试调用的代码,c++的,就直接参考lightglue的就可以 onnx导出问题 argmax的问题,需要转换成 pytorch的max,这个地方改成mask = conf_matrix > self.thr
mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c',
**axes_lengths) mask = conf_matrix > self.thr
mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c',
**axes_lengths).long()还有下面这个地方mask_v, all_j_ids = mask.max(dim=2)`

这里改成
mask_v, all_j_ids = mask.float().max(dim=2) mask_v = mask_v.long() # Ensure mask_v is an integer tensor

2.还有 onnx的bool值的问题,onnx 不支持 tensor[bool]
nvalidGraph: [ONNXRuntimeError] : 10 : INVALID_GRAPH : Load model from T.onnx failed:This is an invalid model. Type Error: Type ‘tensor(bool)’ of input parameter (8) of operator (ScatterND) in node (ScatterND_15) is invalid.

3.Support for 'aten::unflatten' operator when exporting to ONNX opset
这个问题好像是升级了pytorch版本解决
pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu121
发生异常: UnsupportedOperatorError
Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues.
File "D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\export_model\export_model.py", line 70, in torch.onnx.export( torch.onnx.errors.UnsupportedOperatorError: Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues.

具体的问题就这么多了

@MachineEyes001
Copy link

@jxhoh 好的大佬, 非常感谢你的分享^v^

@rebmaso
Copy link

rebmaso commented Sep 12, 2024

@jxhoh Thanks for your reply! I keep having some problems with inference of the .onnx model that is generated. Which environment did you use? The one provided by the authors?

Could you please create a fork of eloftr with the onnx export notebook? Thanks 😊

@klein0809
Copy link

@wyf2020 @MachineEyes001 `import os os.chdir("..") from copy import deepcopy

import torch import cv2 import numpy as np import matplotlib.cm as cm from src.utils.plotting import make_matching_figure from src.loftr import LoFTR, full_default_cfg, opt_default_cfg, reparameter

You can choose model type in ['full', 'opt']

model_type = 'opt' # 'full' for best quality, 'opt' for best efficiency

You can choose numerical precision in ['fp32', 'mp', 'fp16']. 'fp16' for best efficiency

precision = 'fp32' # Enjoy near-lossless precision with Mixed Precision (MP) / FP16 computation if you have a modern GPU (recommended NVIDIA architecture >= SM_70).

You can also change the default values like thr. and npe (based on input image size)

if model_type == 'full': _default_cfg = deepcopy(full_default_cfg) elif model_type == 'opt': _default_cfg = deepcopy(opt_default_cfg)

if precision == 'mp': _default_cfg['mp'] = True elif precision == 'fp16': _default_cfg['half'] = True

print(_default_cfg) matcher = LoFTR(config=_default_cfg)

matcher.load_state_dict(torch.load(r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloftr_outdoor.ckpt")['state_dict']) matcher = reparameter(matcher) # no reparameterization will lead to low performance

if precision == 'fp16': matcher = matcher.half()

matcher = matcher.eval().cuda()

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-35.jpg" img1_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-50.jpg" img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE) img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE) img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//32_32, img0_raw.shape[0]//32_32)) # input size shuold be divisible by 32 img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//32_32, img1_raw.shape[0]//32_32))

if precision == 'fp16': img0 = torch.from_numpy(img0_raw)[None][None].half().cuda() / 255. img1 = torch.from_numpy(img1_raw)[None][None].half().cuda() / 255. else: img0 = torch.from_numpy(img0_raw)[None][None].cuda() / 255. img1 = torch.from_numpy(img1_raw)[None][None].cuda() / 255.

Inference with EfficientLoFTR and get prediction

#导出地址

eloftr_path = r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx"

dynamic_axes = { "image0": {2: "height0", 3: "width0"}, "image1": {2: "height1", 3: "width1"}, "mkpts0": {0: "points_0"}, "mkpts1": {0: "points_1"}, "mconf": {0: "nums"}, }

torch.onnx.export( matcher, (img0,img1), eloftr_path, input_names=["image0", "image1"], output_names=[ "mkpts0", "mkpts1", "mconf", ], opset_version=17, dynamic_axes=dynamic_axes, )

`

这是我导出的代码

`import numpy as np import onnxruntime as ort import cv2 import os os.chdir("..") from copy import deepcopy

import torch import cv2 import numpy as np import matplotlib.cm as cm from src.utils.plotting import make_matching_figure import sqlite3 import time trt = True

Load ONNX models

providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] if trt: providers = [ ( "TensorrtExecutionProvider", { "trt_fp16_enable": True, "trt_engine_cache_enable": True, "trt_engine_cache_path": "weights/cache", }, ) ] + providers

import matplotlib.pyplot as plt

Load example images

img0_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4254.JPG"

img1_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4255.JPG"

#3443 1591 img0_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102822_resize.jpg"

img1_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102827_resize.jpg"

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-35.jpg"

img1_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-50.jpg"

img0_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\4.jpg"

img1_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\1.jpg"

img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE) img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE)

img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//32_32, img0_raw.shape[0]//32_32)) # input size shuold be divisible by 32 img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//32_32, img1_raw.shape[0]//32_32)) input_data_0 = np.expand_dims(img0_raw, axis=0).astype(np.float32) / 255.0 input_data_1 = np.expand_dims(img1_raw, axis=0).astype(np.float32) / 255.0

eloftr_path = r'D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx' #session = ort.InferenceSession(eloftr_path)

sess_options = ort.SessionOptions() eloftr = ort.InferenceSession( eloftr_path, sess_options=sess_options, providers=providers )

将输入数据转换为 ONNX Runtime 需要的格式

input_name = eloftr.get_inputs()[0].name input_tensor_0 = np.array(input_data_0).astype(np.float32) input_tensor_1 = np.array(input_data_1).astype(np.float32)

假设 eloftr 和其他相关变量已经定义和初始化

kpts0, kpts1, mconf = ...

记录开始时间

start_time = time.time()

执行你的代码

kpts0, kpts1, mconf = eloftr.run( None, { 'image0': input_tensor_0[None], 'image1': input_tensor_1[None], })

记录结束时间

end_time = time.time()

计算总时间差

elapsed_time = end_time - start_time

打印执行时间

print(f"Elapsed time: {elapsed_time} seconds")

mkpts0 = kpts0 mkpts1 = kpts1 mconf = mconf

H, mask = cv2.findHomography(mkpts0, mkpts1, method=cv2.RANSAC, ransacReprojThreshold=10.0)

inliers_count = np.sum(mask)

total_matches = mkpts0.shape[0]

inliers_ratio = inliers_count / total_matches

print(f"inlines_ratio:{inliers_ratio},inlines_count:{inliers_count},total_matches:{total_matches}")

mask = mask.squeeze()

mkpts0 = mkpts0[mask == 1]

mkpts1 = mkpts1[mask == 1]

mconf = mconf[mask == 1]

mconf = (mconf - min(20.0, mconf.min())) / (max(30.0, mconf.max()) - min(20.0, mconf.min()))

color = cm.jet(mconf) text = [ 'LoFTR', 'Matches: {}'.format(len(mkpts0)), ] fig = make_matching_figure(img0_raw, img1_raw, mkpts0, mkpts1, color, text=text) 这是测试调用的代码,c++的,就直接参考lightglue的就可以 onnx导出问题 argmax的问题,需要转换成 pytorch的max,这个地方改成mask = conf_matrix > self.thr mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c', **axes_lengths) mask = conf_matrix > self.thr mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c', **axes_lengths).long()还有下面这个地方mask_v, all_j_ids = mask.max(dim=2)`

这里改成 mask_v, all_j_ids = mask.float().max(dim=2) mask_v = mask_v.long() # Ensure mask_v is an integer tensor

2.还有 onnx的bool值的问题,onnx 不支持 tensor[bool] nvalidGraph: [ONNXRuntimeError] : 10 : INVALID_GRAPH : Load model from T.onnx failed:This is an invalid model. Type Error: Type ‘tensor(bool)’ of input parameter (8) of operator (ScatterND) in node (ScatterND_15) is invalid.

3.Support for 'aten::unflatten' operator when exporting to ONNX opset 这个问题好像是升级了pytorch版本解决 pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu121 发生异常: UnsupportedOperatorError Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues. File "D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\export_model\export_model.py", line 70, in torch.onnx.export( torch.onnx.errors.UnsupportedOperatorError: Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues.

具体的问题就这么多了

大佬 请教一哈。你上面提到的三点我都改了 然后export没有抱错,但是推理的时候遇到了两张图的特征点数量不匹配的情况,在fine_matching中的add1节点。请教一下你遇到过这个问题哇

@jxhoh
Copy link
Author

jxhoh commented Nov 5, 2024

@jxhoh Thanks for your reply! I keep having some problems with inference of the .onnx model that is generated. Which environment did you use? The one provided by the authors?

Could you please create a fork of eloftr with the onnx export notebook? Thanks 😊

I'll use the environment exported by the author. I don't know what problem you've encountered.

@jxhoh
Copy link
Author

jxhoh commented Nov 5, 2024

@wyf2020 @MachineEyes001 `import os os.chdir("..") from copy import deepcopy
import torch import cv2 import numpy as np import matplotlib.cm as cm from src.utils.plotting import make_matching_figure from src.loftr import LoFTR, full_default_cfg, opt_default_cfg, reparameter

You can choose model type in ['full', 'opt']

model_type = 'opt' # 'full' for best quality, 'opt' for best efficiency

You can choose numerical precision in ['fp32', 'mp', 'fp16']. 'fp16' for best efficiency

precision = 'fp32' # Enjoy near-lossless precision with Mixed Precision (MP) / FP16 computation if you have a modern GPU (recommended NVIDIA architecture >= SM_70).

You can also change the default values like thr. and npe (based on input image size)

if model_type == 'full': _default_cfg = deepcopy(full_default_cfg) elif model_type == 'opt': _default_cfg = deepcopy(opt_default_cfg)
if precision == 'mp': _default_cfg['mp'] = True elif precision == 'fp16': _default_cfg['half'] = True
print(_default_cfg) matcher = LoFTR(config=_default_cfg)
matcher.load_state_dict(torch.load(r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloftr_outdoor.ckpt")['state_dict']) matcher = reparameter(matcher) # no reparameterization will lead to low performance
if precision == 'fp16': matcher = matcher.half()
matcher = matcher.eval().cuda()

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-35.jpg" img1_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-50.jpg" img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE) img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE) img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//32_32, img0_raw.shape[0]//32_32)) # input size shuold be divisible by 32 img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//32_32, img1_raw.shape[0]//32_32))
if precision == 'fp16': img0 = torch.from_numpy(img0_raw)[None][None].half().cuda() / 255. img1 = torch.from_numpy(img1_raw)[None][None].half().cuda() / 255. else: img0 = torch.from_numpy(img0_raw)[None][None].cuda() / 255. img1 = torch.from_numpy(img1_raw)[None][None].cuda() / 255.

Inference with EfficientLoFTR and get prediction

#导出地址
eloftr_path = r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx"
dynamic_axes = { "image0": {2: "height0", 3: "width0"}, "image1": {2: "height1", 3: "width1"}, "mkpts0": {0: "points_0"}, "mkpts1": {0: "points_1"}, "mconf": {0: "nums"}, }
torch.onnx.export( matcher, (img0,img1), eloftr_path, input_names=["image0", "image1"], output_names=[ "mkpts0", "mkpts1", "mconf", ], opset_version=17, dynamic_axes=dynamic_axes, )
这是我导出的代码import numpy as np import onnxruntime as ort import cv2 import os os.chdir("..") from copy import deepcopy
import torch import cv2 import numpy as np import matplotlib.cm as cm from src.utils.plotting import make_matching_figure import sqlite3 import time trt = True

Load ONNX models

providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] if trt: providers = [ ( "TensorrtExecutionProvider", { "trt_fp16_enable": True, "trt_engine_cache_enable": True, "trt_engine_cache_path": "weights/cache", }, ) ] + providers
import matplotlib.pyplot as plt

Load example images

img0_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4254.JPG"

img1_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4255.JPG"

#3443 1591 img0_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102822_resize.jpg"
img1_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102827_resize.jpg"

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-35.jpg"

img1_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-50.jpg"

img0_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\4.jpg"

img1_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\1.jpg"

img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE) img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE)
img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//32_32, img0_raw.shape[0]//32_32)) # input size shuold be divisible by 32 img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//32_32, img1_raw.shape[0]//32_32)) input_data_0 = np.expand_dims(img0_raw, axis=0).astype(np.float32) / 255.0 input_data_1 = np.expand_dims(img1_raw, axis=0).astype(np.float32) / 255.0
eloftr_path = r'D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx' #session = ort.InferenceSession(eloftr_path)
sess_options = ort.SessionOptions() eloftr = ort.InferenceSession( eloftr_path, sess_options=sess_options, providers=providers )

将输入数据转换为 ONNX Runtime 需要的格式

input_name = eloftr.get_inputs()[0].name input_tensor_0 = np.array(input_data_0).astype(np.float32) input_tensor_1 = np.array(input_data_1).astype(np.float32)

假设 eloftr 和其他相关变量已经定义和初始化

kpts0, kpts1, mconf = ...

记录开始时间

start_time = time.time()

执行你的代码

kpts0, kpts1, mconf = eloftr.run( None, { 'image0': input_tensor_0[None], 'image1': input_tensor_1[None], })

记录结束时间

end_time = time.time()

计算总时间差

elapsed_time = end_time - start_time

打印执行时间

print(f"Elapsed time: {elapsed_time} seconds")
mkpts0 = kpts0 mkpts1 = kpts1 mconf = mconf

H, mask = cv2.findHomography(mkpts0, mkpts1, method=cv2.RANSAC, ransacReprojThreshold=10.0)

inliers_count = np.sum(mask)

total_matches = mkpts0.shape[0]

inliers_ratio = inliers_count / total_matches

print(f"inlines_ratio:{inliers_ratio},inlines_count:{inliers_count},total_matches:{total_matches}")

mask = mask.squeeze()

mkpts0 = mkpts0[mask == 1]

mkpts1 = mkpts1[mask == 1]

mconf = mconf[mask == 1]

mconf = (mconf - min(20.0, mconf.min())) / (max(30.0, mconf.max()) - min(20.0, mconf.min()))
color = cm.jet(mconf) text = [ 'LoFTR', 'Matches: {}'.format(len(mkpts0)), ] fig = make_matching_figure(img0_raw, img1_raw, mkpts0, mkpts1, color, text=text) mask = conf_matrix > self.thr mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c', **axes_lengths)mask = conf_matrix > self.thr mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c', **axes_lengths).long()mask_v, all_j_ids = mask.max(dim=2)这是测试调用的代码,c++的,就直接参考lightglue的就可以 onnx导出问题 argmax的问题,需要转换成 pytorch的max,这个地方改成 ``还有下面这个地方这里改成mask_v, all_j_ids = mask.float().max(dim=2) mask_v = mask_v.long() # Ensure mask_v is an integer tensor`
2.还有 onnx的bool值的问题,onnx 不支持 tensor[bool] nvalidGraph: [ONNXRuntimeError] : 10 : INVALID_GRAPH : Load model from T.onnx failed:This is an invalid model. Type Error: Type ‘tensor(bool)’ of input parameter (8) of operator (ScatterND) in node (ScatterND_15) is invalid.
3.Support for 'aten::unflatten' operator when exporting to ONNX opset 这个问题好像是升级了pytorch版本解决 pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu121 发生异常: UnsupportedOperatorError Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues. File "D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\export_model\export_model.py", line 70, in torch.onnx.export( torch.onnx.errors.UnsupportedOperatorError: Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues.
具体的问题就这么多了

大佬 请教一哈。你上面提到的三点我都改了 然后export没有抱错,但是推理的时候遇到了两张图的特征点数量不匹配的情况,在fine_matching中的add1节点。请教一下你遇到过这个问题哇

你这个我好像没碰到过。也许时间节点有点久

@klein0809
Copy link

@wyf2020 @MachineEyes001 `import os os.chdir("..") from copy import deepcopy
import torch import cv2 import numpy as np import matplotlib.cm as cm from src.utils.plotting import make_matching_figure from src.loftr import LoFTR, full_default_cfg, opt_default_cfg, reparameter

You can choose model type in ['full', 'opt']

model_type = 'opt' # 'full' for best quality, 'opt' for best efficiency

You can choose numerical precision in ['fp32', 'mp', 'fp16']. 'fp16' for best efficiency

precision = 'fp32' # Enjoy near-lossless precision with Mixed Precision (MP) / FP16 computation if you have a modern GPU (recommended NVIDIA architecture >= SM_70).

You can also change the default values like thr. and npe (based on input image size)

if model_type == 'full': _default_cfg = deepcopy(full_default_cfg) elif model_type == 'opt': _default_cfg = deepcopy(opt_default_cfg)
if precision == 'mp': _default_cfg['mp'] = True elif precision == 'fp16': _default_cfg['half'] = True
print(_default_cfg) matcher = LoFTR(config=_default_cfg)
matcher.load_state_dict(torch.load(r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloftr_outdoor.ckpt")['state_dict']) matcher = reparameter(matcher) # no reparameterization will lead to low performance
if precision == 'fp16': matcher = matcher.half()
matcher = matcher.eval().cuda()

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-35.jpg" img1_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-50.jpg" img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE) img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE) img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//32_32, img0_raw.shape[0]//32_32)) # input size shuold be divisible by 32 img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//32_32, img1_raw.shape[0]//32_32))
if precision == 'fp16': img0 = torch.from_numpy(img0_raw)[None][None].half().cuda() / 255. img1 = torch.from_numpy(img1_raw)[None][None].half().cuda() / 255. else: img0 = torch.from_numpy(img0_raw)[None][None].cuda() / 255. img1 = torch.from_numpy(img1_raw)[None][None].cuda() / 255.

Inference with EfficientLoFTR and get prediction

#导出地址
eloftr_path = r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx"
dynamic_axes = { "image0": {2: "height0", 3: "width0"}, "image1": {2: "height1", 3: "width1"}, "mkpts0": {0: "points_0"}, "mkpts1": {0: "points_1"}, "mconf": {0: "nums"}, }
torch.onnx.export( matcher, (img0,img1), eloftr_path, input_names=["image0", "image1"], output_names=[ "mkpts0", "mkpts1", "mconf", ], opset_version=17, dynamic_axes=dynamic_axes, )
这是我导出的代码import numpy as np import onnxruntime as ort import cv2 import os os.chdir("..") from copy import deepcopy
import torch import cv2 import numpy as np import matplotlib.cm as cm from src.utils.plotting import make_matching_figure import sqlite3 import time trt = True

Load ONNX models

providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] if trt: providers = [ ( "TensorrtExecutionProvider", { "trt_fp16_enable": True, "trt_engine_cache_enable": True, "trt_engine_cache_path": "weights/cache", }, ) ] + providers
import matplotlib.pyplot as plt

Load example images

img0_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4254.JPG"

img1_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4255.JPG"

#3443 1591 img0_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102822_resize.jpg"
img1_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102827_resize.jpg"

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-35.jpg"

img1_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-50.jpg"

img0_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\4.jpg"

img1_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\1.jpg"

img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE) img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE)
img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//32_32, img0_raw.shape[0]//32_32)) # input size shuold be divisible by 32 img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//32_32, img1_raw.shape[0]//32_32)) input_data_0 = np.expand_dims(img0_raw, axis=0).astype(np.float32) / 255.0 input_data_1 = np.expand_dims(img1_raw, axis=0).astype(np.float32) / 255.0
eloftr_path = r'D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx' #session = ort.InferenceSession(eloftr_path)
sess_options = ort.SessionOptions() eloftr = ort.InferenceSession( eloftr_path, sess_options=sess_options, providers=providers )

将输入数据转换为 ONNX Runtime 需要的格式

input_name = eloftr.get_inputs()[0].name input_tensor_0 = np.array(input_data_0).astype(np.float32) input_tensor_1 = np.array(input_data_1).astype(np.float32)

假设 eloftr 和其他相关变量已经定义和初始化

kpts0, kpts1, mconf = ...

记录开始时间

start_time = time.time()

执行你的代码

kpts0, kpts1, mconf = eloftr.run( None, { 'image0': input_tensor_0[None], 'image1': input_tensor_1[None], })

记录结束时间

end_time = time.time()

计算总时间差

elapsed_time = end_time - start_time

打印执行时间

print(f"Elapsed time: {elapsed_time} seconds")
mkpts0 = kpts0 mkpts1 = kpts1 mconf = mconf

H, mask = cv2.findHomography(mkpts0, mkpts1, method=cv2.RANSAC, ransacReprojThreshold=10.0)

inliers_count = np.sum(mask)

total_matches = mkpts0.shape[0]

inliers_ratio = inliers_count / total_matches

print(f"inlines_ratio:{inliers_ratio},inlines_count:{inliers_count},total_matches:{total_matches}")

mask = mask.squeeze()

mkpts0 = mkpts0[mask == 1]

mkpts1 = mkpts1[mask == 1]

mconf = mconf[mask == 1]

mconf = (mconf - min(20.0, mconf.min())) / (max(30.0, mconf.max()) - min(20.0, mconf.min()))
color = cm.jet(mconf) text = [ 'LoFTR', 'Matches: {}'.format(len(mkpts0)), ] fig = make_matching_figure(img0_raw, img1_raw, mkpts0, mkpts1, color, text=text) mask = conf_matrix > self.thr mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c', **axes_lengths)mask = conf_matrix > self.thr mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c', **axes_lengths).long()mask_v, all_j_ids = mask.max(dim=2)这是测试调用的代码,c++的,就直接参考lightglue的就可以 onnx导出问题 argmax的问题,需要转换成 pytorch的max,这个地方改成 ``还有下面这个地方这里改成mask_v, all_j_ids = mask.float().max(dim=2) mask_v = mask_v.long() # Ensure mask_v is an integer tensor`
2.还有 onnx的bool值的问题,onnx 不支持 tensor[bool] nvalidGraph: [ONNXRuntimeError] : 10 : INVALID_GRAPH : Load model from T.onnx failed:This is an invalid model. Type Error: Type ‘tensor(bool)’ of input parameter (8) of operator (ScatterND) in node (ScatterND_15) is invalid.
3.Support for 'aten::unflatten' operator when exporting to ONNX opset 这个问题好像是升级了pytorch版本解决 pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu121 发生异常: UnsupportedOperatorError Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues. File "D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\export_model\export_model.py", line 70, in torch.onnx.export( torch.onnx.errors.UnsupportedOperatorError: Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues.
具体的问题就这么多了

大佬 请教一哈。你上面提到的三点我都改了 然后export没有抱错,但是推理的时候遇到了两张图的特征点数量不匹配的情况,在fine_matching中的add1节点。请教一下你遇到过这个问题哇

你这个我好像没碰到过。也许时间节点有点久

我研究了一哈。问题是model type如果是full的话,就会抱错 但opt不会 神奇

@klein0809
Copy link

@wyf2020 @MachineEyes001 `import os os.chdir("..") from copy import deepcopy
import torch import cv2 import numpy as np import matplotlib.cm as cm from src.utils.plotting import make_matching_figure from src.loftr import LoFTR, full_default_cfg, opt_default_cfg, reparameter

You can choose model type in ['full', 'opt']

model_type = 'opt' # 'full' for best quality, 'opt' for best efficiency

You can choose numerical precision in ['fp32', 'mp', 'fp16']. 'fp16' for best efficiency

precision = 'fp32' # Enjoy near-lossless precision with Mixed Precision (MP) / FP16 computation if you have a modern GPU (recommended NVIDIA architecture >= SM_70).

You can also change the default values like thr. and npe (based on input image size)

if model_type == 'full': _default_cfg = deepcopy(full_default_cfg) elif model_type == 'opt': _default_cfg = deepcopy(opt_default_cfg)
if precision == 'mp': _default_cfg['mp'] = True elif precision == 'fp16': _default_cfg['half'] = True
print(_default_cfg) matcher = LoFTR(config=_default_cfg)
matcher.load_state_dict(torch.load(r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloftr_outdoor.ckpt")['state_dict']) matcher = reparameter(matcher) # no reparameterization will lead to low performance
if precision == 'fp16': matcher = matcher.half()
matcher = matcher.eval().cuda()

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-35.jpg" img1_pth = r"D:\ImagesStitchCode\test2\Snipaste_2024-07-18_14-57-50.jpg" img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE) img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE) img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//32_32, img0_raw.shape[0]//32_32)) # input size shuold be divisible by 32 img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//32_32, img1_raw.shape[0]//32_32))
if precision == 'fp16': img0 = torch.from_numpy(img0_raw)[None][None].half().cuda() / 255. img1 = torch.from_numpy(img1_raw)[None][None].half().cuda() / 255. else: img0 = torch.from_numpy(img0_raw)[None][None].cuda() / 255. img1 = torch.from_numpy(img1_raw)[None][None].cuda() / 255.

Inference with EfficientLoFTR and get prediction

#导出地址
eloftr_path = r"D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx"
dynamic_axes = { "image0": {2: "height0", 3: "width0"}, "image1": {2: "height1", 3: "width1"}, "mkpts0": {0: "points_0"}, "mkpts1": {0: "points_1"}, "mconf": {0: "nums"}, }
torch.onnx.export( matcher, (img0,img1), eloftr_path, input_names=["image0", "image1"], output_names=[ "mkpts0", "mkpts1", "mconf", ], opset_version=17, dynamic_axes=dynamic_axes, )
这是我导出的代码import numpy as np import onnxruntime as ort import cv2 import os os.chdir("..") from copy import deepcopy
import torch import cv2 import numpy as np import matplotlib.cm as cm from src.utils.plotting import make_matching_figure import sqlite3 import time trt = True

Load ONNX models

providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] if trt: providers = [ ( "TensorrtExecutionProvider", { "trt_fp16_enable": True, "trt_engine_cache_enable": True, "trt_engine_cache_path": "weights/cache", }, ) ] + providers
import matplotlib.pyplot as plt

Load example images

img0_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4254.JPG"

img1_pth = r"D:\ImagesStitchCode\Image8\image8_resized\DSC_4255.JPG"

#3443 1591 img0_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102822_resize.jpg"
img1_pth = r"D:\ImagesStitchCode\test_home_outdoor\resize\20240813102827_resize.jpg"

Load example images

img0_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-35.jpg"

img1_pth = r"D:\ImagesStitchCode\test2\resized_Snipaste_2024-07-18_14-57-50.jpg"

img0_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\4.jpg"

img1_pth = r"D:\jx\ai\featue_match\dataset\seach_dataset\uav\test_database\1.jpg"

img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE) img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE)
img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//32_32, img0_raw.shape[0]//32_32)) # input size shuold be divisible by 32 img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//32_32, img1_raw.shape[0]//32_32)) input_data_0 = np.expand_dims(img0_raw, axis=0).astype(np.float32) / 255.0 input_data_1 = np.expand_dims(img1_raw, axis=0).astype(np.float32) / 255.0
eloftr_path = r'D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\weights\eloft_size_.onnx' #session = ort.InferenceSession(eloftr_path)
sess_options = ort.SessionOptions() eloftr = ort.InferenceSession( eloftr_path, sess_options=sess_options, providers=providers )

将输入数据转换为 ONNX Runtime 需要的格式

input_name = eloftr.get_inputs()[0].name input_tensor_0 = np.array(input_data_0).astype(np.float32) input_tensor_1 = np.array(input_data_1).astype(np.float32)

假设 eloftr 和其他相关变量已经定义和初始化

kpts0, kpts1, mconf = ...

记录开始时间

start_time = time.time()

执行你的代码

kpts0, kpts1, mconf = eloftr.run( None, { 'image0': input_tensor_0[None], 'image1': input_tensor_1[None], })

记录结束时间

end_time = time.time()

计算总时间差

elapsed_time = end_time - start_time

打印执行时间

print(f"Elapsed time: {elapsed_time} seconds")
mkpts0 = kpts0 mkpts1 = kpts1 mconf = mconf

H, mask = cv2.findHomography(mkpts0, mkpts1, method=cv2.RANSAC, ransacReprojThreshold=10.0)

inliers_count = np.sum(mask)

total_matches = mkpts0.shape[0]

inliers_ratio = inliers_count / total_matches

print(f"inlines_ratio:{inliers_ratio},inlines_count:{inliers_count},total_matches:{total_matches}")

mask = mask.squeeze()

mkpts0 = mkpts0[mask == 1]

mkpts1 = mkpts1[mask == 1]

mconf = mconf[mask == 1]

mconf = (mconf - min(20.0, mconf.min())) / (max(30.0, mconf.max()) - min(20.0, mconf.min()))
color = cm.jet(mconf) text = [ 'LoFTR', 'Matches: {}'.format(len(mkpts0)), ] fig = make_matching_figure(img0_raw, img1_raw, mkpts0, mkpts1, color, text=text) mask = conf_matrix > self.thr mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c', **axes_lengths)mask = conf_matrix > self.thr mask = rearrange(mask, 'b (h0c w0c) (h1c w1c) -> b h0c w0c h1c w1c', **axes_lengths).long()mask_v, all_j_ids = mask.max(dim=2)这是测试调用的代码,c++的,就直接参考lightglue的就可以 onnx导出问题 argmax的问题,需要转换成 pytorch的max,这个地方改成 ``还有下面这个地方这里改成mask_v, all_j_ids = mask.float().max(dim=2) mask_v = mask_v.long() # Ensure mask_v is an integer tensor`
2.还有 onnx的bool值的问题,onnx 不支持 tensor[bool] nvalidGraph: [ONNXRuntimeError] : 10 : INVALID_GRAPH : Load model from T.onnx failed:This is an invalid model. Type Error: Type ‘tensor(bool)’ of input parameter (8) of operator (ScatterND) in node (ScatterND_15) is invalid.
3.Support for 'aten::unflatten' operator when exporting to ONNX opset 这个问题好像是升级了pytorch版本解决 pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu121 发生异常: UnsupportedOperatorError Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues. File "D:\jx\ai\model2cpp\models\EfficientLoFTR-main\EfficientLoFTR-main\export_model\export_model.py", line 70, in torch.onnx.export( torch.onnx.errors.UnsupportedOperatorError: Exporting the operator 'aten::unflatten' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues.
具体的问题就这么多了

大佬 请教一哈。你上面提到的三点我都改了 然后export没有抱错,但是推理的时候遇到了两张图的特征点数量不匹配的情况,在fine_matching中的add1节点。请教一下你遇到过这个问题哇

你这个我好像没碰到过。也许时间节点有点久

大佬 你在onnx gpu推理的时候 速度有没有比pytorch慢很多

@jxhoh
Copy link
Author

jxhoh commented Nov 5, 2024

大佬 请教一哈。你上面提到的三点我都改了 然后export没有抱错,但是推理的时候遇到了两张图的特征点数量不匹配的情况,在fine_matching中的add1节点。请教一下你遇到过这个问题哇

你这个我好像没碰到过。也许时间节点有点久

大佬 你在onnx gpu推理的时候 速度有没有比pytorch慢很多
我好像是这样的,pythontorch好像很快,我用c++调用反而慢了很多
所以我在导出 这个方面也没搞明白,我感觉也不是特别好的方法这样,onnx,我感觉最终是不是要上tesorrt

@jxhoh
Copy link
Author

jxhoh commented Nov 5, 2024

我好像是这样的,pythontorch好像很快,我用c++调用反而慢了很多
所以我在导出 这个方面也没搞明白,我感觉也不是特别好的方法这样,onnx,我感觉最终是不是要上tesorrt

我好像是这样的,pythontorch好像很快,我用c++调用反而慢了很多
所以我在导出 这个方面也没搞明白,我感觉也不是特别好的方法这样,onnx,我感觉最终是不是要上tesorrt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants