利用OPENCV中基于张友正标定法的camera_calibration进行单目相机标定

  • 张友正标定法简介

(整合自 )
(整合自https://www.jianshu.com/p/9d2fe4c2e3b7

”张正友标定”是指张正友教授1998年提出的单平面棋盘格的摄像机标定方法。文中提出的方法介于传统标定法和自标定法之间,但克服了传统标定法需要的高精度标定物的缺点,而仅需使用一个打印出来的棋盘格就可以。同时也相对于自标定而言,提高了精度,便于操作。因此张氏标定法被广泛应用于计算机视觉方面。

其中limmmy写的非常好,这是地址
但是出于个人学习目的,我还是自己进行二次书写。

python张定友标定_特征点

请看上图,以第一个等号左右为例,S是尺度因子代表着长度;(u、v、1)是某一个特征点在像素坐标系下的坐标,1是齐次化的结果;

等式右边(X、Y、Z、1)是此特征点所代表的实物点在世界坐标系下的位置,1是齐次化的结果;

右边倒数第二个是变化矩阵,由旋转变换R和平移变换t组成,到这里为止,从世界坐标X变成了相机坐标x;

右边倒数第三个和第四个分别是投影矩阵和畸变矩阵,前者是由小孔成像几何原理推导,后者是相机真正的内参,即X\Y轴的拉伸畸变程度,αβ,关于X\Y方向的位置偏移程度,cx,cy。两个矩阵共同组成第二个等号后的第一个矩阵——相机内参矩阵K。

下面真正进入张友正标定法

将上面式子中的相机内参矩阵K和变换矩阵T矩阵相乘,得到单应性矩阵H,H=【h1,h2,h3】,同时变换矩阵T是4×4的矩阵可以表示为T=【r1,r2,r3,t】 (都是用新参数表示原矩阵的列向量)

将投影关系定义为棋盘位于Z=0,则KT=【r1,r2,r3,t】【 X,Y,0,1】T可化简为T=【r1,r2,t】[X,Y,1]T,(括号外的T代表转置)。

所以得到以下关系,其中A即为相机内参矩阵K去掉最右边全是0的那一列。

python张定友标定_计算机视觉_02


A中包含4个畸变参数,在A外有一个尺度因子,和r1,r2,t这三个变换系数,所以H矩阵一共有8个未知数,所以有8个自由度,需要4对匹配点进行求解,高翔博士的是《视觉SLAM十四讲》中是使用直接线性变换法,把H元素(9维)一个一个提取出来变成线性向量——x,和4对匹配点的像素坐标(已知数)——从中提取出a和b,组成aX=b,对X进行求解。得到H。

计算内参矩阵!!!!!

python张定友标定_xml_03


此式是加入了尺度因子的H=AT‘,由于变换矩阵T中的旋转矩阵R是一个正交阵,所以r1,r2正交即内积为0,R的模为1,则r1,r1的模也为1. 将h用r表示。

python张定友标定_计算机视觉_04

同时由于r具有正交的特点,用上面两式做内积有:r1与r2的内积

python张定友标定_python张定友标定_05


现在开始为最终的计算准备式子:

python张定友标定_ci_06


把B的定义带到hAAh那个式子中得到hBh=vb的左边,hBh=vb中得到右边vb的过程和前面求H矩阵中的h一样,有一个配凑的过程,就是把左边完全列出来,在从里面提取b组成一个向量,那剩下的另一个向量就是v了,把复杂矩阵分解成向量的内积。

python张定友标定_特征点_07


此时v知道了,它是由h组成的,而h之前已经利用H求出来了。这个时候注意红框里的式子,上面的是前面说过的两个正交向量的内积——为约束一,下面的的是两个正交向量分别与自身的内积,由于模为1且相等所以成为——约束二

二者联立:(根据上图中第二个式子hi B hj = vij b, 和红框中第一个式子 分析得 h1 A A h2 =h1 B h2 = v12 b =0——得到了最终解析式得第一式;同理红框第二式右边移到左边后做相同处理得到解析式第二式。),

经过整理得到

python张定友标定_计算机视觉_08


Vij全部式由已知得h表示,未知数只有b,则相当于求其次方程ax=0结果为

python张定友标定_xml_09


以上推导图片整合自https://www.jianshu.com/p/9d2fe4c2e3b7

下面是我在利用opencv3.1.0中提供得camera_calibration中得标定程序进行标定时得心得

1.配置文件。
1.1 配置文件中,下面分别时棋牌得横纵方向黑白块得交点数

<!-- Number of inner corners per a item row and column. (square, circle) -->
  <BoardSize_Width> 7</BoardSize_Width>
  <BoardSize_Height>7</BoardSize_Height>

然后下面第一个是方块得边长单位是mm,下面得是要求得图像输入,只输入数字则代表系统相机代号,不过一般虚拟机里刚开始是没有相机的;如果是图像和视频就需要给出绝对地址。

<!-- The size of a square in some user defined metric system (pixel, millimeter)-->
  <Square_Size>17</Square_Size>
  
  <!-- The type of input used for camera calibration. One of: CHESSBOARD CIRCLES_GRID ASYMMETRIC_CIRCLES_GRID -->
  <Calibrate_Pattern>"CHESSBOARD"</Calibrate_Pattern>
  
  <!-- The input to use for calibration. 
  To use an input camera -> give the ID of the camera, like "1"
  To use an input video  -> give the path of the input video, like "/tmp/x.avi"
  To use an image list   -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml"
  -->

图片是需要生成IMAGELIST得,可以手动输入到example给得VID5.XML中,也可以在opencv源文件里找到imagelist_creator.cpp进行编译自己制作任意数量图片得image list。

python张定友标定_计算机视觉_10


我使用了15张上面那样类似得笔记本电脑拍摄得图片。

最终得到得结果如下

<?xml version="1.0"?>
<opencv_storage>
<calibration_time>"Mon 01 Jun 2020 08:05:54 PM PDT"</calibration_time>
<nr_of_frames>11</nr_of_frames>
<image_width>640</image_width>
<image_height>480</image_height>
<board_width>7</board_width>
<board_height>7</board_height>
<square_size>17.</square_size>
<fix_aspect_ratio>1.</fix_aspect_ratio>
<!-- flags: +fix_aspectRatio +fix_principal_point +zero_tangent_dist -->
<flags>6158</flags>
<fisheye_model>0</fisheye_model>
<camera_matrix type_id="opencv-matrix">
  <rows>3</rows>
  <cols>3</cols>
  <dt>d</dt>
  <data>
    8.4969512886687153e+02 0. 3.1950000000000000e+02 0.
    8.4969512886687153e+02 2.3950000000000000e+02 0. 0. 1.</data></camera_matrix>

即fx为 8.4969512886687153e+02,cx为3.1950000000000000e+02,fy为 8.4969512886687153e+02,cy为2.3950000000000000e+02

以上内容均属于本人学习记录所用,不希望产生收益。