在PC机的ubuntu14.04系统上实现ncnn加载caffe模型对目标进行分类

准备caffe网络和模型

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
 

转换ncnn网络和模型


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 <stdio.h>
#include <algorithm>
#include <vector>
#include"gesture.id.h"


#include "net.h"

//使用ncnn,传入的参数第一个是你需要预测的数据,第二个参数是各个类别的得分vector,注意传入的是地址,这样才能在这个函数中改变其值
static int detect_squeezenet( float *data, std::vector<float>& cls_scores)
{
    //实例化ncnn:Net,注意include "net.h",不要在意这时候因为找不到net.h文件而include<net.h>报错,后文会介绍正确的打开方式
    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<out.w; j++)
    {

        cls_scores[j] = out[j];
    }

    return 0;
}
int main(int argc, char** argv)
{
    //注意,这里的argv是之后从终端输入的参数,我这里是数据源的路径,因为我是从两个文件中生成一个总的数据,所以用了argv[1]和argv[2],你也可以自己根据需求改变
    const char* imagepath1 = argv[1];
    const char* imagepath2=argv[2];

    FILE *fopeni=NULL;
    FILE *fopenq=NULL;

    fopeni=fopen(imagepath1,"r");
    fopenq=fopen(imagepath2,"r");

    //这是我的数据,i和q相当于图片的两个通道
    float i[4400];
    float q[4400];
    float data[8800];

    int count=4400;
    for (int j = 0; j < count; ++j)
    {
      fscanf(fopeni,"%f",&i[j]);
      fscanf(fopenq,"%f",&q[j]);
    }   
    //这是将iq(相当于图片的两个通道的数据)转化为一个一维向量,需要特别注意的是数据维度的顺序
    for (int j = 0; j < 8800; ++j)
    {
        if (j<4400)
        {
            data[j]=i[j];
        }else{
            data[j]=q[j-4400];
        }

    }

    char a[13]={'A','B','C','F','G','H','I','J','K','L','M','N','O'};

    //注意,这里是调用ncnn的代码
    std::vector<float> 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 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值