实验环境:Ubuntu 20.0 推理模型:ONNX分类模型

1. 安装依赖项

首先是需要安装依赖库,如g++cmake等,如果已经安装的话可以忽略

sudo apt install -y g++
sudo apt install -y cmake
sudo apt install -y make
sudo apt install -y wget unzip
  • 1.
  • 2.
  • 3.
  • 4.

安装一些opencv的依赖项(可不安装)

sudo apt-get install build-essential libgtk2.0-dev libgtk-3-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev
  • 1.

安装一些可选库(可不安装)

# streamer支持
sudo apt install libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev
# 可选的依赖
sudo apt install libpng-dev libopenexr-dev libtiff-dev libwebp-dev
  • 1.
  • 2.
  • 3.
  • 4.

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_OpenCV

2. 下载并安装OpenCV

可以在官网下载相应版本的OpenCV,主要有SourceGitHub两种方式下载。

2.1 Source下载
Source:https://opencv.org/releases/
  • 1.

点击Source进行下载:

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_opencv_02

2.2 GitHub下载

这里推荐安装4.9.0版本。

# 安装4.9.0版本
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.9.0.zip
# 安装最新版本
wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip
  • 1.
  • 2.
  • 3.
  • 4.

下载完成后解压,并将文件夹名字改为opencv

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_OpenCV_03

3. Cmake配置和编译OpenCV

进入到下载好的opencv目录中,新建并进入目录build

cd opencv
mkdir build
cd build
  • 1.
  • 2.
  • 3.

使用cmake配置opencv

cmake -D CMAKE_BUILD_TYPE=Release -D OPENCV_GENERATE_PKGCONFIG=YES ..
  • 1.

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_linux_04

说明:
-D OPENCV_GENERATE_PKGCONFIG=YES OpenCV4以上默认不使用pkg-config,该编译选项开启生成opencv4.pc文件,支持pkg-config功能

随后使用make进行编译

make -j4
  • 1.

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_#include_05

说明:
-j4中的4指同时使用4个进程,可以根据电脑的进程数调整此值

make进行安装(可以不用sudo)

sudo make install
  • 1.

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_opencv_06

默认安装路径为:
/usr/local/bin - executable files
/usr/local/lib - libraries(.so)
/usr/local/cmake/opencv4 - cmake package
/usr/local/include/opencv4 - headers
/usr/local/share/opencv4 - other files (e.g. trained cascades in XML format)

4. 环境配置

4.1 配置pkg-config环境

opencv4.pc文件的默认路径:/usr/local/lib/pkgconfig/opencv4.pc 若此目录下没有,可以使用以下命令搜索:

sudo find / -iname opencv4.pc
  • 1.

可以看到在该目录下面:

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_#include_07

将路径加入到PKG_CONFIG_PATH(用vim打开):

sudo vim /etc/profile.d/pkgconfig.sh
  • 1.

在文件后面加入下面一行:

export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
  • 1.

保存并退出后激活:vim保存退出的方式:按ESC 输入:wq 然后回车

# 激活
source /etc/profile
  • 1.
  • 2.

用以下命令验证是否成功:

pkg-config --libs opencv4
  • 1.

输出结果如下则代表成功

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_#include_08

4.2 配置动态库环境

打开文件(可能为空文件):

sudo vim /etc/ld.so.conf.d/opencv4.conf
  • 1.

在该文件末尾加上OpenCVlib路径,保存退出:

/usr/local/lib
  • 1.

使配置的路径生效:

sudo ldconfig
  • 1.

5. 测试OpenCV(CPU)

cd/opencv/samples/cpp/example_cmake目录下,然后打开opencv_example.cpp文件,替换为下面的代码,这个代码执行的便是 加载分类ONNX模型进行推理。

这里博主使用的是OpenCV中的dnn.hpp来加载ONNX模型,当然我们也可以选择使用ONNX Runtime

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <iostream>
#include <vector>
#include <cmath>

// Softmax 函数
void softmax(const float* data, float* output, int size) {
    float max_val = -INFINITY;
    for (int i = 0; i < size; ++i) {
        max_val = std::max(max_val, data[i]);
    }

    float sum_exp = 0.0f;
    for (int i = 0; i < size; ++i) {
        sum_exp += std::exp(data[i] - max_val);
    }

    for (int i = 0; i < size; ++i) {
        output[i] = std::exp(data[i] - max_val) / sum_exp;
    }
}

int main() {
    // 加载模型
    std::string modelPath = "juan_cls.onnx";
    cv::dnn::Net net = cv::dnn::readNetFromONNX(modelPath);

    if (net.empty()) {
        std::cerr << "无法加载模型,请检查路径是否正确" << std::endl;
        return -1;
    }

    // 图像输入
    cv::Mat img = cv::imread("img.jpg");
    if (img.empty()) {
        std::cerr << "无法加载图像 img.jpg" << std::endl;
        return -1;
    }

    // 预处理
    int inputWidth = 640;
    int inputHeight = 640;
    cv::Mat blob = cv::dnn::blobFromImage(img, 1.0, cv::Size(inputWidth, inputHeight),
                                         cv::Scalar(), true, false);
    net.setInput(blob);

    // 推理
    cv::Mat out = net.forward();
    std::cout << "Inference Shape: " << out.size << std::endl;

    // 假设 out 是 [1 x C x H x W]
    int batchSize = out.size[0];   // 1
    int channels = out.size[1];    // 2
    int height = out.size[2];      // 640
    int width = out.size[3];       // 640
    
    std::vector<float> avgScores(channels, 0.0f);
    
    for (int c = 0; c < channels; ++c) {
        double sum = 0.0;
        float* ptr = out.ptr<float>(0, c);  // batch=0, channel=c
        for (int h = 0; h < height; ++h) {
            for (int w = 0; w < width; ++w) {
                sum += ptr[h * width + w];
            }
        }
        avgScores[c] = static_cast<float>(sum / (height * width));
    }

    // Softmax 归一化
    float probs[2];
    softmax(avgScores.data(), probs, 2);

    // 输出结果
    std::cout.precision(4);
    std::cout << std::fixed;
    std::cout << "\n【Result】" << std::endl;
    std::cout << "Cls 0 Score: " << probs[0] << std::endl;
    std::cout << "Cls 1 Score: " << probs[1] << std::endl;
    std::cout << "Cls: " << (probs[0] > probs[1] ? 0 : 1) << std::endl;

    return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.

随后,进行编译执行:

cmake .
make
./opencv_example
  • 1.
  • 2.
  • 3.

cmake .后,会生成下面这些文件,根据 CMakeLists.txt 生成编译规则(如 Makefile)

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_linux_09

make根据 Makefile 编译出可执行文件

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_linux_10

./opencv_example运行编译好的程序,执行结果如下:

Linux环境下使用 C++ 与 OpenCV 实现 ONNX 分类模型推理_linux_11

至此,我们便已经完成了使用C++OpenCV加载ONNX模型进行推理,接下来,我们将调用GPU来进行加速推理,敬请期待。