相机的标定是所有人走进视觉世界需要做的第一件事,辣么多的视觉标定原理解释你可以随便在网上找到,这里只讲到底如何去实现,也算是给刚入门的朋友做个简单的分享。

1.单目相机标定的工程源码

  首先请到同性交友网站Github上下载工程源码(https://github.com/Zhanggx0102/Camera_Calibration),注意以下几点:

1).这是一个MS Visual Studio 2010的工程源码(版本是201x都可以)。

2).在编译运行之前请先在VS中配置好OpenCV(网上搜索有很多图文并茂的教程),OpenCV的各个版本应该都兼容,我使用的是2.4.6。

3).这个工程源码不是个人编写,而是我直接从OpenCV中拷贝出来的。

  完成上述配置之后你会发现项目中的源文件有以下几项:

  camera_calibration.cpp----相机标定的源码

  in_Arlco_Camera_data.xml----某款相机的标定参数配置文件

  Arlco_Camera.xml----某款相机的标定用图片索引文件

  in_Logitech_C170.xml----另一款相机的标定参数配置文件

  Logitech_C170.xml----另一款相机的标定用图片索引文件

此时如果点击运行则标定的是Arlco相机,且标定使用的是预先拍好的图片。

2.相机标定的配置过程。

  经过第一部分的介绍,下面你要做的就是更改配置来标定你自己的相机(注意:这个时候你已经打印了一张自己的标定黑白棋盘),请紧跟下列步骤:

1).在工程目录中找到文件in_Arlco_Camera_data.xml,复制一份改个名字如:in_YourCam_Camera_data.xml 放置在同样的文件夹下,表示这是你自己的相机标定配置文件。

2).修改camera_calibration.cpp源代码中的217行

    const string inputSettingsFile = argc >  ? argv[] : "in_Arlco_Camera_data.xml";

改为你刚才复制的自己的配置文件,例如:

    const string inputSettingsFile = argc >  ? argv[] : "in_YourCam_Camera_data.xml";

3).修改你自己的相机标定配置文件in_YourCam_Camera_data.xml,具体如下:

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

这一步配置你的横向和纵向角点(黑白相交的点)数,如下图所示。我的是横向7个,纵向5个,请根据自己的标定棋盘更改相应的数目。

 <!-- The size of a square in some user defined metric system (pixel, millimeter)-->
<Square_Size></Square_Size>

这个定义的是你的棋盘格的尺寸,我的是30mm,请根据自己的做更改。

  <!-- The type of input used for camera calibration. One of: CHESSBOARD CIRCLES_GRID ASYMMETRIC_CIRCLES_GRID -->
<Calibrate_Pattern>"CHESSBOARD"</Calibrate_Pattern>

这个定义的是你标定用的棋盘类型,如果你用的是黑白棋盘,不用修改。

 <Input>"Arlco_Camera.xml"</Input>
<!-- If true (non-zero) we flip the input images around the horizontal axis.-->
<Input_FlipAroundHorizontalAxis></Input_FlipAroundHorizontalAxis>

这个指定的是你标定的时候采用的方式,支持一下三种:

a. 用预先拍好的带有标定棋盘的照片进行标定。(本文采用的标定方式,下面将具体介绍方法)

b.用预先录制好的视频进行标定(支持AVI格式)。用"/tmp/x.avi"代替源码中的"Arlco_Camera.xml"即可,其中x.avi是你录制好的带有棋盘的视频。

c.打开相机边录制边标定。用“1”代替源码中的"Arlco_Camera.xml"即可。

如果采用a方法,需要工程目录中找到文件Arlco_Camera.xml,复制一份改个名字如:YourCam_Camera.xml 放置在同样的文件夹下。这个里面指定了标定用的照片的存放位置和名称,具体代码如下:

<?xml version="1.0"?>
<opencv_storage>
<images>
imges/1.jpg
imges/2.jpg
imges/3.jpg
imges/4.jpg
imges/5.jpg
imges/6.jpg
imges/7.jpg
imges/8.jpg
imges/9.jpg
imges/10.jpg
imges/11.jpg
imges/12.jpg
imges/13.jpg
imges/14.jpg
imges/15.jpg
imges/16.jpg
imges/17.jpg
imges/18.jpg
imges/19.jpg
imges/20.jpg
imges/21.jpg
imges/22.jpg
imges/23.jpg
imges/24.jpg
imges/25.jpg
imges/26.jpg
imges/27.jpg
</images>
</opencv_storage>

你不需要修改,只需要把工程目录下的imges文件夹里的图片换成你自己的就可以了,图片名称还是用1~27的数字。

继续回到in_YourCam_Camera_data.xml文件修改参数:

  <!-- How many frames to use, for calibration. -->
<Calibrate_NrOfFrameToUse></Calibrate_NrOfFrameToUse>

这里27指定了你预先拍照的数量,可以修改,但是需要相应的修改YourCam_Camera.xml文件。

  <!-- The name of the output log file. -->
<Write_outputFileName>"out_Arlco_Camera_data.yml"</Write_outputFileName>

这里指定的是你的标定参数保存的文件名称,用自己的名字如:out_YourCam_Camera_data.yml 代替:out_Arlco_Camera_data.yml 即可。

ok,其余的参数用默认即可,这个时候请把你修改好的文件:in_YourCam_Camera_data.xml 和 YourCam_Camera.xml 添加到工程项目的源码中。

  此时点击运行口可以标定你自己的相机了,最后的结果会保存在工程目录下,名字就是上一步你自己设置的out_YourCam_Camera_data.yml。

标定过程如下图所示:

完成后你就可以看到相机内参、外参以及畸变系数了,部分数据如下:

%YAML:1.0
calibration_Time: "09/02/17 14:27:10"
nrOfFrames:
image_Width:
image_Height:
board_Width:
board_Height:
square_Size: .
FixAspectRatio: .
# flags: +fix_aspectRatio +fix_principal_point +zero_tangent_dist
flagValue:
Camera_Matrix: !!opencv-matrix
rows:
cols:
dt: d
data: [ 1.0078520005023535e+003, ., 6.3950000000000000e+002, .,
1.0078520005023535e+003, 3.5950000000000000e+002, ., ., . ]
Distortion_Coefficients: !!opencv-matrix
rows:
cols:
dt: d
data: [ -4.9694653328469340e-002, 2.3886698343464000e-001, ., .,
-2.1783942538569392e-001 ]
Avg_Reprojection_Error: 6.4271522441441153e-001
Per_View_Reprojection_Errors: !!opencv-matrix
rows:
cols:
dt: f
data: [ 3.89407665e-001, 4.69866753e-001, 3.74819994e-001,
4.79580641e-001, 2.85050988e-001, 3.93756509e-001,
9.21430171e-001, 7.79153645e-001, 6.87648296e-001,
6.19106829e-001, 6.83992207e-001, 6.41160131e-001,
2.52024829e-001, 2.94729859e-001, 4.55538809e-001,
7.44070828e-001, 4.21751559e-001, 5.13929784e-001,
6.03685081e-001, 1.09411442e+000, 1.20731401e+000,
8.70341241e-001, 3.22936684e-001, 4.73881990e-001,
8.06841075e-001, 6.78049505e-001 ]

我用的图片是1280x720的,这个数据是根据你用的标定图片得出的。

3.总结

  本文是为视觉入门者准备的,后续我会陆续介绍在linux下的标定过程,包括用其他开源库如ArUco等的标定方法。

作者:Shawn

基于OpenCV单目相机的快速标定--源码、工程、实现过程的更多相关文章

  1. opencv单目摄像机标定(一)

    #include <string> #include <iostream> #include <cv.h> #include <highgui.h> u ...

  2. opencv单目摄像机标定(二)

    // 引入实际标定板方格宽度的标定程序 #include <string> #include <iostream> #include <cv.h> #include ...

  3. CRMEB单商户商城系统v4.0源码,含前端uni-app源码

    CRMEB商城系统是基于ThinkPhp6.0+Vue开发的一套新零售移动电商系统,CRMEB系统就是集客户关系管理+营销电商系统,能够快速积累客户.会员数据分析.智能转化客户. 有效提高销售.会员维 ...

  4. 基于ffmpeg 直播推流和播放rtmp (IOS源码)

    ios直播推流每秒能达到30帧,比安卓要强,视频采用软编码的话手机会发烫,得采用码编码,播放视频采用opengl渲染. ffmpeg初始化代码如下: int init_Code(int width, ...

  5. android适配全机型悬浮框、视频APP项目、手势操作、Kotlin妹子App、相机图片处理等源码

    Android精选源码 图片滤镜处理,相机滤镜实时处理,相机拍照录制 android仿爱壁纸App更换壁纸效果源码 基于Kotlin+MVP+Retrofit+RxJava+Glide 等架构实现短视 ...

  6. 基于MVVM的知乎日报应用安卓源码

    使用data binding , dagger2 , retrofit2和rxjava实现的,基于MVVM的知乎日报APP运行效果: <ignore_js_op> 使用说明: 项目结构 a ...

  7. 源码来袭!!!基于jquery的ajax分页插件(demo+源码)

    前几天打开自己的博客园主页,无意间发现自己的园龄竟然有4年之久了.可是看自己的博客列表却是空空如也,其实之前也有写过,但是一直没发布(然而好像并没有什么卵用).刚开始学习编程时就接触到博客园,且在博客 ...

  8. 干货——基于Nop的精简版开发框架(附源码)

    .NET的开发人员应该都知道这个大名鼎鼎的高质量b2c开源项目-nopCommerce,基于EntityFramework和MVC开发,拥有透明且结构良好的解决方案,同时结合了开源和商业软件的最佳特性 ...

  9. 基于微软企业库的AOP组件(含源码)

    软件开发,离不开对日志的操作.日志可以帮助我们查找和检测问题,比较传统的日志是在方法执行前或后,手动调用日志代码保存.但自从AOP出现后,我们就可以避免这种繁琐但又必须要实现的方式.本文是在微软企业库 ...

随机推荐

  1. NGUI_Toggle

    七.Toggle复选框:就是对一个选项做上一个标记,表示这个选项已经被选中了. 1.当我们要判断是否使用复选框,可以遵循一下规律: (1).该功能只有两种状态  是/否 (2).该功能同一时间只能激活 ...

  2. 快速排序及优化(Java实现)

    普通快速排序 找一个基准值base,然后一趟排序后让base左边的数都小于base,base右边的数都大于等于base.再分为两个子数组的排序.如此递归下去. public class QuickSo ...

  3. 利用sfc文件构建网络渗透

      收集哈希 SCF(Shell命令文件)文件可用于执行一组有限的操作,例如显示Windows桌面或打开Windows资源管理器,这并不是什么新鲜事.然而,一个SCF文件可以用来访问一个特定的UNC路 ...

  4. Mysql设置字段自动获取时间

    问题:现在在用户表中有一个字段表示用户创建的时间 第一个想法是写一段程序获得系统当前时间,想想就太麻烦了,果断放弃,之后想到了存储过程和函数,再想想还要编写存储过程或者函数的代码,有点放弃的想法,但是 ...

  5. linux --> 进程和线程

    进程和线程 进程(process)和线程(thread)是操作系统的基本概念,下面用一个类比,来解释它们. 1. 计算机的核心是CPU,它承担了所有的计算任务.它就像一座工厂,时刻在运行. 2. 假定 ...

  6. python scrapy框架爬虫遇到301

    1.什么是状态码301 301 Moved Permanently(永久重定向) 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一.如果可能,拥有链接编 ...

  7. hackme.inndy.tw - pyyy - Writeup

    hackme.inndy.tw - pyyy - Writeup 0x01 反编译 1.第一次尝试的时候我直接在线反编译,部分结果如下. for (i, f) in enumerate(F): n = ...

  8. Build to win

    UPDATE:看到周筠老师的评论里的链接,那版式真的非常舒服.我想想模仿模仿他的布局来看看,虽然感觉做的也不是太好.另外对博客内容稍作修改. 一.获得小黄衫的感受 很幸运能够获得"领骑衫&q ...

  9. python中使用flask时遇到的markupsafe._compat包缺失的问题与解决

    环境:windows7 + python3.6.0 在尝试使用python的flask时,按照flask的tutorial操作,装好flask.venv后,对tutorial中的hello.py进行运 ...

  10. python API的安全认证

    我们根据pid加客户端的时间戳进行加密md5(pid|时间戳)得到的单向加密串,与时间戳,或者其它字段的串的url给服务端. 服务端接收到请求的url进行分析 客户端时间与服务端的时间戳之差如果大于规 ...