美文网首页
ncnn c++模型测试

ncnn c++模型测试

作者: FelixCoder | 来源:发表于2019-03-27 16:50 被阅读0次

    ncnn c++测试

    在模型转换完成后,紧接着就要真正在移动端上运行啦,不过在正式放到嵌入式设备上运行时(这一步也不属于我做),还是在PC上拿c++测试一下,确认没问题了才能说明模型的正确性

    ncnn安装

    先使用git命令拉取ncnn源码

    git clone https://github.com/Tencent/ncnn
    

    对ncnn进行编译、安装

    cd ncnn
    mkdir build && cd build
    cmake ..
    make -j
    make install
    

    执行完毕后,在$ncnn_dir/build/install/文件夹下会产生安装文件

    • $ncnn_dir/build/install/lib/libncnn.a为链接库
    • $ncnn_dir/build/install/include/为头文件包含路径

    Cmake配置工程

    在CMakeLists.txt中,加入如下代码,来添加ncnn的链接库和头文件路径

    # 设置ncnn的链接库和头文件路径
    include_directories($ncnn_dir/build/install/include/)
    target_link_libraries($ncnn_dir/build/install/lib/libncnn.a)
    

    由于本人模型输入为图片,因此还需要配置OpenCV,这里就不啰嗦了,直接参考如下链接安装:

    Ubuntu16.04安装opencv for c++:https://blog.csdn.net/qq_33591712/article/details/83279982

    其他Cmake基本配置,比如工程名、增加需要输出的可执行文件、链接OpenCV等等,在这里就不啰嗦了,参考如下链接
    https://www.cnblogs.com/lidabo/p/7359422.html

    ncnn模型文件net.params,net.bin文件解析

    1. params包含了网络结构
    2. bin包含了网络参数
    3. 对于使用该模型,最重要的是从这个网络结构中找到你要的输入输出节点名称,下面是一个网络结构的例子
    7767517
    60 63
    Input            data             0 1 data 0=3 1=180 2=550
    Convolution      ConvNd_1         1 1 data ConvNd_1 0=32 1=3 2=1 3=2 4=1 5=0 6=864
    ........................
    ....... 中间省略.........
    ........................
    Dropout          Dropout_2        1 1 Addmm_1 Dropout_2
    InnerProduct     Addmm_2          1 1 Dropout_2 Addmm_2 0=130 1=1 2=33280
    Softmax          Softmax_1        1 1 Addmm_2 Softmax_1 0=0
    
    • 其中第一行的7767517是ncnn magic numger(幻数),
    • 第二行的60 63。60为layer number(网络层数),63为blob number(参数块数)
    • 剩余的为Input data 0 1 data 0=3 1=180 2=550,我们只关心中间的data,Softmax_1等,这是网络的节点名称,不论是输入还是输出节点,都必须在代码中指定输入输出节点名称

    C++代码

    1. 包含ncnn头文件
    #include "net.h"
    
    1. 读取输入图片
    string img_path = "$IMG_PATH";
    cv::Mat img = cv::imread(img_path, CV_LOAD_IMAGE_COLOR);
    cv::Mat img2;
    //这里一定要检查你图片的大小和训练网络时的图片输入大小,要一样,否则到全连接层时会出现矩阵维数无法相乘
    //input_width:网络输入图片宽度
    //input_height:网络输入图片高度
    cv::resize(img, img2, cv::Size(input_width, input_height));
    
    1. 加载ncnn模型和参数
    // 加载模型和参数
    ncnn::Net DeepNet;
    DeepNet.load_param("$param_path");
    DeepNet.load_model("$bin_path");
    
    1. 将读取的输入图片转化为ncnn::Mat input数据类型,通过ncnn自带的从图像像素转换函数
    ncnn::Mat input = ncnn::Mat::from_pixels(img2.data, ncnn::Mat::PIXEL_BGR, img2.cols, img2.rows);
    
    1. 经输入Mat送入网络并定义输出节点获取结果
    ncnn::Extractor extractor = DeepNet.create_extractor();
    //    将'data'节点名称和ncnn::Mat input对应起来
    extractor.input("data", input);
    //    将'Addmm_1'节点名称和ncnn::Mat output对应起来
    ncnn::Mat output;
    extractor.extract("Addmm_1", output);
    
    1. 将ncnn::Mat类型的输出结果转化为std::vector<float>
    std::vector<float> & cls_scores
    //    网络输出为output,将output转化到cls_scores中输出
    cls_scores.resize(output.cstep);
    for(int j=0; j<output.cstep; j++)
    {
        const float* prob = (float*)output.data + output.c * j;
        cls_scores[j] = prob[0];
    }
    //Debug打印输出
    for(int j = 0;j < cls_scores.size();j++)
    {
        cout << cls_scores[j] ;
    }
    

    调试trick

    1. 对于输出节点,可以使用如下代码来打印节点的通道数和长宽,来判断该节点是否为你需要的那个输出节点(比如你要的输出为15121,那么你可以根据你自己的网络结构大概定位到哪部分,然后挨个使用这种方法打印输出,观察输出节点的维度来判断是否为你需要的输出节点)
        cout << "output.c: " << output.c << endl;
        cout << "output.w: " << output.w << endl;
        cout << "output.h: " << output.h << endl;
    

    相关文章

      网友评论

          本文标题:ncnn c++模型测试

          本文链接:https://www.haomeiwen.com/subject/inftbqtx.html