pytorch模型转ncnn,并移植android,ios

模型转换

pytorch转onnx,并用onnxruntime验证模型转换是否正确

import torch.utils.data
from torch.autograd import Variable
from squeezenet import squeezenet1_2
import onnxruntime
import numpy as np
from onnxruntime.datasets import get_example
import cv2
import  onnx
model_file = '/home/bbt/qinghua/detetion/pytorch-mobilenet/model/model_best_squeezenet1_2_age0.926.pth.tar'
num_class =3
# create model
model=squeezenet1_2(pretrained=False,num_classes=num_class)
model = torch.nn.DataParallel(model)
checkpoint = torch.load(model_file)
model.load_state_dict(checkpoint['state_dict'])
model.to('cpu')
model.eval()
input=cv2.imread('/home/bbt/age00.jpg')
input=cv2.resize(input,(224,224))
input=np.transpose(input, (2, 0, 1)).astype(np.float32)
now_image1 = Variable(torch.from_numpy(input))
dummy_input = now_image1.unsqueeze(0)
input_names=['input']
output_names=['output']
torch_out = torch.onnx._export(model.module, dummy_input, "/home/bbt/qinghua/detetion/pytorch-mobilenet/model/age.onnx",verbose=True, input_names=input_names, output_names=output_names)
#test onnx model
example_model = get_example('/home/bbt/qinghua/detetion/pytorch-mobilenet/model/age.onnx')
sess = onnxruntime.InferenceSession(example_model)
result = sess.run([output_name], {input_name: dummy_input.data.numpy()})
np.testing.assert_almost_equal(torch_out.data.cpu().numpy(), result[0], decimal=3)
print(result[0])

转换后的模型保存在age.onnx,还需要对age.onnx模型进行简化,

python -m onnxsim age.onnx age-sim.onnx

得到age-sim.onnx文件,后续转ncnn模型使用这个。

onnx模型转ncnn

编译ncnn:

1.编译本地ncnn

git clone https://github.com/Tencent/ncnn.git

cd ncnn

mkdir -p build

cd build

cmake …

make -j4

编译后,在目录ncnn/build/tools/caffe下,分别有ncnn2mem和caffe2ncnn两个可执行文件:

  • caffe2ncnn 将caffemodel转换为ncnnmodel
  • ncnn2mem 对模型进行加密操作

模型转换:

./onnx2ncnn age-sim.onnx age.param age.bin

模型加密:

./ncnn2mem age.param age.bin age.id.h age.men.h

会生成aeg.param.bin, age.id.h, age.mem.h。

android移植

新建android-ncnn工程,可以参考https://blog.csdn.net/qq_33431368/article/details/85009758。

或者直接下载编译好的工程,https://github.com/chehongshu/ncnnforandroid_objectiondetection_Mobilenetssd/tree/master/MobileNetSSD_demo_single,我们以这个工程为例,直接修改为自己的模型。

首先将自己的模型文件age.param.bin,age.bin,标签文件label.txt(每行对应标签名) 拷贝到ncnnforandroid_objectiondetection_Mobilenetssd/MobileNetSSD_demo_single/app/src/main/asset/.

将age.id.h文件拷贝到ncnnforandroid_objectiondetection_Mobilenetssd/MobileNetSSD_demo_single/app/src/main/cpp/

修改ncnnforandroid_objectiondetection_Mobilenetssd/MobileNetSSD_demo_single/app/src/main/cpp/MobileNetssd.cpp

文件:

修改include “MobileNetSSD_deploy.id.h” 为include “age.id.h”

a.输入:

由于我的输入图片是直接cv2.imread(‘tupian.jpg’),读取的为bgr格式,因此修改输入为,

in = ncnn::Mat::from_pixels((const unsigned char*)indata, ncnn::Mat::PIXEL_RGBA2BGR, width, height);

由于我没有归一化,注释掉一下行,

const float mean_vals[3] = {127.5f, 127.5f, 127.5f}; const float scale[3] = {0.007843f, 0.007843f, 0.007843f}; in.substract_mean_normalize(mean_vals, scale);// 归一化

b.模型输入、输出名修改

如果不修改正确 int ret = ncnn_net.load_param((const unsigned char *) ncnn_param);返回值ret=0;
按照age.id.h的输入,输出名,修改输入输出,

// 如果不加密是使用ex.input(“data”, in);

// BLOB_data在id.h文件中可见,相当于datainput网络层的id

ex.input(age_param_id::BLOB_input, in);

// 如果时不加密是使用ex.extract(“prob”, out);

//BLOB_detection_out.h文件中可见,相当于dataout网络层的id,输出检测的结果数据

ex.extract(age_param_id::BLOB_output, out);

到此,模型可以正常预测了。

参考:

输入问题:https://github.com/Tencent/ncnn/wiki/FAQ-ncnn-produce-wrong-result

参考:https://blog.csdn.net/qq_33431368/article/details/85009758

你可能感兴趣的:(torch学习笔记,深度学习)