基于 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

算法流程:

  1. 双目深度估计算法流程

image

双目相机标定资料

  1. 使用 matlab 进行相机标定
  2. 使用 opencv 进行相机标定 C++
  3. 使用 opencv 进行相机标定 python
  4. Camera Calibration-opencv(python)
  5. 相机标定知识汇总

SGBM 资料:

  1. Accurate and Efficient Stereo Processing by Semi-Global Matching and Mutual
    Information--SGM 算法
  2. 基于python的SGBM参数影响效果
  3. SGBM 双目立体视觉资料
  4. SGBM 视频教程

开源代码仓库:

  1. jetson-stereo-depth
  2. VPI 新版本例子
  3. libsgm--重写的sgm 算法的 cuda 实现
  4. Conventional SGBM depth ranging + yolov5 object detection with deployment on Jeston nano

3. 1 基于 VPI 的双目深度估计

VPI 教程:

  1. 编写Python加速图像处理管道的简短教程
  2. nvidia VPI 官方视频资料
  3. nvidia VPI 官方文档
  4. nvidia 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:

参考: 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

image

03.安装 OpenCV

sudo make install -j 12

image

04.python 测试 和 jtop 确认:

除了上面的 python 来测试。jetson 也可以用 jtop 来查看。opencv with CUDA YES

image

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。

posted @ 2024-01-15 15:31  cold_moon  阅读(39)  评论(0编辑  收藏  举报