最近项目用到onnx,对onnx内容进行总结,每一种都是测过可行,可以根据对应情况修改对应内容。
#双输入,单输出
import torch.onnx
#根据模型图片输入设定input的h和w的尺寸大小,我是512
input = (torch.randn([1,3,512,512]).cuda(), torch.randn([1,3,512,512]).cuda())
input_names = ['input_1', 'input_2']
output_names = ['output']
weight_path = './onnx/*****.pt'
model=torch.load(weight_path)
model = model.cuda()
model.eval()
print('load model over')
torch.onnx.export(model,
args=input,
f = './onnx/*****.onnx',
opset_version=11,
input_names=input_names,
output_names=output_names
)
print('to onnx success!')
import torch.onnx
from model.siamunet_diff.SiamUNet_Diff import SiamUnet_diff #根据自己模型定义
####转换onnx####
input = (torch.randn([1,3,512,512]).cuda(), torch.randn([1,3,512,512]).cuda())
input_names = ['input_1', 'input_2']
output_names = ['output']
weight_path = '/home/*****.pth'
model = SiamUnet_diff(input_nbr=3, label_nbr=2).cuda()#根据自己模型定义
model.load_state_dict(torch.load(weight_path))
model.eval()#固定住dropout、 batchnorm
print('load model over')
torch.onnx.export(model,
args=input,
f = '/home/CropLand-CD/onnx/simen_unet.onnx',
opset_version=11,
input_names=input_names,
output_names=output_names)
print('to onnx success!')
from model.siamunet_diff.SiamUNet_Diff import SiamUnet_diff #根据自己模型定义
input = (torch.randn([1,3,512,512]).cuda(), torch.randn([1,3,512,512]).cuda())
#多输入多输出,若设置单输入,删减names内容即可
input_names = ['input_1', 'input_2']
output_names = ['output_1','output_2','output_3']
import torch.nn as nn
weight_path = '/home/******.pth'
model = SiamUnet_diff(input_nbr=3, label_nbr=2).cuda()
model.load_state_dict(torch.load(weight_path))
# model = nn.DataParallel(model).cuda() #如果多显卡训练需要加这个
model.eval()
print('load model over')
#可以定义动态宽高
# dynamic_axes = {'input_1': {0: 'batch_size', 1: 'channel', 2: 'height', 3: 'width'},
# 'input_2': {0: 'batch_size', 1: 'channel', 2: 'height', 3: 'width'},
# 'output_1': {0: 'batch_size', 1: 'channel', 2: 'height', 3: 'width'},
# 'output_2': {0: 'batch_size', 1: 'channel', 2: 'height', 3: 'width'},
# 'output_3': {0: 'batch_size', 1: 'channel', 2: 'height', 3: 'width'}}
#
dynamic_axes = {'input_1': {0: 'batch_size'},
'input_2': {0: 'batch_size'},
'output_1': {0: 'batch_size'},
'output_2': {0: 'batch_size'},
'output_3': {0: 'batch_size'}}
torch.onnx.export(model,
args=input,
f = '/home/CropLand-CD/onnx/simen_unet.onnx',
opset_version=11,
input_names=input_names,
output_names=output_names,
dynamic_axes = dynamic_axes)
print('to onnx success!')
###双输入图片测试
import onnxruntime as ort
import cv2
import numpy as np
from PIL import Image
def to_numpy(tensor):
return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()
def resize_img_2(path, size=(512,512)):
img = Image.open(path)
img = img.resize(size)
img = np.asarray(img, dtype='float32')
img = np.expand_dims(img.transpose(2, 0, 1), axis=0)
# print('img', img.shape)
return img
# 读取图片
path1 = './**/1.png'
path2 = './**/2.png'
img1 = resize_img_2(path1)
img2 = resize_img_2(path2)
# 加载 onnx
from onnxruntime.datasets import get_example
onnx_model = get_example(r'/home/*****.onnx')#一定要绝对路径
sess = ort.InferenceSession(onnx_model,providers=['CUDAExecutionProvider']) # 'CPUExecutionProvider'
input_name_1 = sess.get_inputs()[0].name
input_name_2 = sess.get_inputs()[1].name
outputs = sess.run(None, {input_name_1:img1, input_name_2:img2})
file_path = './result/'
cv2.imwrite(file_path + '******.png', outputs) #保存图片
print('success!')
#测试转换模型是否有问题#
import onnx
onnx_path = './onnx/******.onnx'
onnx_model = onnx.load(onnx_path)
check = onnx.checker.check_model(onnx_model)
print('check', check)
check 为 none 则正常
import onnxruntime
import numpy as np
from onnxruntime.datasets import get_example
import torch
from model.CDNET import CDNET #根据自己模型定义
def to_numpy(tensor):
return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()
model = CDNet(n_class=2,img_size=512).cuda()
checkpoint = torch.load('/home/CropLand-CD/onnx/*****.pth')
# model = nn.DataParallel(model).cuda() #如果用了多张显卡训练
model.load_state_dict(checkpoint)
# 得到torch模型的输出
dummy_input = torch.randn(1, 3, 512, 512)
dummy_input_2 = torch.randn(1, 3, 512, 512)
model.eval()
with torch.no_grad():
torch_out = model(dummy_input,dummy_input_2)
# 得到onnx模型的输出
onnx_model = get_example(r'/home/*****.onnx') # 要写绝对路径
sess = onnxruntime.InferenceSession(onnx_model, providers=['CUDAExecutionProvider'])
# sess = ort.InferenceSession(onnx_path,providers=['CUDAExecutionProvider']) # 'CPUExecutionProvider'
input_name_1 = sess.get_inputs()[0].name
input_name_2 = sess.get_inputs()[1].name
onnx_out = sess.run(None, {input_name_1:to_numpy(dummy_input), input_name_2:to_numpy(dummy_input_2)})
# 判断输出结果是否一致,小数点后3位一致即可
print(np.testing.assert_almost_equal(to_numpy(torch_out), onnx_out, decimal=3))
from model.network import CDNet
from torchsummary import summary
import torch
net = CDNet().cuda()
summary(net, input_size = [(3,512,512),(3,512,512)])
####两个输入,单输入对应删减####