单目标定:从理论到OpenCV实践

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhazhiqiang2010/article/details/82084833

(转载请注明出处:http://blog.csdn.net/zhazhiqiang/ 未经允许请勿用于商业用途)

一、针 孔摄像机模型    2

1.1 优缺点    2

1.2 针 孔摄像机模型图与公式    2

1.2.1 理想情况    2

1.2.2 实际情况    2

1.3 基本投影几何    3

1.3.1 投影变换的定义    3

1.3.2 摄像机内参数矩阵    3

二、透镜摄像机    5

2.1 优缺点    5

2.2 透镜畸变    5

2.2.1 畸变产生原因    5

2.2.2 径向畸变    5

2.2.3 切向畸变    6

2.2.4 其他畸变    7

三、旋转矩阵和平移向量    8

四、摄像机内外参数总结    8

五、摄像机标定    9

5.1 标定目的    9

5.2 单应性矩阵    9

5.3 棋盘    10

5.3.1 棋盘大小    10

5.3.2 角点数量与棋盘图片数量要求    11

5.4 OpenCV的求解理论方法    11

六、矫正    11

七、OpenCV1.1主要相关函数    12

参考文献    13

一、针 孔摄像机模型

1.1 优缺点

优点:简单好用。

缺点:真实的针孔由于不能为快速曝光收集足够的光线,因此不是得到图像的好方法。

1.2 针 孔摄像机模型图与公式

1.2.1 理想情况

描述:芯片是正方形,芯片中心在光轴上。

f:摄像机焦距

Z:摄像机到物体的距离

X:物理物体长度

x:图像上的物体长度

1.2.2 实际情况

描述:芯片是矩形(长宽不同),芯片中心不在光轴上。

实际上,芯片的中心通常不在光轴上,因此引入新的参数cx和cy;

物理世界中的点Q(X,Y,Z),以某些偏移的方式投影为点(x_srceen,y_srceen):

1.3 基本投影几何

1.3.1 投影变换的定义

1.3.2 摄像机内参数矩阵

【重要概念】

定义摄像机的参数(fx,fy,cx,cy)重新排列为3X3的矩阵,称为摄像机内参数矩阵。

二、透镜摄像机

2.1 优缺点

优点:利用透镜收集更多的光线;

缺点:背离了针 孔几何模型,而且引入透镜的畸变

2.2 透镜畸变

2.2.1 畸变产生原因

畸变产生原因:理论上讲是可能定义一种透镜而不引入任何畸变的,然后现实世界没有完美的透镜。这主要是制造上的原因,因为制作一个"球形"透镜比制作一个数学上理想的透镜更容易。而且从机械方面也很难把透镜和成像仪保持平行

两种主要的畸变:径向畸变切向畸变

2.2.2 径向畸变

【重要概念】

径向畸变:来自于透镜形状;

2.2.3 切向畸变

【重要概念】

切向畸变:来自于整个摄像机的组装过程。

2.2.4 其他畸变

三、旋转矩阵和平移向量

【重要概念】

四、摄像机内外参数总结

摄像机参数:一般一共15个相关参数:

(1)外参数6个:旋转3个参数;平移3个参数;

(2)内参数4个:fx,fy,cx,cy;

求解上述10个参数的前提是先假设每次的畸变参数为0;

(3)5个畸变参数:k1,k2,k3,p1,p2;

其中(2)和(3)都为摄像机内参数,其中k3在普通镜头不使用,鱼眼镜头要使用。

五、摄像机标定

5.1 标定目的

矫正因使用透镜而给针 孔模型带来的主要偏差。

标定的过程既给出摄像机几何模型、也给出透镜的畸变模型,即求解上述的15个相关参数。

5.2 单应性矩阵

【重要概念】

单应性矩阵主要解决外参数和内参数矩阵,且假设畸变参数为0。

在计算机视觉中,平面的单应性被定义为从一个平面到另一个平面的投影映射。

5.3 棋盘

5.3.1 棋盘大小

(1)标准

一个标准象棋棋盘,格子为7X7。

(2)非标准

(3)最小要求

最少需要4个点(3X3的棋盘点)

(4)格子多的好处

5.3.2 角点数量与棋盘图片数量要求

5.4 OpenCV求解标定的理论方法

5.4.1 摄像机标定的理论方法简介

(1)传统标定法

传统标定技术在定标的时候,需要在摄像机前放置一个特定的标定物,并认为地提供一组已知坐标的特征基元,摄像机通过寻找标定物上这些已知的特征基元来实现定标。它用到了很多射影几何方面的理论,是一种直接计算摄像机模型的方法。

(2)自标定法

自标定技术则更为灵活,它不需要特定的参照物来实现定标,是一种对环境具有很强适应性的定标技术,也是目前研究的热点。它利用环境的刚体性,通过对比多幅图像中的对应点来计算摄像机模型,但就目前的研究来看,其定标精度还无法与传统定标技术相比。

(3)张正友标定法

5.4.1 OpenCV采用的理论方法

5.4.2 张正友标定相关理论资料

(1)精简版8页《Flexible Camera Calibration by Viewing a Plane from Unknown Orientations》- Zhang1999

网址:http://www.vision.caltech.edu/bouguetj/calib_doc/papers/zhan99.pdf

(2)完整版22页《A Flexible New Technique for Camera Calibration.rar》- Zhang2000

网址:http://research.microsoft.com/~zhang/Papers/TR98-71.pdf

(3)张正友主页:

网址:http://research.microsoft.com/en-us/um/people/zhang/

(3)张正友主页中的相机标定页:

网址:http://research.microsoft.com/en-us/um/people/zhang/Calib/

5.4.3 Brown论文资料

网址:http://www.ifp.uni-stuttgart.de/lehre/vorlesungen/Aero/Brown71.pdf

六、矫正

利用棋盘标定的结果可进行畸变矫正。

七、OpenCV1.1主要相关函数

7.1 单目标定流程与对应主要函数

(1)查找棋盘角点:cvFindChessboardCorners;

(2)亚像素角点:cvFindCornerSubPix;

(3)显示角点结果:cvDrawChessboardCorners;

(4)单目标定:

[A]方式一:获取摄像机内外参数:cvCalibrateCamera2(内部包含

cvFindExtrinsicCameraParams2);

[B]方式二:根据摄像机内参数求取外参数:cvFindExtrinsicCameraParams2

注意:上述两种方式输出的是旋转向量和平移向量,如果需要转换为矩阵使用函数cvRodrigues2,该函数可以将向量和矩阵进行互转。

(5)图像畸变矫正:

[A]单目图像畸变矫正方式一(效率低):cvUndistort2;

[B]单目图像畸变矫正方式二(效率高):cvInitUndistortMap+cvRemap;

[C]双目点畸变矫正:cvUndistortPoints(注意:输入输出为点坐标,只能在双目标定中使用)。

(6)统计单目标定误差(计算3D点在图像上的投影坐标与棋盘点坐标的差值):

cvProjectPoints2+cvNorm。

注意:cvProjectPoints2输入的是旋转向量和平移向量。

7.2 主要相关函数详解

7.2.1 cvCalibrateCamera2详解

(1)函数原型

void cvCalibrateCamera2(const CvMat* object_points,

const CvMat* image_points,

const CvMat* point_counts,

CvSize image_size,

CvMat* intrinsic_matrix,//[output]

CvMat* distortion_coeffs,//[output]

CvMat* rotation_vectors=NULL,//[output]

CvMat* translation_vectors=NULL,//[output]

int flags=0

);

(2)参数注释(9个)

  • object_points

定标点的世界坐标,为3xN或者Nx3的矩阵,这里N是所有视图中点的总数。

http://www.360doc.com/content/14/0410/14/10724725_367762917.shtml

  • image_points

定标点的图像坐标,为2xN或者Nx2的矩阵,这里N是所有视图中点的总数。

  • point_counts:

向量,指定不同视图里点的数目,1xM或者Mx1向量,M是视图数目。

  • image_size:

图像大小,只用在初始化内参数时。

  • intrinsic_matrix

输出内参矩阵(A) ,如果指定

CV_CALIB_USE_INTRINSIC_GUESS和(或)CV_CALIB_FIX_ASPECT_RATION,fx、 fy、 cx和cy部分或者全部必须被初始化。

  • distortion_coeffs:

输出大小为4x1或者1x4的向量,里面为形变参数[k1, k2, p1, p2]。

  • rotation_vectors

输出大小为3xM或者Mx3的矩阵,里面为旋转向量(旋转矩阵的紧凑表示方式,具体参考函数cvRodrigues2)

  • translation_vectors:

    输出大小为3xM或Mx3的矩阵,里面为平移向量。

  • flags【重点】

不同的标志,可以是0(默认),或者下面值的组合:

  • CV_CALIB_USE_INTRINSIC_GUESS(1):内参数矩阵包含fx,fy,cx和cy的初始值。否则,(cx, cy)被初始化到图像中心(这儿用到图像大小),焦距用最小平方差方式计算得到。注意,如果内部参数已知,没有必要使用这个函数,使用cvFindExtrinsicCameraParams2则可。

  • CV_CALIB_FIX_ASPECT_RATIO(2):优化过程中认为fx和fy中只有一个独立变量,保持比例fx/fy不变,fx/fy的值跟内参数矩阵初始化时的值一样。在这种情况下,(fx, fy)的实际初始值或者从输入内存矩阵中读取(当CV_CALIB_USE_INTRINSIC_GUESS被指定时),或者采用估计值(后者情况中fx和fy可能被设置为任意值,只有比值被使用)。

  • CV_CALIB_FIX_PRINCIPAL_POINT(4):主点在全局优化过程中不变,一直在中心位置或者在其他指定的位置(当CV_CALIB_USE_INTRINSIC_GUESS设置的时候)。

  • CV_CALIB_ZERO_TANGENT_DIST(8):切向形变参数(p1, p2)被设置为0,其值在优化过程中保持为0。

  • CV_CALIB_FIX_FOCAL_LENGTH(16):该标志在优化的时候,直接使用intrinsic_matrix传递过来的

  • CV_CALIB_FIX_K1(32):固定径向畸变k1。径向畸变参数可以通过组合这些标志设置为任意值。

  • CV_CALIB_FIX_K2(64):固定径向畸变k2。径向畸变参数可以通过组合这些标志设置为任意值。

  • CV_CALIB_FIX_K3(128):固定径向畸变k3。径向畸变参数可以通过组合这些标志设置为任意值,通常设置为0。

(3)单目定标函数cvCalibrateCamera2采用怎样的 flags 比较合适?(来自[文献4])

由于一般镜头只需要计算k1,k2,p1,p2四个参数,所以我们首先要设置 CV_CALIB_FIX_K3;其次,如果所用的摄像头不是高端的、切向畸变系数非常少的,则不要设置 CV_CALIB_ZERO_TANGENT_DIST,否则单目校正误差会很大;如果事先知道摄像头内参的大概数值,并且cvCalibrateCamera2函数的第五个参数intrinsic_matrix非空,则也可设置 CV_CALIB_USE_INTRINSIC_GUESS ,以输入的intrinsic_matrix为初始估计值来加快内参的计算;其它的 flag 一般都不需要设置,对单目定标的影响不大。

7.2.2 cvFindExtrinsicCameraParams2详解

(1)函数原型

void cvFindExtrinsicCameraParams2( const CvMat* object_points,

const CvMat* image_points,

const CvMat* intrinsic_matrix,

const CvMat* distortion_coeffs,

CvMat* rotation_vector,//[output]

CvMat* translation_vector//[output]

);

(2)参数注释(6个)

  • object_points:

定标点的坐标,为3xN或者Nx3的矩阵,这里N是视图中的个数。

  • image_points:

定标点在图像内的坐标,为2xN或者Nx2的矩阵,这里N是视图中的个数。

  • intrinsic_matrix:

内参矩阵(A) 。

  • distortion_coeffs:

大小为4x1或者1x4的向量,里面为形变参数[k1,k2,p1,p2]。如果是NULL,所有的形变系数都为0。

  • rotation_vector:

输出大小为3x1或者1x3的矩阵,里面为旋转向量(旋转矩阵的紧凑表示方式,具体参考函数cvRodrigues2)。

  • translation_vector:

大小为3x1或1x3的矩阵,里面为平移向量。

7.3 单目标定示例代码

http://blog.sina.com.cn/s/blog_73ef08a80100vi49.html

八、单目标定效果不好的原因分析

(1)问题(来自[文献3]):OpenCV中用cvCalibrateCamera2 进行相机标定的精度差,标定结果不稳定。

分析:可能原因有:

A.夹角太小会导致误差较大

可能是在标定的时候标定板所在平面与成像平面(image plane)之间的夹角太小,张正友论文里的仿真数据(有噪声的数据)说明当两者夹角太小误差会很大,从张正友的论文里给出的5幅图中(http://research.microsoft.com/~zhang/Calib/),其中标定平面与成像平面的夹角分别为:8.8947、11.2325、24.4875、10.8535、9.5829(单位:度)。而且张正友的论文中也提到两幅标定板之间的位置平行放置的话,相关相当于一幅,因此在实际标定中平行放置的情况最好避免,可能有时你无形之中就犯了这个错误。

B.标定时拍摄的图片太少

虽然张正友的论文里只用了5幅图片,但是建议用10来幅左右还是必要的,因为我们实际中可能标定板用A4的纸打印出来贴在一块板上的,标定板上的世界坐标精度就不是特别高,多拍摄几幅图像能减少这方面带来的误差,而且多个角度拍摄也可能解决了问题一:标定板和成像平面夹角小的问题。

有个例子是用20幅图片进行标定的:

http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/example.html

C.图像上角点提取的不准确

用cvFindChessboardCorners函数找角点不是很好,假如拍到的图像不是完整的棋盘格的时候肯定会有问题的,而且也不少人反应用这个函数提取不出角点,建议可以用其他工具 比如:

OpenCV and MatLab Camera Calibration Toolboxes Enhancement:

http://graphics.cs.msu.ru/en/research/calibration/

Camera Calibration Toolbox for Matlab(强烈推荐):

http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/example.html

(2)建议用其他标定方法(比如Tsai)或其他标定工具进行对比

强烈推荐 用这个matlab标定工具箱来进行标定,可以和OpenCV做对比,它也是基于张正友的平面标定方法的,做得非常人性化,有误差分析、标定结果三维重建、重投影计算角点等功能 。

Camera Calibration Toolbox for Matlab:

http://www.vision.caltech.edu/bouguetj/calib_doc/

(3)使用OpenCV进行摄像机定标虽然方便,但是定标结果往往不够准确和稳定,最好是使用 Matlab标定工具箱 来进行定标,再将定标结果取回来用于立体匹配和视差计算。

参考文献

  1. [书籍]学习OpenCV:第十一章 摄像机模型与标定。

  2. [书籍]基于OpenCV的计算机视觉技术实现

  3. [博文]在OpenCV中用cvCalibrateCamera2进行相机标定

http://blog.csdn.net/zhazhiqiang/article/details/50593677

  1. [博文]双目测距与三维重建的OpenCV实现问题集锦(一)图像获取与单目定标

http://blog.csdn.net/zhazhiqiang/article/details/50593730

  1. [书籍]学习OpenCV:第十一章5。

  2. [书籍]学习OpenCV:第十一章。

  3. [书籍]学习OpenCV:第十一章2

猜你喜欢

转载自blog.csdn.net/zhazhiqiang2010/article/details/82084833