您的位置:首页 > 其它

深度学习【19】ncnn安卓搭建并使用自己的模型

2017-09-15 10:03 615 查看

ncnn安卓搭建并使用自己的模型

github上面已经给了一个ncnn的安卓例子,地址:https://github.com/dangbo/ncnn-mobile

clone 这个项目后用Android studio就可以打开(12.19更新:这个项目已经更改,不能直接运行,需要自己编译ncnn,然后更改ncnn-mobile/squeezencnn-AS/app/src/main/jni/Android.mk中的ncnn安装路径)。

使用自己的模型

我这边的例子是caffe转ncnn,然后ncnn转memery。

以alexnet为例。

1、首先下载caffe模型,

deploy.prototxt: https://github.com/BVLC/caffe/tree/master/models/bvlc_alexnet caffemodel:http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel


2、因为这个alexnet的caffe版本比较老,ncnn不支持。需要用caffe自带的转换工具,转成最新的caffe版本。用一下两个命令(这两个命令,需要安装最新的caffe):

upgrade_net_proto_text [老prototxt] [新prototxt]
upgrade_net_proto_binary [老caffemodel] [新caffemodel]


3、在deploy.prototxt中将caffe的输入层改成input层:

layer {
name: "data"
type: "Input"
top: "data"
input_param { shape: { dim: 1 dim: 3 dim: 227 dim: 227 } }
}


4、用caffe2ncnn将caffe版本alexnet转成ncnn的

caffe2ncnn deploy.prototxt bvlc_alexnet.caffemodel alexnet.param alexnet.bin


5、用ncnn2mem将ncnn的alexnet的param和bin文件,转成嵌入代码的形式,并生成安卓demo中的param.bin文件

ncnn2mem alexnet.param alexnet.bin alexnet.id.h alexnet.mem.h


这时候会额外生成alexnet.param.bin文件

6、将生成的alexnet.param.bin和alexnet.bin文件拷贝到ncnn安卓工程的assets文件夹中。并在MainActivity.java中的initSqueezeNcnn函数中读取param.bin文件和bin文件相关代码改成读取alexnet.param.bin和alexnet.bin(可能你还要修改一下输入图像的大小)

{
InputStream assetsInputStream = getAssets().open("alexnet.param.bin");
int available = assetsInputStream.available();
param = new byte[available];
int byteCode = assetsInputStream.read(param);
assetsInputStream.close();
}
{
InputStream assetsInputStream = getAssets().open("alexnet.bin");
int available = assetsInputStream.available();
bin = new byte[available];
int byteCode = assetsInputStream.read(bin);
assetsInputStream.close();
}


7、在之前生成的alexnet.id.h中查看输入层ID和想要抽取的层的ID,或者用alexnet.id.h替换掉squeezenet_v1.1.id.h,使用安卓工程中的例子获取输入层ID和抽取层ID(注意:这个ID是BLOB的ID不是LAYER的ID)。

例如我要抽取最后一层的数据,从alexnet.id.h中可知,输入层为BLOB_data=0,最后一层为BLOB_prob=23。

与安卓工程相似的写法:

ex.input(alexnet_param_id::BLOB_data, in);
ex.extract(alexnet_param_id::BLOB_prob, out);


直接写id:

ex.input(0, in);
ex.extract(23, out);


最后需要注意的是:

由于ncnn的数据对齐,你可能会发现抽取出来的数据不对,特别要抽取中间层的时候。那么请使用ncnn中Mat的reshape函数,reshape一下就可以了。

ncnn::Mat out1(out.reshape(w * h * c));//w,h,c:要抽取层的w,h和channel
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐