双目立体视觉的整体流程包括:图像获取、双目标定、双目矫正、立体匹配、三维重建。
图像获取
双目相机拍摄获取 左右目图像
双目标定
内参 | 外参 |
---|---|
相机矩阵 | 旋转矩阵 |
畸变系数 | 平移向量 |
《Learning OpenCV》中对于 Translation 和 Rotation 的图示是这样的:
双目矫正
通过 OpenCV函数 stereoRectify,包括 畸变矫正 和 立体矫正 。
输出参数 |
---|
左目 矫正矩阵(旋转矩阵) (3x3) |
右目 矫正矩阵(旋转矩阵) (3x3) |
左目 投影矩阵 (3x4) |
右目 投影矩阵 (3x4) |
disparity-to-depth 映射矩阵 (4x4) |
其中,
\begin{aligned}
P_1 =
\begin{bmatrix}
f & 0 & c_x & 0 \
0 & f & c_y & 0 \
0 & 0 & 1 & 0
\end{bmatrix}
\end{aligned}
\begin{aligned}
P_2 =
\begin{bmatrix}
f & 0 & c_x & T_x \cdot f \
0 & f & c_y & 0 \
0 & 0 & 1 & 0
\end{bmatrix}
\end{aligned}
通过
可计算出 基线 长度:
\begin{aligned}
baseline = - T_x = - \frac{{P_2}_{03}}{f_x}
\end{aligned}
- ethz-asl/image_undistort: A compact package for undistorting images directly from kalibr calibration files. Can also perform dense stereo estimation.
立体匹配
视差计算
通过 OpenCV函数 stereoBM (block matching algorithm),生成 视差图(Disparity Map) (CV_16S or CV_32F)
disparity map from stereoBM of OpenCV :
It has the same size as the input images. When disptypeCV_16S, the map is a 16-bit signed single-channel image, containing disparity values scaled by 16. To get the true disparity values from such fixed-point representation, you will need to divide each disp element by 16. If disptypeCV_32F, the disparity map will already contain the real disparity values on output.
So if you’ve chosen disptype = CV_16S during computation, you can access a pixel at pixel-position (X,Y) by: short pixVal = disparity.at<short>(Y,X);
, while the disparity value is float disparity = pixVal / 16.0f;
; if you’ve chosen disptype = CV_32F during computation, you can access the disparity directly: float disparity = disparity.at<float>(Y,X);
三维重建
深度计算
深度计算公式如下,通过遍历图像生成 深度图
\begin{aligned}
Z = depth = \frac{f_x \cdot baseline}{disparity}
\end{aligned}
其中,
代表 视差图 坐标值
图像类型
- 单位meter --> 32FC1
- 单位millimeter --> 16UC1
三维点坐标计算
- 根据 小孔成像模型,已知
和 相机内参 可计算出 三维点坐标,从而生成 三维点云
\begin{aligned}
\begin{cases}
Z = depth \
X = \frac{u-c_x}{f_x} \cdot Z \
Y = \frac{v-c_y}{f_y} \cdot Z
\end{cases}
\end{aligned}