實驗環境: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
安裝一些opencv
的依賴項(可不安裝)
sudo apt-get install build-essential libgtk2.0-dev libgtk-3-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev
安裝一些可選庫(可不安裝)
# streamer支持
sudo apt install libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev
# 可選的依賴
sudo apt install libpng-dev libopenexr-dev libtiff-dev libwebp-dev
2. 下載并安裝OpenCV
可以在官網下載相應版本的OpenCV
,主要有Source
和GitHub
兩種方式下載。
2.1 Source下載
Source:https://opencv.org/releases/
點擊Source
進行下載:
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
下載完成后解壓,并將文件夾名字改為opencv
3. Cmake配置和編譯OpenCV
進入到下載好的opencv
目錄中,新建并進入目錄build
:
cd opencv
mkdir build
cd build
使用cmake
配置opencv
:
cmake -D CMAKE_BUILD_TYPE=Release -D OPENCV_GENERATE_PKGCONFIG=YES ..
說明:
-D OPENCV_GENERATE_PKGCONFIG=YES OpenCV4以上默認不使用pkg-config,該編譯選項開啟生成opencv4.pc文件,支持pkg-config功能
隨后使用make
進行編譯
make -j4
說明:
-j4中的4指同時使用4個進程,可以根據電腦的進程數調整此值
用make
進行安裝(可以不用sudo
)
sudo make install
默認安裝路徑為:
/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
可以看到在該目錄下面:
將路徑加入到PKG_CONFIG_PATH
(用vim
打開):
sudo vim /etc/profile.d/pkgconfig.sh
在文件后面加入下面一行:
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
保存并退出后激活:
vim
保存退出的方式:按ESC
輸入:wq
然后回車
# 激活
source /etc/profile
用以下命令驗證是否成功:
pkg-config --libs opencv4
輸出結果如下則代表成功
4.2 配置動態庫環境
打開文件(可能為空文件):
sudo vim /etc/ld.so.conf.d/opencv4.conf
在該文件末尾加上OpenCV
的lib
路徑,保存退出:
/usr/local/lib
使配置的路徑生效:
sudo ldconfig
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]; // 1int channels = out.size[1]; // 2int height = out.size[2]; // 640int width = out.size[3]; // 640std::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=cfor (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;
}
隨后,進行編譯執行:
cmake .
make
./opencv_example
cmake .后,會生成下面這些文件,根據 CMakeLists.txt 生成編譯規則(如 Makefile)
make
根據 Makefile
編譯出可執行文件
./opencv_example
運行編譯好的程序,執行結果如下:
至此,我們便已經完成了使用C++
與OpenCV
加載ONNX
模型進行推理,接下來,我們將調用GPU來進行加速推理,敬請期待。