最近由于业务需求,接触到了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 ..
会发生报错: