SLAM学习:相机标定(张氏标定)及opencv应用

具体的张氏标定过程参考1(获得初值):http://blog.csdn.net/PINBODEXIAOZHU/article/details/43373247

参考2(极大似然估计):http://blog.csdn.net/pinbodexiaozhu/article/details/43374181

张氏标定(单平面棋盘格的摄像机标定方法)

目的:得到相机的内参、外参和畸变系数。

过程:

  • 标定平面到图像平面的单应性,H = A[R T] ,    sx = HX
  • 标定平面建立世界坐标系,Z=0, X可通过测量标定平面获得世界坐标 ,x通过图片坐标获得像素坐标。
  • H为3*3矩阵,有八个未知参数,通过四组点对可解出具体值。(所以用棋盘格)
  • 利用旋转向量的约束求解内参。H=[h1 h2 h3] = sA[r1 r2 t] 。
  • r1 r2 正交,故r1*r2=0。旋转后长度不变,故|r1|=|r2|=1。故可建立俩个方程
  • 内参A有5个未知量,通过三个已知的不同的单应矩阵 H 可解得内参 A(所以需要改变摄像机和标定板的相对位置)
  • 通过[h1 h2 h3]  = A[r1 r2 t] 获得外参[r1 r2 t]
  • 以上为获得的初值 (角点存在噪声),进行极大似然估计(最小二乘)
  • 求得内外参将世界坐标投影到像素坐标得到m™,图片上检测到的坐标为m。最小二乘 minΣ||m-m™||²

关于opencv中标定的使用有很多参考,我主要参考了:
                 https://www.2cto.com/kf/201610/559735.html(关于函数的使用)及
                http://blog.csdn.net/u011574296/article/details/73823569(主要参考程序自己加以修改为C++的形式)
在主要想说明遇到的一个关键问题和一个理解:
      关键问题:是将标定后的参数输出的问题,在程序中标定后的参数格式为MAT形式(float)但我在calibrationcamera函数后面使用ptr,at形式的输出Mat的数据均不能得到正常的结果,如图:

SLAM学习:相机标定(张氏标定)及opencv应用_第1张图片

很明显标定后的内参结果不正确。后来对比前面参考的网站内容发现函数使用均正确,果断把问题定位在打印输出问题上,故尝试了几种Mat的数据访问,但结果是一样,使用 at 访问时程序在 at 访问处报错。然后查看参考网站内容 发现其并没有在显示上打印输出数据,而是使用保存为文件的格式。尝试将输出改为使用文件的额形式,在文件中可观察到正确结果。

SLAM学习:相机标定(张氏标定)及opencv应用_第2张图片
具体的打印输出格式我暂且没有找到可以正确的输出方法。


            一个理解:是关于坐标系的理解。很显然如果要想正确的标定出结果,必须把标定板在世界坐标的点与图片上的点相对应,这就涉及到世界坐标系的建立问题。我参考了:http://blog.csdn.net/shenxiaolu1984/article/details/50165635
             可能时我没能理解作者的具体意思,在我多次尝试后,可以确定的是坐标系确实时如作者所说与object_point与 findChessboardCorners检测顺序有关。但具体的坐标建立我有自己的理解。
           
               

SLAM学习:相机标定(张氏标定)及opencv应用_第3张图片       SLAM学习:相机标定(张氏标定)及opencv应用_第4张图片

检测到一个角点图,检测顺序如作者所说 先由右下方红色(右到左)再向上到左上方。可以断点查看数据进行确认。然后object_point的话按照常规的我们会定义为先x不变y变化,即按我下面的程序:

	bool MyCalibration::ComputeWorldPoint()
	{
		for (int n = 0; n < imgCount; n++)
		{
			vector temp;
			for (int i = 0; i 
断点查看到数据:如上图。
          我们即可发现世界坐标系下的(0,0,0)点即为检测道德第一个角点为图片的右下角。所以世界坐标系的坐标原点认为是标定板右下角第一个角点。然后图片坐标系下 点先向左移动的。对应的worldPoint是y轴变化的,所以 y 轴指向左方,同理 X 轴指向上方,z轴可由右手法则得到。


你可能感兴趣的:(OpenCV,SLAM)