转换模型
ncnn(https://github.com/Tencent/ncnn)编译好后,tools内有一个onnx2ncnn的工具,直接使用此工具即可将onnx模型转换为ncnn模型,命令如下:
cd /home/darrenzhang/ncnn/build/tools/onnx./onnx2ncnn resnet18-v2-7.onnx resnet18.param resnet18.bin

生成resnet18的param文件和bin文件,其中,param文件保存了模型结构,bin文件保存了模型参数。
C++ 调用
测试ncnn模型的前向推理结果的正确性,导入ncnn的库和头文件后,调用代码如下:
CMakeLists.txt文件如下
cmake_minimum_required(VERSION 3.17)project(ncnn_res_cls)set( OpenCV_DIR /home/darrenzhang/opencv/usr/local/lib/cmake/opencv4)find_package(OpenCV REQUIRED)FIND_PACKAGE( OpenMP REQUIRED)if(OPENMP_FOUND)message("OPENMP FOUND")set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")endif()set(CMAKE_CXX_STANDARD 11)include_directories(/home/darrenzhang/ncnn/build/install/include/ncnn)link_directories(/home/darrenzhang/ncnn/build/install/lib)add_executable(ncnn_res_cls main.cpp)target_link_libraries(ncnn_res_cls ${OpenCV_LIBS}/home/darrenzhang/ncnn/build/install/lib/libncnn.a)
main.cpp代码如下
//// Created by darrenzhang on 2021/3/3.//#include <opencv2/opencv.hpp>#include <fstream>#include "platform.h"#include "net.h"using namespace std;using namespace cv;vector<string> split(const string& str, const string& pattern) {vector<string> ret;if (pattern.empty()) return ret;size_t start = 0, index = str.find_first_of(pattern, 0);while (index != str.npos) {if (start != index)ret.push_back(str.substr(start, index - start));start = index + 1;index = str.find_first_of(pattern, start);}if (!str.substr(start).empty())ret.push_back(str.substr(start));return ret;}void get_label(vector<string> &labels, const char* file_path) {FILE *fp = fopen(file_path, "r");ifstream infile;string temp;const char*d = ":";infile.open(file_path);while(getline(infile, temp)) {vector<string> line = split(temp, ":");labels.push_back((line[1]));}}static int print_topk(const std::vector<float>& cls_scores, int topk,vector<string> labels){// partial sort topk with indexint size = cls_scores.size();std::vector< std::pair<float, int> > vec;vec.resize(size);for (int i=0; i<size; i++){vec[i] = std::make_pair(cls_scores[i], i);}std::partial_sort(vec.begin(), vec.begin() + topk, vec.end(),std::greater< std::pair<float, int> >());// print topk and scorefor (int i=0; i<topk; i++){float score = vec[i].first;int index = vec[i].second;string label = labels[index];fprintf(stderr, "%d = %f %s \n", index, score ,label.c_str());}return 0;}int main() {vector<string> labels;get_label(labels, "/home/darrenzhang/CLionProjects/ncnn_res_cls/data/label.txt");cv::Mat img = cv::imread("/home/darrenzhang/CLionProjects/ncnn_res_cls/data/test.jpg");int img_w = img.cols;int img_h = img.rows;ncnn::Mat input_img = ncnn::Mat::from_pixels_resize(img.data, ncnn::Mat::PIXEL_BGR, img.cols, img.rows, 224, 224);const float mean_vals[3] = {104.0f,117.0f,123.0f};const float norm_vals[3] = {0.007843f, 0.007843f, 0.007843f};input_img.substract_mean_normalize(mean_vals, norm_vals); // normalize for input imgncnn::Net resnet18;resnet18.load_param("/home/darrenzhang/CLionProjects/ncnn_res_cls/model/resnet.param");resnet18.load_model("/home/darrenzhang/CLionProjects/ncnn_res_cls/model/resnet.bin");ncnn::Extractor ex = resnet18.create_extractor(); // 定义解析器,解析特征平面ex.set_num_threads(4);ex.input("data", input_img);ncnn::Mat out; // define the ncnn`s outputex.extract("resnetv22_dense0_fwd", out); // extract the last layer`s output of the modelvector<float> output;output.resize(out.w);for (int i = 0; i < out.w; i ++)output[i] = out[i];print_topk(output, 2, labels);}
报错如下:
locate libopencv_imgproc.so.4.1

进入到/etc/ld.so.conf.d
cd etc/ld.so.conf.d
sudo vi OpenCV.conf
/home/darrenzhang/opencv/usr/local/lib/
sudo ldconfig -v
报错内容2:
内存溢出,使用断点调试发现如下错误,模型加载问题
fopen resnet.param failed
fopen resnet.bin failed
find_blob_index_by_name data failed
find_blob_index_by_name prob failed

在debug或者运行可执行文件的时候,可执行文件在cmake-build-debug文件夹中,所以模型路径和测试文件路径要根据可执行文件的路径来设置。
