- 操作系统: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)