在ncnn源码中写自己的c++推理代码

在ncnn源码中写自己的c++推理代码,第1张

在ncnn源码中写自己的c++推理代码

按照官网下载的https://github.com/Tencent/ncnn源码,并且按照链接https://github.com/Tencent/ncnn/wiki/how-to-build#pass-for-linux中的方式来进行编译,编译之后就可以运行一下。
此时有一个新的需求,我们想要自己编译一个项目,但是我尝试抽取ncnn中的编译库来编译,但是无法成功抽取,太垃圾了,然后转头一想加上分析,发现可以不用抽取ncnn源码,只用在他相同的文件夹中来编译自己的源码就好了。

  • 1,ncnn源码中有一个examples文件夹,他里边放着很多自带的待编译demo,编译之后生成的可执行文件就在build/examples文件夹中(顺着ncnn官网的squeezenet编译与使用来了解整个项目);

  • 2,然后仿照上边的处理思路,我们可以在examples所在的文件夹下建立自己的待编译源码文件夹my_src,然后里边的CMakeLists.txt以及cpp源码都可以仿照examples里边的代码来处理。

    • CMakeLists.txt:修改的地方主要有添加 ncnn_add_my_src(srcnn)
    • cpp: 文件中就是把squeezenet中的代码复制过来修改为自己的就好了
  • 值得一提的是,尽量把数据预处理的代码都写到model中,这样减少在c++中做数据预处理,因为c++数据预处理比较麻烦。

自己的cpp代码如下,仅供参考:

#include "net.h"

#include 
#if defined(USE_NCNN_SIMPLEOCV)
#include "simpleocv.h"
#else
#include 
#include   // image文件读取与写入
#include   // 高等级gui
#include   // 图像处理
#endif
#include 
#include 
#include 

using namespace std;


static int srcnn_process(const cv::Mat& bgr_image1)
{
    
    // 显示一下输入的image
    cout<< bgr_image1.size() << endl;
    cv::imshow("bgr_image1", bgr_image1);
    cv::waitKey(0);

    // 网络加载
    ncnn::Net srcnn;
    srcnn.opt.use_vulkan_compute = true;
    // 看看能否加载成功
    if (srcnn.load_param("srcnn.param"))
        exit(-1);
    if (srcnn.load_model("srcnn.bin"))
        exit(-1);

    
    /**  数据预处理  */
    // resize小一点
    int row = bgr_image1.rows;  // 行高
    int col = bgr_image1.cols;  // 列宽
    cv::Mat bgr_image;
    cv::resize(bgr_image1, bgr_image, cv::Size(col/2, row/2), 0, 0, CV_INTER_LINEAR);
    cout<< bgr_image.size() << endl;

    // bgr_image.convertTo(bgr_image, CV_32F);  // 首先将数据转为32位浮点数(因为python推理里边有这个操作)

    // cvMat转为ncnnMat
    ncnn::Mat in = ncnn::Mat::from_pixels(bgr_image.data, ncnn::Mat::PIXEL_BGR2RGB, bgr_image.cols, bgr_image.rows);

    // 可视化一下转为ncnn的数据是否还是正常的图片
    cv::Mat cv_img_temp(in.h, in.w, CV_8UC3);
    in.to_pixels(cv_img_temp.data, ncnn::Mat::PIXEL_RGB2BGR);  // 先把ncnnMat转为cvMat的image格式
    cv::imshow("cv_img_temp", cv_img_temp);
    cv::waitKey(0);
    
    // 归一化
    // float mean[1] = { 128.f };  // 均值
    // float norm[1] = { 1/128.f };  // 方差
    // in.substract_mean_normalize(mean, norm);

    // cout<< "111" << endl;

    /**  推理  */
    // 得到特征提取器
    ncnn::Extractor ex = srcnn.create_extractor();
    // 送入输入
    ex.input("input", in);
    // 得到网络的输出
    ncnn::Mat out;
    ex.extract("output", out);

    // cout<< "222" << endl;


    /**  后处理  */
    // 得到3通道的无符号8位图像数据
    cv::Mat cv_img(out.h, out.w, CV_8UC3);
    out.to_pixels(cv_img.data, ncnn::Mat::PIXEL_RGB2BGR);  // 数据转为BGR输出到cv_img中
    
    // 显示一下处理后的image
    cv::imshow("image", cv_img);
    cv::waitKey(0);

    return 0;
}



// main函数
int main(int argc, char** argv) {
    // argc 输入有多少个参数, argv[] 用来存你输入的参数

    // 如果没输入两个参数,就是没图片路径
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s [imagepath]\n", argv[0]);
        return -1;
    }

    // 取出第一个参数,就是 imagepath
    const char* imagepath = argv[1];

    // 读取输入图片
    cv::Mat m = cv::imread(imagepath, 1);
    if (m.empty())  // 图片读取失败
    {
        fprintf(stderr, "cv::imread %s failed\n", imagepath);
        return -1;
    }

    // 推理
    srcnn_process(m);

    // cv::imshow("image", m);
    // cv::waitKey(0);

    return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/2889457.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-14
下一篇 2022-09-14

发表评论

登录后才能评论

评论列表(0条)

保存