pytorch模型转NCNN模型在手机部署
记录一下自己的转换过程,中间也踩了很多坑。。
第一步, pytorch转onnx
这一步比较方便,pyroch自身就支持,注意input和output_names一定要填写正确。
net = torch.load("./model17_4.pkl")
net.eval()
test_arr = np.random.rand(1, 3, 400, 400)
dummy_input = torch.Tensor(test_arr).cuda()
# print(dummy_input.shape)
# d = dummy_input.permute(0, 3, 1, 2)
# print(d.shape)
input_names = ["input"]
output_names = ["output"]
torch.onnx.export(net,
dummy_input,
"mobilenet_v7_2.onnx",
export_params=True,
do_constant_folding=True,
input_names=input_names,
output_names=output_names)
得到onnx模型后,还可以写代码验证一下效果:
TF_PATH = "tf_model6" # where the representation of tensorflow model will be stored
ONNX_PATH = "mobilenet_v7_2.onnx" # path to my existing ONNX model
onnx_model = onnx.load(ONNX_PATH) # load onnx model
tf_rep = prepare(onnx_model) # creating TensorflowRep object
tf_rep.export_graph(TF_PATH)
#test tensorflow mode
img = cv2.imread('./data/000701.jpg')[:,:,::-1]
#img = img[850:1250,850:1250]
img = (np.transpose(img, (2, 0, 1)) - 128.) / 128.
#img = torch.from_numpy(img).unsqueeze(0).float()
#input = img.numpy()
input = tf.expand_dims(img, 0).numpy()
output = tf_rep.run(input) # run the loaded model
res = output.output[0]
res = np.clip(res, 0, 1)
im = np.array(res*255, dtype=np.uint8)
im1 = np.transpose(im, (1, 2, 0))[:,:,::-1]
cv2.imwrite('./test/out.bmp', im1)
第二步,将onnx模型转换为ncnn模型
这个参考了这篇文章,还不错https://zhuanlan.zhihu.com/p/137458205
先到github下载最新的ncnn库,然后编译。注意需要安装opencv和protobuf,否则编译ncnn会不完整或者有异常。
编译成功后,会在build/tools/目录下生成onnx和quantize等文件夹,
cd进入onnx文件夹,把上一步生成的.onnx文件拷贝过来,
先简化模型:
python3 -m onnxsim mobilenet_v7_2.onnx mobilenet_v7_2.onnx-sim.onnx
再运行
./onnx2ncnn mobilenet_v7_2.onnx-sim.onnx model.param model.bin
生成的.bin与.param文件就是我们在安卓上需要使用的NCNN模型文件
第三步,在手机上加载运行ncnn模型
ncnn::Net net;
//net.opt.num_threads=1;
net.load_param("./model.param");
net.load_model("./model.bin");
// 把opencv的mat转换成ncnn的mat
ncnn::Mat input = ncnn::Mat::from_pixels(img2.data, ncnn::Mat::PIXEL_BGR, img2.cols, img2.rows);
const float mean_vals[3] = { 128.f,128.f,128.f };
const float norm_vals[3] = { 1 / 128.f,1 / 128.f,1 / 128.f };
input.substract_mean_normalize(mean_vals, norm_vals);
// ncnn前向计算
ncnn::Extractor extractor = net.create_extractor();
extractor.input("input", input);
ncnn::Mat m, output1;//取决于模型的输出有几个
clock_t start_time = clock();
extractor.extract("output", output1);
最后,再记录一下我的相关软件版本,注意onnx-tf的版本不能太低:
tensorflow-gpu 2.8.0
onnx 1.6.0
onnx-tf 1.6.0
libprotoc 3.5.0
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构