前言:


         解决相机的标定问题!接下来介绍Matlab 进行相机标定的流程操作!


         这种标定的方式在网上有很多的公式啊,原理讲解,这里只是在应用上进行介绍!


         当然了,还是需要简单了解下标定基础知识的:  点击打开链接



          http://docs.opencv.org/2.4/_downloads/pattern.png


首先就是进行标定板的图像采集


       对于标定板,由于时间有限,就不采用打印的方式了,我直接在网页上显示!环保绿色!


         

OPENCV 对焦 opencv相机标定步骤_MATLAB


     标定嘛,肯定需要具体尺寸样标的,所以我直接在电脑上量取,这个误差在小范围内可以允许!




OPENCV 对焦 opencv相机标定步骤_VS2017_02


如你所见我测的数据是33mm,这里的数据等会在Matlab的 Camera Calibrator是要使用的!


这里附上OpenCV简单的图片采集程序,按‘q' 获取,按esc退出!

#include "opencv2/opencv.hpp"
#include <string>
#include <iostream>


using namespace cv;
using namespace std;

int main()
{
	VideoCapture inputVideo(0);
	inputVideo.set(CV_CAP_PROP_FRAME_WIDTH, 800);
	inputVideo.set(CV_CAP_PROP_FRAME_HEIGHT, 600);
	if (!inputVideo.isOpened())
	{
		cout << "Could not open the input video " << endl;
		return -1;
	}
	Mat frame;
	string imgname;
	int f = 1;
	while (1) //Show the image captured in the window and repeat
	{
		inputVideo >> frame;              // read
		if (frame.empty()) break;         // check if at end
		imshow("Camera", frame);
		char key = waitKey(1);
		if (key == 27)break;
		if (key == 'q' || key == 'Q')
		{
			imgname = to_string(f++) + ".jpg";
			imwrite(imgname, frame);
		}
	}
	cout << "Finished writing" << endl;
	return 0;
}

注意这里inputVideo.set(CV_CAP_PROP_FRAME_WIDTH, 800);


inputVideo.set(CV_CAP_PROP_FRAME_HEIGHT, 600);
如果没有设置,OpenCV直接按默认大小的获取图像尺寸!



接下来就是进行多角度的拍摄,角度越丰富越好! 


OPENCV 对焦 opencv相机标定步骤_MATLAB_03

因为我是VS2017,且没有规定路径,所以图片直接存储在项目文件夹中!



MATLAB操作

如下图找到  Camera Calibrator



OPENCV 对焦 opencv相机标定步骤_VS2017_04



运行可以看到



OPENCV 对焦 opencv相机标定步骤_OpenCV_05


点击Add Images时,会显示:



OPENCV 对焦 opencv相机标定步骤_MATLAB_06


注意这里是要输入黑白正方体的大小的,在上面的测定中,显示的是33mm,所以这里填写33



注意这里的图片还是要多一点:



OPENCV 对焦 opencv相机标定步骤_OpenCV_07


然后选定以下参数:


为了防止可能产生极大的扭曲,所以选择使用两参数,并且选择错切和桶形畸变。



OPENCV 对焦 opencv相机标定步骤_ide_08

直接点击Calibrate 就可以了


然后保存Camera Parameters就可以了



这是矫正前的图片:

OPENCV 对焦 opencv相机标定步骤_MATLAB_09


点击show Undistorted即可看到校正后的图像:




OPENCV 对焦 opencv相机标定步骤_MATLAB_10



数据分析:



OPENCV 对焦 opencv相机标定步骤_MATLAB_11



白畸变参数,总共有五个,径向畸变3个(k1,k2,k3)和切向畸变2个(p1,p2)。

径向畸变:

OPENCV 对焦 opencv相机标定步骤_MATLAB_12


切向畸变:

OPENCV 对焦 opencv相机标定步骤_VS2017_13


以及在OpenCV中的畸变系数的排列(这点一定要注意k1,k2,p1,p2,k3)。

OPENCV 对焦 opencv相机标定步骤_OpenCV_14



OPENCV 对焦 opencv相机标定步骤_OpenCV_15


对应 k1 k2      k3由于前面选择

OPENCV 对焦 opencv相机标定步骤_VS2017_16

,所以这里就为0



OPENCV 对焦 opencv相机标定步骤_MATLAB_17

对应 p1 p2




OPENCV 对焦 opencv相机标定步骤_OPENCV 对焦_18



对应

OPENCV 对焦 opencv相机标定步骤_OPENCV 对焦_19


矫正代码示例:

#include "opencv2/opencv.hpp"
#include <string>
#include <iostream>


using namespace cv;
using namespace std;

int main()
{
	VideoCapture inputVideo(1);
	inputVideo.set(CV_CAP_PROP_FRAME_WIDTH, 800);
	inputVideo.set(CV_CAP_PROP_FRAME_HEIGHT, 600);
	if (!inputVideo.isOpened())
	{
		cout << "Could not open the input video: " << endl;
		return -1;
	}
	Mat frame;
	Mat frameCalibration;

	inputVideo >> frame;
	Mat cameraMatrix = Mat::eye(3, 3, CV_64F);
	cameraMatrix.at<double>(0, 0) = 917.052472085750;
	cameraMatrix.at<double>(0, 1) = 0.657056681717874;
	cameraMatrix.at<double>(0, 2) = 408.884053678499;
	cameraMatrix.at<double>(1, 1) = 916.541676777971;
	cameraMatrix.at<double>(1, 2) = 332.189066871859;

	Mat distCoeffs = Mat::zeros(5, 1, CV_64F);
	distCoeffs.at<double>(0, 0) = -0.108750634204250;
	distCoeffs.at<double>(1, 0) = -0.155068804309725;
	distCoeffs.at<double>(2, 0) = -0.00261486335789016;
	distCoeffs.at<double>(3, 0) = 0.00154770538482982;
	distCoeffs.at<double>(4, 0) = 0;

	Mat view, rview, map1, map2;
	Size imageSize;

	imageSize = frame.size();
	initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(),
		getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0),
		imageSize, CV_16SC2, map1, map2);


	while (1) //Show the image captured in the window and repeat
	{
		inputVideo >> frame;              // read
		if (frame.empty()) break;         // check if at end
		remap(frame, frameCalibration, map1, map2, INTER_LINEAR);
		imshow("Origianl", frame);
		imshow("Calibration", frameCalibration);
		char key = waitKey(1);
		if (key == 27 || key == 'q' || key == 'Q')break;
	}
	return 0;
}


以上为OpenCV提供的简单 代码示例!


以下为原来的图像:


OPENCV 对焦 opencv相机标定步骤_OPENCV 对焦_20


以下为矫正后的图像:



OPENCV 对焦 opencv相机标定步骤_ide_21



以上为基本的操作流程,可见Matlab 是有多么的强大!


至于矫正后对于那个黑色区域怎么办呢?  可以直接矩形框选中间区域就行了。



相机无畸变后,我们就可以把真实世界的坐标,直接转化为图像里的坐标! 依据像素做有意思的事情! 例如我曾经利用几何原理做过扫描线激光的三维重建! 这个原理也就是现在市面上的短距离激光雷达的基本结构,区别就是,我是三维的。


有误希望指点!