OpenCV相机标定与3D重建(65)对图像点进行去畸变处理函数undistortPoints()的使用
- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
从观测到的点坐标计算理想点坐标。
该函数类似于 undistort 和 initUndistortRectifyMap,但它操作的是稀疏点集而不是光栅图像。此外,该函数执行与 projectPoints 相反的变换。对于3D对象,它不会重建其3D坐标;但对于平面对象,如果指定了适当的旋转矩阵 R,它可以重建坐标,直到一个平移向量为止。
对于每个观测到的点坐标 (u,v),该函数计算:
x
"
←
(
u
−
c
x
)
/
f
x
y
"
←
(
v
−
c
y
)
/
f
y
(
x
′
,
y
′
)
=
u
n
d
i
s
t
o
r
t
(
x
"
,
y
"
,
distCoeffs
)
[
X
Y
W
]
T
←
R
∗
[
x
′
y
′
1
]
T
x
←
X
/
W
y
←
Y
/
W
only performed if P is specified:
u
′
←
x
f
′
x
+
c
′
x
v
′
←
y
f
′
y
+
c
′
y
\begin{array}{l} x^{"} \leftarrow (u - c_x)/f_x \\ y^{"} \leftarrow (v - c_y)/f_y \\ (x',y') = undistort(x^{"},y^{"}, \texttt{distCoeffs}) \\ {[X\,Y\,W]} ^T \leftarrow R*[x' \, y' \, 1]^T \\ x \leftarrow X/W \\ y \leftarrow Y/W \\ \text{only performed if P is specified:} \\ u' \leftarrow x {f'}_x + {c'}_x \\ v' \leftarrow y {f'}_y + {c'}_y \end{array}
x"←(u−cx)/fxy"←(v−cy)/fy(x′,y′)=undistort(x",y",distCoeffs)[XYW]T←R∗[x′y′1]Tx←X/Wy←Y/Wonly performed if P is specified:u′←xf′x+c′xv′←yf′y+c′y
其中 undistort 是一个近似的迭代算法,它根据归一化的畸变点坐标估计归一化的原始点坐标(“归一化”意味着这些坐标不依赖于相机矩阵)。
该函数可以用于立体相机或单目相机(当旋转矩阵R为空时)。
函数原型
void cv::undistortPoints
(
InputArray src,
OutputArray dst,
InputArray cameraMatrix,
InputArray distCoeffs,
InputArray R = noArray(),
InputArray P = noArray()
)
参数
- 参数src:观测到的点坐标,可以是 2xN 或 Nx2 的单通道矩阵(CV_32FC1 或 CV_64FC1),或者是 1xN 或 Nx1 的双通道矩阵(CV_32FC2 或 CV_64FC2)(或 vector)。
- 参数dst:去畸变和反向透视变换后的输出理想点坐标(1xN 或 Nx1 的双通道矩阵或 vector)。如果矩阵P 是单位矩阵或被省略,则 dst 将包含归一化的点坐标。
- 参数cameraMatrix:相机矩阵 A = [ f x 0 c x 0 f y c y 0 0 1 ] A = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} A= fx000fy0cxcy1
- 参数distCoeffs:输入的畸变系数向量 D = ( k 1 , k 2 , p 1 , p 2 , k 3 , k 4 , k 5 , k 6 , s 1 , s 2 , s 3 , s 4 , τ x , τ y ) D = (k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4, \tau_x, \tau_y) D=(k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,τx,τy)]]]]),包含 4、5、8、12 或 14 个元素。如果该向量为空,则假定为零畸变系数。
- 参数R:物体空间中的矫正变换矩阵(3x3 矩阵)。可以传递由 stereoRectify 计算得到的R1或R2。如果该矩阵为空,则使用单位变换。
- 参数P:新的相机矩阵(3x3)或新的投影矩阵(3x4),形式为 P = [ f x ′ 0 c x ′ t x 0 f y ′ c y ′ t y 0 0 1 t z ] P = \begin{bmatrix} f'_x & 0 & c'_x & t_x \\ 0 & f'_y & c'_y & t_y \\ 0 & 0 & 1 & t_z \end{bmatrix} P= fx′000fy′0cx′cy′1txtytz 。可以传递由 stereoRectify 计算得到的P1或P2。如果该矩阵为空,则使用单位新的相机矩阵。
代码示例
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
// 假设我们有一组畸变的图像点
vector< Point2f > distortedPoints = { Point2f( 320, 240 ), Point2f( 330, 250 ) };
// 相机内参矩阵和畸变系数(假设已经通过标定获得)
Mat cameraMatrix = ( Mat_< double >( 3, 3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );
Mat distCoeffs = ( Mat_< double >( 5, 1 ) << -0.28340811, 0.07395907, 0.00019359, 1.76187114e-05, 0.0 );
// 创建输出点容器
vector< Point2f > undistortedPoints;
// 可选参数:旋转矩阵 R 和新投影矩阵 P
// 对于单目相机,R 和 P 可以为空
// 注意:这里直接使用 noArray() 作为参数传递,而不是赋值给 Mat 类型变量
// Mat R = noArray(); // 错误的做法
// Mat P = noArray(); // 错误的做法
// 执行去畸变操作
undistortPoints( distortedPoints, undistortedPoints, cameraMatrix, distCoeffs, noArray(), noArray() );
// 输出结果
for ( size_t i = 0; i < undistortedPoints.size(); ++i )
{
cout << "Point " << i + 1 << ": (" << undistortedPoints[ i ].x << ", " << undistortedPoints[ i ].y << ")" << endl;
}
return 0;
}
运行结果
Point 1: (-0.00979206, -0.0186206)
Point 2: (0.00940703, 0.000575813)