基于 AGX Orin 开发传统的立体匹配算法手册
1. agx orin 开发环境的搭建
1. agx orin 使用 sdk manager 刷机
请参考:
https://qymj5fptm1.feishu.cn/wiki/Fj02wctLrie95SkJoFocV2V3nrc?from=from_copylink
将agx orin 刷机为 Jetpack 系统选择 5.1.2 , vpi 版本为 2.3.9。
谨慎直接升级 jetpack, 可能出现错误。如何升级 orin nx安装的版本都是2.2.7 到 2.3.9, 成功!
https://blog.csdn.net/weixin_42283539/article/details/133170195
但是 jtop 显示 jetpack 还是 5.1.1 , sudo apt show nvidia-jetpack 显示 jetpack 为 5.1.2
运行例子报错:
Traceback (most recent call last):
File "main.py", line 29, in
import vpi
ImportError: /opt/nvidia/cupva-2.3/lib/aarch64-linux-gnu/libcupva_host.so.2.3: undefined symbol: PvaProgramSetDMADescriptorsV2
估计是版本不兼容,需要使用 sdkm 重新刷 jetpack。
不要使用:
sudo apt-get upgrade
,重启后容易系统崩溃。
2. 安装必备的软件
输入法:谷歌拼音
监控 jetson 的软件:jtop
代码编辑器:vscode(aarch64版本)
python 管理: miniconda(可选)
常用命令:
jtop
:查看各种软件版本和硬件运行情况sudo apt show nvidia-jetpack
:查看 jetpack 版本which python
: 查看当前终端使用的 python 位置whereis python
:查找所有的 python 位置uname -m
: 查看处理器类型, orin 为aarch64
sudo jetson_release
:查看 jetson 各种软件版本
安装 miniconda:
# 下载
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh -O ~/miniconda3/miniconda.sh
# 安装
bash ~/miniconda3/Miniconda3-latest-Linux-aarch64.sh -b -u -p ~/miniconda3
# 删除掉安装包
rm -rf ~/miniconda3/miniconda.sh
# 激活
~/miniconda3/bin/conda init bash
注:需要安装的软件版本为 arm64
3. 双目深度估计算法之 SGBM
算法流程:
双目相机标定资料:
- 使用 matlab 进行相机标定
- 使用 opencv 进行相机标定 C++
- 使用 opencv 进行相机标定 python
- Camera Calibration-opencv(python)
- 相机标定知识汇总
SGBM 资料:
- Accurate and Efficient Stereo Processing by Semi-Global Matching and Mutual
Information--SGM 算法 - 基于python的SGBM参数影响效果
- SGBM 双目立体视觉资料
- SGBM 视频教程
开源代码仓库:
- jetson-stereo-depth
- VPI 新版本例子
- libsgm--重写的sgm 算法的 cuda 实现
- Conventional SGBM depth ranging + yolov5 object detection with deployment on Jeston nano
3. 1 基于 VPI 的双目深度估计
VPI 教程:
基于 代码库 jetson-stereo-depth 的 实践:
calib 文件夹下的 jupyter notebook 提供了 基于 opencv(python) 的 双目相机标定和矫正的整个流程。
运行 calib/calib_images/download_images.sh 脚本,下载 calib_images 图像。
01:
- 输入待矫正的图像
- cv2.findChessboardCorners: 确定输入图片是否有棋盘图案,并定位棋盘板上的角点
- cv2.cornerSubPix:寻找亚像素角点
- cv2.calibrateCamera:标定得到 左右相机的内参矩阵、畸变系数、旋转矩阵和平移矩阵
02:
- cv2.stereoCalibrate:双目标定函数,https://blog.csdn.net/weixin_43560489/article/details/123562399
- cv2.stereoRectify:为每个摄像头计算立体校正的映射矩阵 R1, R2, P1, P2 ,Q。https://blog.csdn.net/weixin_43196818/article/details/129184280
- 通过 cv2.initUndistortRectifyMap 将结果以映射的形式表达,映射关系存储在 map1(X坐标重映射参数)和map2(Y坐标重映射参数)中
- 将 map1, map2 和 Q 存到 yaml 文件中。
参考: https://blog.csdn.net/weixin_41405284/article/details/105327694
- 读取 yaml 文件
- cv2.remap 把原始图像中某位置的像素映射到矫正后的图像指定位置
- disparity = stereo.compute(img1_rectified, img2_rectified) 计算视差
- cv2.normalize:归一化函数算法,生成深度图(灰度图)
- cv2.applyColorMap: 生成深度图(颜色图)
- cv2.reprojectImageTo3D: 计算三维坐标数据值, 需要 Q
VPI 实现了 remap、vpi.stereodisp,加快了计算速度。
图像 640×480 ,Orin 速度 55 FPS(只计算 SGBM 算法时间)
3. 2 基于 Opencv 的双目深度估计
CPU 版本
基于 https://github.com/yzfzzz/Stereo-Detection
图像 640×480 ,使用 opencv cpu 计算,大约 6 fps。
3. 3 ligsgm 库的实现
该算法库手工实现了 sgm 在 cuda 上计算的各个步骤。
0.环境准备
01.更新cmake
查看cmake版本:
$ sudo cmake --version
cmake version 3.16.3
卸载旧的 cmake
$ sudo apt -y remove cmake
升级 cmake 到 3.23.0
cmake官方为我们提供了各个版本的源码包,列表链接为:https://cmake.org/files/
参考: https://zhuanlan.zhihu.com/p/519732843
1.下载源码
$ git clone https://github.com/fixstars/libSGM.git
$ cd libSGM
$ git submodule update --init # It is needed if ENABLE_TESTS option is set to ON
$ mkdir build
$ cd build
$ cmake .. -DENABLE_SAMPLES=on
$ make
2.数据下载
在kitti数据网站(需要注册)中 The KITTI Vision Benchmark Suite,下载 synced+rectified data.
3.运行
$ ./build/sample/stereosgm_movie --left_img ./2011_09_26_drive_0048_sync/2011_09_26/2011_09_26_drive_0048_sync/image_00/data/%010d.png --right_img ./2011_09_26_drive_0048_sync/2011_09_26/2011_09_26_drive_0048_sync/image_01/data/%010d.png
$ ./build/sample/stereosgm_image --left_img ./2011_09_26_drive_0048_sync/2011_09_26/2011_09_26_drive_0048_sync/image_00/data/0000000000.png --right_img ./2011_09_26_drive_0048_sync/2011_09_26/2011_09_26_drive_0048_sync/image_01/data/0000000000.png
$ ./build/sample/stereosgm_movie --left_img ./KITTI2011_10_03_drive_0042_sync/2011_10_03/2011_10_03_drive_0042_sync/image_00/data/%010d.png --right_img ./KITTI\ 2011_10_03_drive_0042_sync/2011_10_03/2011_10_03_drive_0042_sync/image_01/data/%010d.png
生成的视频: test.mp4
该代码实现了 cuda 的计算,并不需要安装 opencv 的 cuda 版本。计算速度为:1242,375 像素下达到 32 FPS。
3. 4 基于 Opencv CUDA 版本的双目深度估计
01.卸载 原来的 opencv
sudo apt purge libopencv*
sudo apt update
安装依赖:
sudo apt-get install build-essential \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
libeigen3-dev \
libglew-dev \
libgtk2.0-dev \
libgtk-3-dev \
libjpeg-dev \
libpostproc-dev \
libswscale-dev \
libtbb-dev \
libtiff5-dev \
libv4l-dev \
libxvidcore-dev \
libx264-dev \
qt5-default \
zlib1g-dev \
libavresample-dev \
gstreamer1.0-plugins-bad \
pkg-config
02.编译支持 GPU 加速的OpenCV
下载 opencv
https://github.com/opencv/opencv/archive/4.5.4.zip
https://github.com/opencv/opencv_contrib/archive/4.5.4.zip
解压、放到一个文件夹中。
cd opencv-4.5.4
mkdir build && cd build
清除 rm CMakeCache.txt
查看 agx orin 的 CUDA_ARCH_BIN 为 8.7。 jetson 除了上面网址可以去查,也可以使用 jtop
查询 CUDA_ARCH_BIN。
cmake -D CMAKE_BUILD_TYPE=Release \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.5.4/modules \
-D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-11.4 \
-D CUDA_ARCH_BIN=8.7 \
-D CUDA_ARCH_PTX=8.7 \
-D WITH_CUDA=ON \
-D OPENCV_DNN_CUDA=ON \
-D WITH_CUDNN=ON \
-D ENABLE_FAST_MATH=ON \
-D CUDA_FAST_MATH=ON \
-D WITH_CUBLAS=1ON \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D BUILD_EXAMPLES=ON \
-D BUILD_NEW_PYTHON_SUPPORT=ON \
-D BUILD_opencv_python3=ON \
-D HAVE_opencv_python3=ON \
-D OPENCV_ENABLE_NONFREE=ON \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D OPENCV_PYTHON3_INSTALL_PATH=/usr/local/lib/python3.8/dist-packages \
-D PYTHON_EXECUTABLE=/usr/bin/python3.8 \
..
如果下载失败,需要FQ
make -j 12
03.安装 OpenCV
sudo make install -j 12
04.python 测试 和 jtop 确认:
除了上面的 python 来测试。jetson 也可以用 jtop
来查看。opencv with CUDA YES
05.清理
安装后,有些文件我们将不再需要,可以安全删除:
cd ..
rm -rf opencv-4.5.4 opencv_contrib-4.5.4
重写了代码:
#include <opencv2/opencv.hpp>
#include <opencv2/cudastereo.hpp>
#include <iostream>
#include <chrono>
class StereoProcessor {
private:
cv::Ptr<cv::cuda::StereoSGM> sgbm;
cv::cuda::GpuMat cudaLeftFrame, cudaRightFrame;
cv::cuda::GpuMat cudaDisparityMap, cudaDrawColorDisparity;
public:
// https://docs.opencv.org/4.x/dd/d47/group__cudastereo.html#gafb7e5284de5f488d664c3155acb12c93
// int minDisparity=0, int numDisparities=128, int P1=10, int P2=120, int uniquenessRatio=5, int mode=cv::cuda::StereoSGM::MODE_HH4
// https://docs.opencv.org/4.x/dd/d47/group__cudastereo.html#gafb7e5284de5f488d664c3155acb12c93
StereoProcessor() : sgbm(cv::cuda::createStereoSGM(1, 64, 10, 120, 10, cv::cuda::StereoSGM::MODE_HH)) {}
void initialize(cv::Mat& left, cv::Mat& right) {
cudaLeftFrame.upload(left);
cudaRightFrame.upload(right);
cudaDisparityMap.create(left.size(), CV_16S);
cudaDrawColorDisparity.create(left.size(), CV_8UC4);
}
void computeDisparity() {
sgbm->compute(cudaLeftFrame, cudaRightFrame, cudaDisparityMap);
}
void downloadDisparity(cv::Mat& disparity) {
cv::Mat disparity_sgbm;
cudaDisparityMap.download(disparity_sgbm);
disparity_sgbm.convertTo(disparity, CV_32F, 1.0 / 16.0f);
}
};
void calcu_disparity_cuda(StereoProcessor& stereoProcessor, cv::Mat& disparity) {
auto t_a = std::chrono::high_resolution_clock::now();
stereoProcessor.computeDisparity();
auto t_b = std::chrono::high_resolution_clock::now();
stereoProcessor.downloadDisparity(disparity);
std::cout << "with cuda: " << std::chrono::duration_cast<std::chrono::microseconds>(t_b - t_a).count() / 1000 << "ms" << std::endl;
}
void get_data(int i, std::string& left_path, std::string& right_path) {
std::string data_path = "/home/nvidia/codes/libSGM/KITTI2011_10_03_drive_0042_sync/2011_10_03/2011_10_03_drive_0042_sync/";
std::string left_data_path = data_path + "image_00/data/";
std::string right_data_path = data_path + "image_01/data/";
char ss[1170];
sprintf(ss, "%010d", i);
left_path = left_data_path + ss + ".png";
right_path = right_data_path + ss + ".png";
}
int main(int argc, char** argv) {
int data_size = 1170;
StereoProcessor stereoProcessor;
for (int i = 0; i < data_size; ++i) {
std::string left_image_path, right_image_path;
get_data(i, left_image_path, right_image_path);
cv::Mat left_image = cv::imread(left_image_path, 0);
cv::Mat right_image = cv::imread(right_image_path, 0);
stereoProcessor.initialize(left_image, right_image);
cv::Mat disparity_cuda;
calcu_disparity_cuda(stereoProcessor, disparity_cuda);
cv::imshow("disparity_cuda Image", disparity_cuda);
const char c = cv::waitKey(1);
if (c == 27) // ESC
break;
}
return 0;
}
计算速度为:1242,375 像素下达到 32 FPS。