博客转载自:http://blog.csdn.net/Loser__Wang/article/details/51811347

本文目的在于记录如何使用MATLAB做摄像机标定,并通过opencv进行校正后的显示。

首先关于校正的基本知识通过OpenCV官网的介绍即可简单了解:

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

对于摄像机我们所关心的主要参数为摄像机内参,以及几个畸变系数。上面的连接中后半部分也给了如何标定,然而OpenCV自带的标定程序稍显繁琐。因而在本文中我主推使用MATLAB的工具箱。下面让我们开始标定过程。

标定板

标定的最开始阶段最需要的肯定是标定板。两种方法,直接从opencv官网上能下载到: 
http://docs.opencv.org/2.4/_downloads/pattern.png

方法二:逼格满满(MATLAB)

J = (checkerboard(300,4,5)>0.5);
figure, imshow(J);

采集数据

那么有了棋盘格之后自然是需要进行照片了。不多说,直接上程序。按q键即可保存图像,尽量把镜头的各个角度都覆盖好。

#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, 320);
//inputVideo.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
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;
}

保存大约15到20张即可。大家可以看到我的方法,直接对着实验室的屏幕拍摄的。这个阶段有个注意事项就是测量好屏幕上每个方格的大小,这个标定的时候会用到。

进行标定

直接而在MATLAB的Command Window里面输入cameraCalibrator即可调用标定应用。

首先先把之前照好的图像添加进去,这是出现:

这就是之前让你记录的标定板中每个方格的大小。 输入无误后就涉及到最关键的一步了(MATLAB的这个实在太方便了,都是傻瓜式操作),选择参数。

为什么说他关键呢,因为如果你仔细阅读了OpenCV的说明之后你会大概明白畸变参数,总共有五个,径向畸变3个(k1,k2,k3)和切向畸变2个(p1,p2)。 
径向畸变

切向畸变

以及在OpenCV中的畸变系数的排列(这点一定要注意k1,k2,p1,p2,k3),千万不要以为k是连着的。

并且通过实验表明,三个参数的时候由于k3所对应的非线性较为剧烈。估计的不好,容易产生极大的扭曲,所以我们在MATLAB中选择使用两参数,并且选择错切和桶形畸变。

点击开始后等待一段时间即可完成标定。并且MATLAB给出的可视化还是很不错的,可以对比校正前后的样子

点击show Undistorted即可看到无畸变的图像

到这为止,你已经完成了标定过程。选择导出参数,即可把参数进行保存。

保存后可以退出标定应用,在MATLAB主界面中将保存的Mat文件打开

第二行就是参数

里面的RadialDistortion对应k1,k2,k3设置为0了。 
TangentialDistortion对应p1,p2。 
IntrinsicMatrix对应内参,注意这个和OpenCV中是转置的关系,注意不要搞错。

对应

OpenCV中查看标定的结果

#include "opencv2/opencv.hpp"
#include <iostream> using namespace cv;
using namespace std; int main()
{
VideoCapture inputVideo(0);
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) = 4.450537506243416e+02;
cameraMatrix.at<double>(0, 1) = 0.192095145445498;
cameraMatrix.at<double>(0, 2) = 3.271489590204837e+02;
cameraMatrix.at<double>(1, 1) = 4.473690628394497e+02;
cameraMatrix.at<double>(1, 2) = 2.442734958206504e+02; Mat distCoeffs = Mat::zeros(5, 1, CV_64F);
distCoeffs.at<double>(0, 0) = -0.320311439187776;
distCoeffs.at<double>(1, 0) = 0.117708464407889;
distCoeffs.at<double>(2, 0) = -0.00548954846049678;
distCoeffs.at<double>(3, 0) = 0.00141925006352090;
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;
}

修复之前和之后的结果对比

还有就是之前讨论的为什么选2系数而不是3系数。因为。。。。。。。 下面是三系数的修正结果,惨不忍睹啊

相机标定与矫正opencv+MATLAB的更多相关文章

  1. 使用OpenCV进行相机标定

    1. 使用OpenCV进行标定 相机已经有很长一段历史了.但是,伴随着20世纪后期的廉价针孔照相机的问世,它们已经变成我们日常生活的一种常见的存在.不幸的是,这种廉价是由代价的:显著的变形.幸运的是, ...

  2. 【视频开发】【计算机视觉】相机标定(Camera calibration)原理、步骤

    相机标定(Camera calibration)原理.步骤 author@jason_ql(lql0716)  http://blog.csdn.net/lql0716 在图像测量过程以及机器视觉应用 ...

  3. Camera Calibration 相机标定

    Camera Calibration 相机标定 一.相机标定方法 在opencv中提供了一组函数用于实现相机的标定,标定返回的值包括:相机内参矩阵(fx fy xc yc).相机外参矩阵(R t)以及 ...

  4. 相机标定过程(opencv) + matlab参数导入opencv + matlab标定和矫正

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 辛苦原创所得,转载请注明出处 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ...

  5. 相机标定 matlab opencv ROS三种方法标定步骤(1)

    一 . 理解摄像机模型,网上有很多讲解的十分详细,在这里我只是记录我的整合出来的资料和我的部分理解 计算机视觉领域中常见的三个坐标系:图像坐标系,相机坐标系,世界坐标系,实际上就是要用矩阵来表 示各个 ...

  6. 相机标定 matlab opencv ROS三种方法标定步骤(2)

    二  ubuntu下Opencv的相机标定 一般直接用Opencv的源码就可以进行相机的标定,但是可能只是会实现结果,却不懂实现的过程,我也是模模糊糊的看了<计算机视觉中的多视图几何>以及 ...

  7. 相机标定 matlab opencv ROS三种方法标定步骤(3)

    三 ,  ROS 环境下 如何进行相机标定 刚开始做到的时候遇到一些问题没有记录下来,现在回头写的时候都是没有错误的结果了,首先使用ROS标定相机, 要知道如何查看节点之间的流程图  rosrun r ...

  8. 相机标定问题-Matlab & Py-Opencv

    一.相机标定基本理论 1.相机成像系统介绍 图中总共有4个坐标系: 图像坐标系:Op    坐标表示方法(u,v)                 Unit:Dots(个) 成像坐标系:Oi      ...

  9. Opencv——相机标定

    相机标定的目的:获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像. 相机标定的输入:标定图像上所有内角 ...

随机推荐

  1. JS和css实现检测移动设备方向的变化并判断横竖屏幕

    这篇文章主要介绍了JS和css实现检测移动设备方向的变化并判断横竖屏幕,本文分别给出实现代码,需要的朋友可以参考下 方法一:用触发手机的横屏和竖屏之间的切换的事件  [自测可用, chrome , 手 ...

  2. MVC四大筛选器—AuthorizeFilter

    在Action的执行中包括两个重要的部分,一个是Action方法本身逻辑代码的执行,第二个就是Action方法的筛选器的执行. MVC4中筛选器都是以AOP(面向方面编程)的方式来设计的,通过对Act ...

  3. 2733. [HNOI2012]永无乡【平衡树-splay】

    Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以 ...

  4. 【node.js】Stream(流)

    Stream 有四种流类型: Readable - 可读操作. Writable - 可写操作. Duplex - 可读可写操作. Transform - 操作被写入数据,然后读出结果. 所有的 St ...

  5. vagrant之道(即其工作流程)

    原文http://mitchellh.com/the-tao-of-vagrant The Tao of Vagrant 在安装vagrant或了解它如何工作之前,了解vagrant在实际工作环境中的 ...

  6. mysql 二进制日志binary log操作简单命令

    show master status \G; #查看当前正在记录的二进制日志 show binary logs; #查看binary log 所有文件列表 show binlog events; #查 ...

  7. c++——静态成员变量成员函数

    静态成员变量成员函数 思考:每个变量,拥有属性.有没有一些属性,归所有对象拥有? 4.1静态成员变量 1)定义静态成员变量 关键字 static 可以用于说明一个类的成员, 静态成员提供了一个同类对象 ...

  8. java基础二 java的跨平台特性

    一:java跨平台的特性: 1.生成不平台无关系的字节码. 2.通过和平台有关的jvm即java虚拟机来执行字节码.jvm不跨平台. 图示: 疑问:1.为什么我们不直接写字节码? 因为字节码只有jvm ...

  9. Spring AOP源码分析(三)创建AOP代理

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.获取增强器 1. 普通增强器的获取 2. 增加同步实例化增强 ...

  10. CommonJS、AMD、CMD、NodeJs、RequireJS到底有什么联系?

    JS中的模块规范(CommonJS,AMD,CMD),如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范,本文包括这三个规范的来源及对应的产物的原理. 一.C ...