caffe 的网络和模型通常是搞深度学习的研究者训练出来的,一般来说训练完会有
train.prototxt
deploy.prototxt
snapshot_10000.caffemodel
部署的时候只需要 TEST 过程,所以有 deploy.prototxt 和 caffemodel 就足够了
alexnet 的 deploy.prototxt 可以在这里下载 https://github.com/BVLC/caffe/tree/master/models/bvlc_alexnet
alexnet 的 caffemodel 可以在这里下载 http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel
caffe 自带了工具可以把老版本的 caffe 网络和模型转换为新版(ncnn的工具只认识新版),这里介绍一种比较笨但是比较快捷的方法:
首先将你需要转换的prototxt和caffemodel放在你电脑的caffe/build/tools目录下,然后终端进入caffe/build/tools,执行命令:
./upgrade_net_proto_text old_deploy.prototxt new_deploy.prototxt
./upgrade_net_proto_binary old.caffemodel new.caffemodel
执行完成之后你就可以在caffe/build/tools下找到你的new_deploy.prototxt和new.caffemodel文件了。
注意完成之后打开你的new_deploy.prototxt文件看一下,因为一般每次只需要做一个数据样本的识别,所以如果第一个 dim 不为1,要将其设为 1,类似于这样:
layer {
name: "data"
type: "Input"
top: "data"
input_param { shape: { dim: 1 dim: 3 dim: 227 dim: 227 } }
}
使用 caffe2ncnn 工具转换为 ncnn 的网络描述和模型
终端进入ncnn/build/toos/caffe(需要提前把上面转化的new_deploy.prototxt和new.caffemodel放到ncnn/build/tools/caffe下),执行如下命令:
caffe2ncnn new_deploy.prototxt new.caffemodel demo.param demo.bin
执行完成之后在ncnn/build/tools下就可以看到生成的param和bin文件了,文件名你可以根据你的需要设置。
去除可见字符串(可选)
用nihui大神的原文介绍:
有 param 和 bin 文件其实已经可以用了,但是 param 描述文件是明文的,如果放在 APP 分发出去容易被窥探到网络结构(说得好像不明文就看不到一样 使用 ncnn2mem 工具转换为二进制描述文件和内存模型,生成 alexnet.param.bin 和两个静态数组的代码文件:
ncnn2mem demo.param demo.bin demo.id.h demo.mem.h
我下面的所有使用为了方便都使用的是没有去除可见字符串的param和bin,如果你有去除可见字符串的需求,可以在ncnn的examples中找到相应去除了可见字符串文件的使用方法。
实现在电脑上使用ncnn
编写代码
使用你喜欢的编辑器编写c语言代码,我这里不做过多语言介绍,直接给一个demo代码,我会在代码中给出关键代码的注释(保证你认真看完代码和注释就会懂ncnn的大概原理),请大家从main函数入口开始阅读,相信更多的读者喜欢这种直接show code的方式:
#include
#include
#include
#include"gesture.id.h"
#include "net.h"
//使用ncnn,传入的参数第一个是你需要预测的数据,第二个参数是各个类别的得分vector,注意传入的是地址,这样才能在这个函数中改变其值
static int detect_squeezenet( float *data, std::vector& cls_scores)
{
//实例化ncnn:Net,注意include "net.h",不要在意这时候因为找不到net.h文件而include报错,后文会介绍正确的打开方式
ncnn::Net squeezenet;
//加载二进制文件,也是照写,后面会介绍对应文件应该放的正确位置
int a=squeezenet.load_param("demo.param");
int b=squeezenet.load_param_bin("demo.bin");
//实例化Mat,前三个参数是维度,第四个参数是传入的data,维度的设置根据你自己的数据进行设置,顺序是w、h、c
ncnn::Mat in = ncnn::Mat(550, 8, 2, data);
//实例化Extractor
ncnn::Extractor ex = squeezenet.create_extractor();
ex.set_light_mode(true);
//注意把"data"换成你deploy中的数据层名字
int d= ex.input("data", in);
ncnn::Mat out;
//这里是真正的终点,不多说了,只能仰天膜拜nihui大牛,重点是将prob换成你deploy中最后一层的名字
int c=ex.extract("prob", out);
//将out中的值转化为我们的cls_scores,这样就可以返回不同类别的得分了
cls_scores.resize(out.w);
for (int j=0; j cls_scores;//用来存储最终各类别的得分
//这个函数的实现在上面,快去看
detect_squeezenet(data, cls_scores);
for (int i = 0; i < cls_scores.size(); ++i)
{
printf("%c : %f\n", a[i],cls_scores[i]);
}
return 0;
}
代码中我展示了最简单的ncnn使用场景,你可以根据自己的需要加入不同的其他代码
编译并运行我们写的代码
首先将你刚才写好的代码文件(假设命名为demo.cpp)放在ncnn/examples目录下,然后打开ncnn/examples目录下的CMakeLists.txt文件,增加这两行:
add_executable(demo demo.cpp)
target_link_libraries(demo ncnn)
最终的CMakeLists.txt文件类似这样:
find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs)
if(NOT OpenCV_FOUND)
find_package(OpenCV REQUIRED COMPONENTS core highgui imgproc)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src)
add_executable(squeezenet squeezenet.cpp)
target_link_libraries(squeezenet ncnn ${OpenCV_LIBS})
add_executable(fasterrcnn fasterrcnn.cpp)
target_link_libraries(fasterrcnn ncnn ${OpenCV_LIBS})
add_executable(demo demo.cpp)
target_link_libraries(demo ncnn)
add_subdirectory(ssd)
然后打开ncnn根目录下的CMakeLists.txt文件,将编译examples语句的注释打开(默认是被注释掉的),如图:
更改后保存退出,现在就可以终端进入ncnn/build后执行:
make
1
执行完毕后你就可以在ncnn/build/examples下找到你的可执行文件了(demo)
执行可执行文件
首先将你之前生成的.param和.bin文件复制到ncnn/build/examples目录下,然后终端cd到ncnn/build/examples,执行:
./demo data_path1 data_path2
---------------------
作者:DmrfCoder
来源:CSDN
原文:https://blog.csdn.net/qq_36982160/article/details/79929869
版权声明:本文为博主原创文章,转载请附上博文链接!