Qt ncnn Android部署模型记录

23 篇文章 2 订阅
5 篇文章 0 订阅

现在有很多模型部署框架了,综合考虑易用性,性能,支持模型转换的类型,成熟程度,考虑使用ncnn进行模型部署。
ncnn开源地址:https://github.com/Tencent/ncnn
这里我使用pytorch训练好的PSENet模型进行部署。

正文

官方pytorch转ncnn说明文档

转换流程如下:
pytorch训练->onnx->onnx-simplifier->ncnn

1. pytorch训练->onnx

注意如果模型中没有sigmoid,而是在后处理中用它,导出onnx时需要在Module里加入sigmoid
注意如果有interpolate操作,align_corners参数设置为False

转换代码如下:

def torch2onnx(model, save_path):
    """
    :param model:
    :param save_path:  XXX/XXX.onnx
    :return:
    """
    model.eval()
    data = torch.rand(1, 3, 224, 224)
    input_names = ["input"]   #ncnn需要
    output_names = ["out"]  #ncnn需要
    torch.onnx._export(model, data, save_path, export_params=True, opset_version=11, input_names=input_names, output_names=output_names)
    print("torch2onnx finish.")

在这里插入图片描述

2. onnx->onnx-simplifier
2.1 安装onnx-simplifier

pip install onnx-simplifier

2.2 输入命令转换模型

python -m onnxsim pse.onnx pse_sim.onnx

得到以下结果:
在这里插入图片描述
在这里插入图片描述

3. onnx-simplifier->ncnn
(这一步不想在本地自己编译的话,可以使用官方提供的在线转换工具)

3.1 下载安装protobuf

这一步我花了挺长时间的,刚开始在windows编译protobuf,现在cmake-gui中进行cmake,然后打开我的VS2013,然后发现protobuf需要c++11,但是VS2013里没有找到可以设置c++11的地方,于是放弃,转到ubuntu。

在ubuntu中安装:

./configure
 make
 make check
 sudo make install
 sudo ldconfig # refresh shared library cache.

3.2 下载ncnn源码,在ncnn/tools/onnx目录下,进行make,即

mkdir build
cd build 
cmake ..
make

如果make时报一大堆错,大概如下:

 error: ‘uint8’ does not name a type
error: ‘uint64’ has not been declared
error: ‘uint32’ has not been declared
 error: ‘Cur’ was not declared in this scope

打开这里的CMakeLists.txt文件,加如以下这一句。然后重新cmake,make,通过。

add_compile_options(-std=c++11)

看到build文件夹里有了一个onnx2ncnn可执行文件。
把之前转换得到的onnx模型文件放到这里,输入以下命令进行格式转换:

./onnx2ncnn pse_sim.onnx pse_sim.param pse_sim.bin

得到以下文件:
在这里插入图片描述

4. 在pro中添加相应的ncnn库
ncnn编译

  1. 用较低版本NDK编译失败,亲测用r15c可以,如果需要vulkan,需要ndk18以上,但是18以上不支持gcc了,默认clang
  2. 较低版本Qt用gcc,高版本用clang,因此高版本应当可以直接用官方公布的最新的编译好的库,用不了的话再自己编译

D:\android-ndk-r15c\build\cmake\android.toolchain.cmake文件,把415行的-g这行去掉(删除debug编译参数,缩小二进制体积)。

cmake参数:-DANDROID_TOOLCHAIN=gcc是设置gcc编译,不设置这一项的话默认为clang,但是Qt默认是gcc的 (这项参数是我阅读NDK的android.toolchain.cmake文件代码发现的,吐血。。。)

编译ncnn:
如果cmake时报以下错:

 CMAKE_SYSTEM_NAME is 'Android' but 'NVIDIA Nsight Tegra Visual Studio
 Edition' is not installed.

添加这一项参数试试-G "Unix Makefiles"

如果cmake时报以下错:

CMake Error: CMake was unable to find a build program corresponding to "Unix Mak
efiles".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a differen
t build tool.

cmake时添加这一项-DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%/prebuilt/windows-x86_64/bin/make.exe"

完整的过程如下:
带vulkan编译详见:Qt ncnn Windows编译

mkdir build-android
cd build-android
set ANDROID_NDK=D:\android-ndk-r15c

cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK%/build/cmake/android.toolchain.cmake -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%/prebuilt/windows-x86_64/bin/make.exe" -DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON -DANDROID_PLATFORM=android-23 -DANDROID_TOOLCHAIN=gcc ..

make 或者 D:\Qt5\Tools\mingw730_32\bin\mingw32-make.exe

make install

-DANDROID_ABI=“armeabi-v7a"或"arm64-v8a”
(make可以用Qt安装目录下,Tools/mingw730_32/bin里面的mingw32-make.exe)
过程如图:
在这里插入图片描述
编译完成的库就在install文件夹里了
在Qt的pro中正常加入库和头文件路径就行了。添加库后,先弄一个简单的测试程序,通过之后再把模型相关代码加进去。

如果需要opencv-android,直接在opencv的release页面下载编译好的即可。

5. 量化
quantize说明文档在这里
优化工具在ncnn/tools/quantize里面,直接在这里cmake和make的话会报错fatal error: layer.h: 没有那个文件或目录。要在ncnn根目录创建build目录然后cmake,make。
得到以下文件:
在这里插入图片描述
这里出现了可执行文件ncnnoptimize,然后把前面得到的两个文件放到这里,输入以下命令进行转换:

./ncnnoptimize pse_sim.param pse_sim.bin pse_sim_opt.param pse_sim_opt.bin 65536

这里的最后一项参数是指存储类型。
这个issue里说65536对应fp32, 输入其他对应fp16。但是从得到的文件大小来看,是相反的?
在这里插入图片描述

6. 在Qt中使用模型文件
6.1 pro中要加入openmp(不加编译报错)

QMAKE_CXXFLAGS += -fopenmp
QMAKE_LFLAGS += -fopenmp
LIBS += -fopenmp -lgomp

6.2 如果编译报错:(当前Qt中用gcc,但是ncnn库是clang,需要编译一下ncnn,见第4节)

undefined reference to '__kmpc_fork_call'
undefined reference to '__kmpc_for_static_init_4'
undefined reference to '__kmpc_push_num_threads'
undefined reference to '__kmpc_for_static_init_8'

6.3 如果报错:

undefined reference to 'stderr' 

试试提高API版本,比如API23。
或者尝试在代码里加一行:

undef stderr

6.4 编译通过后。模型文件(param和bin放到pro同级目录下),通过pro传到assets目录中,打包到apk,在程序运行时把模型文件拷到本地。这个操作可以看我之前的博客:Qt将资源通过assets打包进apkQt+opencv部署深度学习模型到windows与android

6.5 按照ncnn文档中的例子调用模型即可。

6.6 pytorch中上采样操作的Size是需要根据数据变化的,但是转为ncnn的param文件中Interp记录的是固定值,对于这个问题我想着一个解决方法是部署时把输入图resize到一个固定尺寸,然后手动修改param文件中Interp里面的尺寸到对应的值。
在这里插入图片描述
另一种方式是看到chineseocr_lite的处理方式,是把输入图片resize到一个正好可以被网络中所有上/下采样倍率整除的尺寸,然后修改param文件的缩放倍率,去掉最后两项(长宽的固定值)。
在这里插入图片描述

6.7 如果模型推理过程中报以下错:

 Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x12600000 in tid 25119

把输入图片尺寸减小试试。

7. 结果展示
虽然检测效果不佳(手机上不能把图片resize太大,之前长边是到2240的,但是在我的手机上最多长边到800),但是先把整个流程先跑通,精度和速度后面再继续优化就行了。
在这里插入图片描述
在这里插入图片描述
换成到chineseocr_lite提供的mobilenet模型之后,如下图,效果更好一些,而且可以检测汉字:
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值