最近由于業務需求,接觸到了Jetson邊緣AI計算主板,博主使用的是Jetson Orin NX 16GB這個版本,可以看到其算力達到了100TOPS,這是一個非常恐怖的算力了,接下來便是博主對其的環境配置過程,博主要在該主板上運行一個旋轉檢測模型,過程如下:
Jetson
使用的是Arm
架構,所以在配置時會存在差異
在使用Jetson
系列設備時,為了實時查看CPU
,GPU
,我們首先應該安裝Jtop
軟件
1. 安裝Jtop
監測軟件
1.1 安裝 pip3
因為我們需要使用pip3
來安裝jtop
,所以需要在系統中先安裝pip3
。
sudo apt install python3-pip
1.2 安裝 jtop
sudo -H pip3 install -U jetson-stats
隨后直接輸入jtop
即可:
隨后我們點擊INFO
,查看系統信息:
可用看到,此時CUDA
、cuDNN
都是沒有的,OpenCV
也是不支持CUDA
加速的。
那么,我們接下來該怎么做呢,難道要像Window
、Ubuntu
下那樣安裝CUDA
和cudNN
嗎,不不不,Jetson
為方便開發者,提供了 Jetpack
開發套件,其幫了我們大忙
2. 安裝JETPACK套件
為啥安裝 Jetpack
,那就是 Jetpack
是 Nvidia
為 Jetson
系列開發板開發的一款軟件開發包,常用的開發工具基本都包括了,并在在安裝 Jetpack
的時候,會自動安裝匹配版本的CUDA
、cuDNN
、TensorRT
等。
我們耐心等待即可,安裝完成后,再次調用 JTop
查看,此時我們看到CUDA
和cuDNN
已經裝好了,接下來便是對其進行配置,并重新編譯OpenCV
,使其能夠支持CUDA
加速
目前,我們只是安裝了CUDA和cuDNN,接下來我們需要對其進行配置
3. CUDA與cuDNN配置
cuDNN
默認安裝路徑在 /usr/lib/aarch64-linux-gnu
下
CUDA
默認安裝路徑在 /usr/local/cuda
下
3.1 CUDA配置
配置Cuda環境變量:
CUDA
已經默認安裝在了/usr/local/cuda
下,運行如下指令:
sudo vim ~/.bashrc # 打開~/.bashrc#在文本末輸入如下代碼:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64
export PATH=$PATH:/usr/local/cuda/bin
export CUDA_HOME=$CUDA_HOME:/usr/local/cudasource ~/.bashrc #保存環境變量
我們使用nvcc-V
查看一下CUDA
配置:
3.2 cuDNN配置
雖然安裝了cuDNN,但沒有將對應的頭文件、庫文件放到cuda目錄。
cuDNN
的頭文件在:/usr/include
,庫文件位于:/usr/lib/aarch64-linux-gnu
。將頭文件與庫文件復制到cuda
目錄下:
# 復制文件到cuda目錄下
cd /usr/include && sudo cp cudnn* /usr/local/cuda/include
cd /usr/lib/aarch64-linux-gnu && sudo cp libcudnn* /usr/local/cuda/lib64
隨后創建軟鏈接,這個步驟不能少,否則在OpenCV
編譯時會報錯,因為其找不到cuDNN
。
# 修改文件權限,修改復制完的頭文件與庫文件的權限,所有用戶都可讀,可寫,可執行:
sudo chmod 777 /usr/local/cuda/include/cudnn.h
sudo chmod 777 /usr/local/cuda/lib64/libcudnn*# 重新軟鏈接,這里的9.3.0和9對應安裝的cudnn版本號和首數字
cd /usr/local/cuda/lib64sudo ln -sf libcudnn.so.9.3.0 libcudnn.so.9sudo ln -sf libcudnn_ops_train.so.9.3.0 libcudnn_ops_train.so.9
sudo ln -sf libcudnn_ops_infer.so.9.3.0 libcudnn_ops_infer.so.9sudo ln -sf libcudnn_adv_train.so.9.3.0 libcudnn_adv_train.so.9
sudo ln -sf libcudnn_adv_infer.so.9.3.0 libcudnn_adv_infer.so.9sudo ln -sf libcudnn_cnn_train.so.9.3.0 libcudnn_cnn_train.so.9
sudo ln -sf libcudnn_cnn_infer.so.9.3.0 libcudnn_cnn_infer.so.9sudo ldconfig
3.3 測試cuDNN
執行下面的命令:
sudo cp -r /usr/src/cudnn_samples_v9/ ~/ #將系統中自帶的 cuDNN 示例代碼文件夾 cudnn_samples_v8 復制到你的用戶主目錄(~/) 方便測試
cd ~/cudnn_samples_v9/mnistCUDNN
sudo chmod 777 ~/cudnn_samples_v9 #給整個 cudnn_samples_v8 目錄賦予“所有用戶”完全權限(讀、寫、執行
sudo make clean && sudo make #清理之前的編譯產物并重新編譯示例程序
./mnistCUDNN
默認會復制到這個路徑下:
如果測試通過的話,會最終輸出:
如果在執行sudo make clean && sudo make
時報錯:
那么就表示缺少對應的庫,安裝下面的庫即可:
sudo apt-get install libfreeimage3 libfreeimage-dev
安裝完成之后再進行sudo make
,基本上就可以編譯成功了。
4. OpenCV with CUDA編譯
先前我們安裝的OpenCV
無法通過CUDA
編譯,因此我們要考慮是否是OpenCV
版本不匹配導致的,先前我們按照的是OpenCV 4.9
,而我們的CUDA
和cuDNN
版本分別是12.6
和9.3
,我們需要查看一下與之匹配的OpenCV
版本:
理論上博主使用OpenCV 4.9
應該是沒有問題的,奈何就是不行,果斷使用最新版本的OpenCV
,即4.13
,直接上就完了。
4.1 運行 CMake 配置
下載對應的 opencv
源碼和 opencv_contrib
源碼,然后創建,這里博主把 opencv_contrib
放到了opencv
下面,然后創建build
文件目錄,開始CMake
配置。
注意,一定要下載opencv_contrib的源碼,否則會報錯,下面博主在執行時便遇到了這個問題。
因為OpenCV
的一些 CUDA
功能(如內存管理、底層工具)被移到了 opencv_contrib
倉庫中的 cudev
模塊中,所以我們需要下載opencv_contrib
將下載后的opencv_contrib
放到opencv
文件夾下:
隨后切換到build
文件夾下,執行下面的腳本:
cmake -D CMAKE_BUILD_TYPE=RELEASE \-D CMAKE_INSTALL_PREFIX=/usr/local \-D WITH_CUDA=ON \-D OPENCV_DNN_CUDA=ON \-D ENABLE_FAST_MATH=ON \-D CUDA_FAST_MATH=ON \-D WITH_CUBLAS=ON \-D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules \-D BUILD_opencv_cudev=ON \..
完成后的效果如下:
4.2 OpenCV with CUDA 編譯與安裝
生成CMake文件后,進行編譯并安裝
make -j$(nproc) #調用最大CPU可用數量,用于加速make編譯
這個過程會比較漫長,預計得半個多小時 。。。。。
最終編譯完成后效果:
在完成后,我們執行安裝命令:
sudo make install
安裝成功:
安裝完成后,我們就可以進行測試了,我們依舊選擇一個分類模型進行測試:
cd
到/opencv/samples/cpp/example_cmake
目錄下,然后打開opencv_example.cpp
文件,替換為下面的代碼,這個代碼執行的便是 加載分類ONNX
模型進行推理。
#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() {// 檢查是否有可用的 CUDA 設備if (cv::cuda::getCudaEnabledDeviceCount() == 0) {std::cerr << "沒有檢測到 CUDA 設備,請檢查 OpenCV 是否啟用了 WITH_CUDA 和 OPENCV_DNN_CUDA" << std::endl;return -1;} else {std::cout << "CUDA is Used,Detected " << cv::cuda::getCudaEnabledDeviceCount() << " GPU" << std::endl;}// 加載模型std::string modelPath = "juan_cls.onnx";cv::dnn::Net net = cv::dnn::readNetFromONNX(modelPath);if (net.empty()) {std::cerr << "無法加載模型,請檢查路徑是否正確" << std::endl;return -1;}// 設置網絡后端為 CUDAnet.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);// 圖像輸入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);// 推理(GPU)cv::Mat out = net.forward();std::cout << "Inference Shape: " << out.size << std::endl;// 假設輸出是 [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 << "\nResult" << 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
最終效果如下,可以看到檢測到了一個GPU
,并且在執行時能夠明顯感覺到速度提升了。
此時我們再使用jtop
查看環境,可用看到此時的OpenCV
便是可用使用CUDA
的了。
踩坑
當我們沒有下載opencv_contrib代碼時,我們在CMake時執行這段編譯代碼:
cmake -D CMAKE_BUILD_TYPE=RELEASE \-D CMAKE_INSTALL_PREFIX=/usr/local \-D WITH_CUDA=ON \-D OPENCV_DNN_CUDA=ON \-D ENABLE_FAST_MATH=ON \-D CUDA_FAST_MATH=ON \-D WITH_CUBLAS=ON \-D BUILD_opencv_cudacodec=OFF \-D BUILD_EXAMPLES=OFF ..
會發生報錯: