您的位置:首页 > 运维架构

基于opencv的摄像机标定

2016-03-15 20:21 344 查看


原理简述:

三维世界中的点的位置与其对应的二维投影,遵从以下公式:



其中,

M表示三维世界中的点;

[R|T]表示欧氏变换,是一个3*4矩阵

A表示相机参数矩阵,存放相机内部参数

P表示M在二维空间的投影,是一个二维点(文献1)

相机成像投影图如下所示(文献2):



摄像机标定的过程就是找到相机内参,即:矩阵A

A通常为:

|afsx|

A=|0fy|

|001|

图像平面和照相机中心间的距离为焦距f。当像素数组在传感器上偏斜的时候,需要用到倾斜参数s。在大多数情况下,s可以设置为0。于是上式可变为:

|af 0x|

A= |0 fy|

|0 01|

纵横比例参数a是在像素元素非正方形的情况下使用的。通常情况下,其为1。于是上式可变为:

|f 0x|

A= |0 fy|

|0 01|

除焦距f外,标定矩阵中剩余的唯一参数为光心(有时称为主点)的坐标c=[x y],也就是光线坐标轴和图像平面的交点。因为光心通常在图像的中心,

并且图像的坐标是从左上角开始计算的,所以光心的坐标常常接近于图像宽度和高度的一半,即x=图像宽度/2,y=图像高度/2。

重要的事情说三遍,照相机标定的唯一未知变量是焦距f。


标定步骤:

使用OpenCV进行摄像机标定,在OpenCV例程中有现成的例程程序可以实现,

/samples/cpp/tutorial_code/calib3d/camera_calibration里的程序就可以进行单目相机标定。

因为例程代码无需修改即可使用,因此,对于该例程的代码分析,在此不展开讨论,有兴趣的可以到文献[3]中查看,该博客
较详细介绍了其中函数。
在此只简单介绍下若要调用该例程生成标定矩阵,所需要做的最小工作量。
一:
准备棋盘格图标并打印,用准备标定的摄像机从不同角度拍摄10-15幅图片。
二:
在VID.xml中添加拍摄图片的路径,用于程序执行时读入图片,建议在程序当前目录下创建一个文件夹放拍摄图片,且在VID.xml中
输入路径时可用相对路径,而不是绝对路径,即便将标定程序工程拷贝到其它路径下,程序无需修改即可运行。如果图片用相对路径,
则将标定程序拷贝到其它路径下,需要修改图片的路径。如果图片路径输入有误,执行程序会出错,在本人计算机上运行错误如下:
Near the sample file you'll find the configuration file, which has detailed help of how to edit it.  It may be any OpenCV supported file format XML/YAML.
OpenCV Error: Assertion failed (src.size == dst.size && src.channels() == dst.channels()) in cvConvertScale, file /home/djt/software/opencv-3.0.0/modules/core/src/convert.cpp, line 6213
terminate called after throwing an instance of 'cv::Exception'
what():  /home/djt/software/opencv-3.0.0/modules/core/src/convert.cpp:6213: error: (-215) src.size == dst.size && src.channels() == dst.channels() in function cvConvertScale

三:
程序开始会读入配置文件in_VID5.xml,该文件对棋盘格的角点数(由你使用的棋盘格决定),即在水平(BoardSize_Width)和垂直方向(BoardSize_Height)方向各有几个角点,如我用的是7*7的棋盘格,相应参数需修改为7,如果该参数设置与你使用棋盘格图片不一致会出错,错误如下:
Near the sample file you'll find the configuration file, which has detailed help of how to edit it.  It may be any OpenCV supported file format XML/YAML.
OpenCV Error: Assertion failed (src.size == dst.size && src.channels() == dst.channels()) in cvConvertScale, file /home/djt/software/opencv-3.0.0/modules/core/src/convert.cpp, line 6213
terminate called after throwing an instance of 'cv::Exception'
what():  /home/djt/software/opencv-3.0.0/modules/core/src/convert.cpp:6213: error: (-215) src.size == dst.size && src.channels() == dst.channels() in function cvConvertScale
四:
配置文件in_VID5.xml还定义了矩阵输出文件"out_camera_data.xml“,当校正完成后,校正矩阵参数就保存到该文件中,对于.xml的读写,opencv中有专门的类进行操作,即
FileStorage类,具体用法自行百度。在校正程序中对校正矩阵的定义为Mat cameraMatrix = Mat::eye(3, 3, CV_64F);其取用方法为cameraMatrix.at<double>(0,0) = 1.0;

重点来了

在之后的程序中(如增强现实中)要是调用该矩阵,一定要将FileStorage类读入数据的校正矩阵定义为Mat cameraMatrix = Mat::eye(3, 3, CV_64F);且取用时用

cameraMatrix.at<double>(0,0) = 1.0; 而不能用cameraMatrix.at<float>(0,0) = 1.0;也不能用Mat_<float> camMatrix; camMatrix = Mat::eye(3, 3, CV_64F);否则

会因数据类型不符而导致后续程序计算错误,但却不报错。但可以通过先读到Mat cameraMatrix = Mat::eye(3, 3, CV_64F);定义变量中再逐个赋值给

Mat_<float> camMatrix1;定义矩阵。但赋值时,camMatrix1(i,j)=cameraMatrix.at<double>(i,j); double类型一定不要写错。

程序已上传到http://download.csdn.net/detail/daijuting/9467510需要的请下载。

参考资料:

主要参考以下博客,其链接如下:

[1]:/article/9623275.html

[2]:/article/9623272.html

[3]:/article/9623273.html

以及计算机视觉的两本书(以上几篇博客也主要是参考文献5):

[4]:Python计算机视觉编程 第四章

[5]:深入理解OpenCV实用计算机视觉项目解析 第二章

因为用到程序主要是opencv的一个例程,其中用到的两个官方文档如下

opencv document:

http://docs.opencv.org/2.4/doc/tutorials/calib3d/camera_calibration/camera_calibration.html

http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: