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

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

你可能感兴趣的:(深度学习)