关于camera calibration以后三维空间和二维图像之间的映射关系

  • Post author:
  • Post category:其他



关于camera calibration以后



三维



空间和二维图像之间的映射关系的讨论






多对一的映射




在三维空间内,任意曲面都可以通过摄像头的映射,投影到一个二维的图像之间。平行的三维空间的曲面重叠映射到同一个二维图像上,通过透明和重叠,形成一组实际的画面。平行的曲面上对应的无穷多个点映射到二维图像上一个相同的点,形成多对一的映射关系。




所以实际的三维空间在经过摄像头投影到图像上的变换,是一组无穷多的三维点映射到一个二维点的变换。据此,当摄像头标定好以后(摄像头的标定在此不再赘述,实例已经很丰富了),一个已知的三维点可以通过变换求得唯一确定对应的二维点,但是一个已知的二维点,必须在已知三维点之间的一个关系时(最基本的就是要锁定三维空间中一个确定的曲面),才能求得一个唯一确定对应的三维点。






三维点到二维点的映射




根据张正友前辈的论文,摄像头的基本工作原理如下




s[x1 x2 1]T=A[R1 R2 R3 t][X1 X2 X3 1]T




x1 x2为二维点的坐标,X1 X2 X3为三维点的坐标,A(3×3)为intrinsic matrix,[R1(3×1) R2(3×1) R3(3×1)]为rotation matrix, t(3×1)为translation vector。[]T为矩阵的旋转。




化简为s[x1 x2 1]T = A([R1 R2 R3][X1 X2 X3 ]T+t)




将三维点的坐标X1 X2 X3带入右边的矩阵算式,运算结果为[sX1 sX2 s]。s的值会随着选取三维点的不同而变化,不是一个常量,但是可以通过这个等式求出来特定的三维点的特定的s值。这样x1=sx1/s, x2=sx2/s便可求出来三维点对应的二维点的坐标。




用opencv的矩阵运算的方程cvGEMM()可以进行如下的编程:




cvGEMM(rotation_matrix,3D_point,1,translation_vector,1,output_vector,0);




cvGEMM(intrinsic_matrix,output_vector,1,0,0,2D_point,0);




x1 = cvGetReal2D(2D_point,0,0);




x2 = cvGetReal2D(2D_point,1,0);




s = cvGetReal2D(2D_point,2,0);




x1 = x1 / s;




x2 = x2 / s;




output_vector为[R1 R2 R3][X1 X2 X3 ]T+t的运算结果。




2D_point, 3D_point, output_vector为3×1的矩阵。




Intrinsic_matrix内矩阵,rotation_matrix旋转矩阵,translation_vector平移向量。




x1 x2即为3D_point对应的图像中二维点的坐标,x3为参数s的值。






二维点到三维点的映射




首先要在选定的三维空间中确定一个唯一的对应曲面(广义的曲面,包括平面),唯一的曲面确定后,三维点坐标可以化简如下:




3D_point=[X1 X2 f(X1,X2)]




则[R1 R2 R3][X1 X2 X3 ]T+t的运算结果为:




[(R11X1+R12X2+R13f(X1,X2)+t11)




(R21X1+R22X2+R23f(X1,X2)+t21)




(R31X1+R32X2+R33f(X1,X2)+t31)]




可以写成矩阵形式[B1 B2 Bt][X1 X2 1]T (B=[B1 B2 Bt])




在已知X3点的坐标时(比较常见的情况),f(X1 X2)=X3 可以写成一个常函数,这个时候,就可以求出在已知X3的坐标时B1 B2 Bt对应的值。




B1=R1  B2=R2  Bt=R3+t






s[x1 x2 1]T=A[R1 R2 R3 t][X1 X2 X3 1]T可以化简为




s[x1 x2 1]T=AB[X1 X2 1]




可以求出[X1/s X2/s 1/s]=(AB)-1[x1 x2 1]。将二维点带入右边算式,即可求出已知X3坐标的对应的三维的点。




用opencv编程为




cvGEMM(intrinsic_matrix,rotation_tanslation_matrix,1,0,0,fundamental_matrix,0);




cvInvert(fundamental_matrix,fundamental_matrix,CV_LU);




cvGEMM(fundamental_matrix,2D_point,1,0,0,3D_point,0);




X1 = cvGetReal2D(3D_point,0,0);




X2 = cvGetReal2D(3D_point,1,0);




s = cvGetReal2D(3D_point,2,0);




X1 = X1 / s;




X2 = X2 / s;




rotation_translation_matrix即为矩阵B,即[R1 R2 (X3R3+t)],可以单一赋值完成。




Fundamental_matrix(3×3) 为AB相乘的逆矩阵,




X1 X2 X3为2D_point对应的显示世界中三维点的坐标,X3坐标已知。






至此完成了




已知三维点3D_point = [X1 X2 X3]的情况下求解二维对应点2D_point = [x1 x2 s]的算法和



已知二维点 2D_point=[x1 x2 1]和X3的具体坐标,求解三维对应映射点3D_point = [X1 X2 X3]的算法,希望能对大家有所帮助。

原文路径: http://www.opencv.org.cn/forum.php?highlight=三维&mod=viewthread&tid=9790