前言:
解决相机的标定问题!接下来介绍Matlab 进行相机标定的流程操作!
这种标定的方式在网上有很多的公式啊,原理讲解,这里只是在应用上进行介绍!
当然了,还是需要简单了解下标定基础知识的: 点击打开链接
:
http://docs.opencv.org/2.4/_downloads/pattern.png
首先就是进行标定板的图像采集
对于标定板,由于时间有限,就不采用打印的方式了,我直接在网页上显示!环保绿色!
标定嘛,肯定需要具体尺寸样标的,所以我直接在电脑上量取,这个误差在小范围内可以允许!
如你所见我测的数据是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直接按默认大小的获取图像尺寸!
接下来就是进行多角度的拍摄,角度越丰富越好!
因为我是VS2017,且没有规定路径,所以图片直接存储在项目文件夹中!
MATLAB操作
如下图找到 Camera Calibrator
运行可以看到
点击Add Images时,会显示:
注意这里是要输入黑白正方体的大小的,在上面的测定中,显示的是33mm,所以这里填写33
注意这里的图片还是要多一点:
然后选定以下参数:
为了防止可能产生极大的扭曲,所以选择使用两参数,并且选择错切和桶形畸变。
直接点击Calibrate 就可以了
然后保存Camera Parameters就可以了
这是矫正前的图片:
点击show Undistorted即可看到校正后的图像:
数据分析:
白畸变参数,总共有五个,径向畸变3个(k1,k2,k3)和切向畸变2个(p1,p2)。
径向畸变:
切向畸变:
以及在OpenCV中的畸变系数的排列(这点一定要注意k1,k2,p1,p2,k3)。
对应 k1 k2 k3由于前面选择
,所以这里就为0
对应 p1 p2
对应
矫正代码示例:
#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提供的简单 代码示例!
以下为原来的图像:
以下为矫正后的图像:
以上为基本的操作流程,可见Matlab 是有多么的强大!
至于矫正后对于那个黑色区域怎么办呢? 可以直接矩形框选中间区域就行了。
相机无畸变后,我们就可以把真实世界的坐标,直接转化为图像里的坐标! 依据像素做有意思的事情! 例如我曾经利用几何原理做过扫描线激光的三维重建! 这个原理也就是现在市面上的短距离激光雷达的基本结构,区别就是,我是三维的。
有误希望指点!