目录

为什么进行相机标定

相机标定原理推导

坐标系的转换

世界坐标系->相机坐标系

相机坐标系->图像坐标系

图像坐标系->像素坐标系

为什么使用齐次坐标系

图像畸变和畸变矫正

径向畸变

切向畸变

相机内外参数的应用

相机标定具体实现

步骤:

1. 准备标定图片

2. 对每张标定图片,提取角点信息

3. 对每张标定图片,进一步提取亚像素角点信息

4. 在标定图上绘制找到的内角点

5. 相机标定

6. 利用标定结果对测试图进行矫正

完整代码(python+opencv):

参考

为什么进行相机标定

首先谈谈相机为什么需要标定?任何理论物理模型都是在特定假设上对真实事物的近似,然而在实际应用中存在误差。实际应用中,普通相机成像误差的主要来源有两部分,第一是sensor制造产生的误差,比如sensor成像单元不是正方形,sensor歪斜;第二是镜头制造和安装产生的误差,镜头一般存在非线性的径向畸变;镜头与相机sensor安装不平行,还会产生切向畸变。

为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立相机成像的几何模型,这些几何模型参数就是相机参数。在大多数条件下这些参数必须通过实验与计算才能得到,这个求解参数的过程就称之为相机标定(或摄像机标定),标定结果的精度及算法的稳定性直接影响相机工作产生结果的准确性。

相机标定的方法有自标定(找图像中特征点)、标定板标定(特征点易求,稳定性好),一般采用标定板标定。相机标定按照相机是否静止,可分为静态相机标定(标定板动,相机静止),动态相机标定(标定板静止,相机运动)。

相机标定原理推导

坐标系的转换

坐标系转换就是为了将空间的三维世界坐标系转换至图像处理的二维像素坐标系。坐标系有:世界坐标系,相机坐标系,图像坐标系,像素坐标系。

世界坐标系(world coordinate)(xw,yw,zw)是实际物体再三维世界中的坐标系,可以表示任何物体,是由于相机而引入的。单位m。

相机坐标系(camera coordinate)(xc,yc,zc):是一个三维直角坐标系,以摄像机光心为原点,z轴与光轴重合也就是z轴指向相机的前方(也就是与成像平面垂直),x轴与y轴的正方向与物体坐标系平行。

图像坐标系(也叫平面坐标系)(image coordinate)(x,y):是像平面上的二维直角坐标系。坐标原点为摄像机光轴与图像物理坐标系的交点位置。它的x轴与相机坐标系的xc轴平行,它的y轴与相机坐标系的yc轴平行,单位是mm。

像素坐标系:(pixel coordinate)(u,v),以像素为单位,坐标原点在左上角。像素坐标系到平面坐标系涉及到的是单位的转换和平移。传感器以mm单位到像素中间有转换。举个例子,CCD传感上上面的8mm x 6mm,转换到像素大小是640x480。dx,dy表示像素坐标系中每个像素的物理大小。像素坐标系的x轴与图像坐标系的u轴平行,像素坐标系的y轴与图像坐标系的v轴平行。

 世界坐标系->相机坐标系

相机坐标系是以相机位置作为原点,世界坐标系是以物体的中心作为原点,世界坐标系到相机坐标系的转换包括三个轴的平移,用表示;因为相机不一定和物体是平齐的姿态,所以坐标转换还包括以轴为轴的旋转,用来表示。

红色的点为世界坐标系中的点,黑色为世界坐标系,蓝色为相机坐标系;绕轴旋转后,通过相似三角形定理:

写成矩阵的形式:

同理,绕轴旋转后:

轴旋转后:

所以,世界坐标系和相机坐标系的转换可以这样表达:

简化为:

相机坐标系->图像坐标系

相机坐标系到图像坐标系可以使用小孔成像的原理进行推导,涉及的是相机本身的参数。

为了便于计算,我们将像平面对称反转过来,如下图所示:

是相机坐标系下的点,映射到图像坐标系上为,通过相似三角形定理,可以得出:

,为焦距;

进一步地:

进一步地:

图像坐标系->像素坐标系

图像坐标系到像素坐标系是在轴上的偏移,但是图像坐标系的单位为mm,像素坐标系的单位为像素pt,所以需要进行单位的转换。

假设每个像素代表的物理尺寸为,则:

从而可以得到像素坐标系和相机坐标系的关系式:

从而可以得到像素坐标系和世界坐标系的关系式:

注:不同的矩阵符号是为了便于区分。

大多数情况下是相机坐标系到像素坐标系的转换:

  为轴的尺度因子,轴的尺度因子;

为相机内参;为相机外参;

所以,像素坐标系->世界坐标系可以表示为:

外参就是相机相对于世界坐标系的旋转和平移变换关系。内参是相机固有的属性,即焦距,像元尺寸。公式中有一个,它表示物体离光学中心的距离。因此,在标定的时候,如果物体在距离相机的不同位置,那么我们就必须在不同的位置对相机做标定。当物体离相机远的时候,在相机上成像小,一个像素代表的实际尺寸就大,当物体离相机近的时候,那么成像大,一个像素代表的实际物体尺寸就小。因此,不同的位置都需要去标定。

为什么使用齐次坐标系

齐次坐标表示是计算机图形学的重要手段之一,它既能够用来明确区分向量和点,同时也更易用于进行仿射几何变换”—— F.S. Hill, JR。

齐次坐标易于进行仿射变换。

首先:齐次坐标就是用N+1维来代表N维坐标;

将三维坐标视为一个列向量,那么矩阵*列向量得到的新向量的每一个分量,都是旧的列向量的线性函数,因而三维笛卡尔坐标与矩阵的乘法只能实现三维坐标的缩放和旋转,而无法实现坐标平移。如下所示:

将三维的笛卡尔坐标添加一个额外坐标,就可以实现坐标平移了,而且保持了三维向量与矩阵乘法具有的缩放和旋转操作。这个就称为齐次坐标。而这种变换也称为仿射变换(affine transformation),不属于线性变换。仿射变换是:“线性变换”+“平移”。

齐次坐标能够用来明确区分向量和点。

(9条消息) 深入探索透视投影变换_popy007的博客-CSDN博客_投影变换

图像畸变和畸变矫正

畸变(distortion)是对直线投影(rectilinear projection)的一种偏移。直线投影是场景内的一条直线投影到图片上也保持为一条直线。畸变就是一条直线投影到图片上不能保持为一条直线了,这是一种光学畸变(optical aberration。

图像畸变一般分为两种:径向畸变和切向畸变。径向畸变发生在相机坐标系转图像坐标系的过程中;切向畸变是发生在相机制作过程,原因是感光元平面跟透镜不平行。

畸变还有其他类型的畸变,但是没有径向畸变、切向畸变显著。

径向畸变

径向畸变(枕形、桶形):光线在远离透镜中心的地方比靠近中心的地方更加弯曲。当光线越靠近中心的位置,畸变越小,沿着半径方向远离中心的时候,畸变越大。桶形畸变虽然不影响成像清晰度,但却影响成像的位置精度,这会给图像分析和图像测量带来误差。

径向畸变都是随着与中心之间的距离增加而增加,因此可以用一个多项式函数来描述畸变前后的坐标变化:

注: 是径向畸变系数;是畸变后点的坐标,是理想的点的坐标,

对于畸变较小的图像中心区域,畸变纠正主要是 起作用;对于畸变较大的边缘区域,主要是起作用。根据所用镜头,可以适当使用合适的校正系数。

切向畸变

切向畸变:透镜不完全平行于图像平面,即sensor装配时与镜头间的角度不准。

注:是切向畸变系数;

综上,我们一共需要5个畸变参数(k1、k2、k3、p1、p2 )来描述镜头畸变。

针孔相机模型中,只要确定相机参数和畸变参数就可以唯一的确定针孔相机模型, 这个过程就称为「相机标定」。

一旦相机结构固定,包括镜头结构固定,对焦距离固定,我们就可以用这些参数去近似这个相机。相机参数标定结果的精度会直接影响相机工作中产生结果的准确性。因此做好相机标定是后续工作的重要前提。

相机内外参数的应用

对单目视觉而言,求得内参和畸变参数后,就可以对拍摄的图像做变换和矫正。矫正完拍摄的图像之后,对图像做其他处理。

对于双目视觉而言,需要用到世界坐标系。对单目视觉做完内参和畸变参数的矫正之后,就可以用这些变换后的图像,同时结合世界坐标系实现定位或者其他用途了。

相机标定具体实现

使用python+opencv进行相机标定。

步骤:

1. 准备标定图片(棋盘图)

2. 对每张标定图片,提取角点信息;

3. 对每张标定图片,进一步提取亚像素角点信息;

4. 在标定图上绘制找到的内角点

5. 相机标定(得到相机内外参)

6. 利用标定结果对棋盘图进行矫正

1. 准备标定图片

标定图片需要使用标定板在不同位置、不同角度、不同姿态下拍摄,最少需要3张,以10~20张为宜。标定板需要是黑白相间的矩形构成的棋盘图。

棋盘图PDF文件链接:https://pan.baidu.com/s/1V1nJYyKDd0ZmIM0BtfyTSg 
提取码:alth

我实验的时候使用的是别人的图片,我的相机拍的图片畸变不明显。在此非常感谢这位博主,数据集在这里:

链接:https://pan.baidu.com/s/1K1SsxV8H_F5BG0avBdbOiQ 
提取码:v6en

2. 对每张标定图片,提取角点信息

使用FindChessboardCorners()函数提取角点信息。

3. 对每张标定图片,进一步提取亚像素角点信息

使用cornerSubPix函数在角点检测中精确化角点位置。

4. 在标定图上绘制找到的内角点

drawChessboardCorners函数用于绘制被成功标定的角点。

5. 相机标定

获取到棋盘标定图的内角点图像坐标之后,使用calibrateCamera()函数进行标定,计算相机内参和外参系数。

6. 利用标定结果对测试图进行矫正

使用undistort()函数对测试的图片进行标定。结果如下图:

完整代码(python+opencv):

import argparse
from argparse import RawDescriptionHelpFormatter
from email import parser
import numpy as np
import cv2def findCorners(img,srcPath,imgId,col,row):srcGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret,corners = cv2.findChessboardCorners(srcGray,(col,row),None)if ret:criteria = (cv2.TermCriteria_EPS + cv2.TermCriteria_COUNT,10,0.001)cornersSubPix = cv2.cornerSubPix(srcGray,corners,(5,5),(-1,-1),criteria)savePath = srcPath + "\\" + str(imgId) + "_corner.jpg"cv2.drawChessboardCorners(img,(row,col),cornersSubPix,ret)cv2.imwrite(savePath,img)print("保存找到角点的图像,地址:",savePath)return (ret,cornersSubPix)def camCalibration(imgDir,srcPath,imgNums,row,col):w,h = 0,0allCornersList = []patterns = []# 相机标定x,y = np.meshgrid(range(row),range(col))prod = row * colpatternPoints = np.hstack((x.reshape(prod,1),y.reshape(prod,1),np.zeros((prod,1)))).astype(np.float32)for i in range(1,imgNums+1):imgPath = imgDir + "\\" + str(i) + ".jpg"print("imgPath:",imgPath)# 读取图像img = cv2.imread(imgPath)(h,w) = img.shape[:2]print("(h:w):",(h,w))# 提取角点ret,cornres = findCorners(img,srcPath,i,row,col)if ret:allCornersList.append(cornres)patterns.append(patternPoints)rms,camMatrix,distcoeffs,rvecs,thecs = cv2.calibrateCamera(patterns,allCornersList,(w,h),None,None)print("rms:",rms)print("distcoeffs:",distcoeffs)print("camMatrix:",camMatrix)print("rvecs:",rvecs)print("thecs:",thecs)return (camMatrix,distcoeffs)def camCorrect(testDir,camMatrix2,distCoffs2):for i in range(1,8):corrImgPath = testDir + "\\" + str(i) + ".jpg"img = cv2.imread(corrImgPath)(w1,h1) = img.shape[:2]print("(w1,h1):",(w1,h1))# 对参数处理,去除不必要的边缘newCamMatrix,roi = cv2.getOptimalNewCameraMatrix(camMatrix2,distCoffs2,(w1,h1),1,(w1,h1))# 矫正图像dst = cv2.undistort(img,camMatrix2,distCoffs2,None,newCamMatrix)# 保存校正后的图像# x,y,w,h = roi# dst = dst[y:y+h,x:x+w]corPath = testDir + "\\" + str(i) + "_crct.jpg"cv2.imwrite(corPath,dst)print("保存校正后的图像,地址:",corPath)if __name__ == "__main__":parser = argparse.ArgumentParser(formatter_class=RawDescriptionHelpFormatter)parser.add_argument("--imgDir",help="标定图片路径",type=str,metavar='',default="E:\\09tmp\\src")parser.add_argument("--srcPath",help="图片保存途径",type=str,metavar='',default="E:\\09tmp\\res")  parser.add_argument("--testDir",help="待测试图片路径",type=str,metavar='',default="E:\\09tmp\\src")parser.add_argument("--row",help="每一行有多少角点,边缘处不算",type=int,metavar='',default="7")parser.add_argument("--col",help="每一列有多少角点,边缘处不算",type=int,metavar='',default="4")parser.add_argument("--imgNum",help="多少幅图像",type=int,metavar='',default="7")args=parser.parse_args()# 相机标定camMatrix,distCoffs = camCalibration(args.imgDir,args.srcPath,args.imgNum,args.row,args.col)# 矫正图片camCorrect(args.testDir,camMatrix,distCoffs)

参考

(37 封私信 / 81 条消息) 世界坐标系 - 搜索结果 - 知乎 (zhihu.com)

为什么要相机标定?你想知道的都在这!_坐标系 (sohu.com)

相机参数标定(camera calibration)及标定结果如何使用_Aoulun的博客-CSDN博客_相机标定后如何使用

(37 封私信 / 81 条消息) 如何通俗地讲解「仿射变换」这个概念? - 知乎 (zhihu.com)

(12条消息) 第三更,单目相机标定实践(完整过程)_Aoulun的博客-CSDN博客

图像处理——相机标定(Camera calibration)_fengye2two的博客-CSDN博客_图像标定

【传感器融合】相机标定(理论推导+具体实现)相关推荐

  1. 双目相机标定理论总结

    一.双目相机标定简介 双目相机标定包含两个部分内容 1)两台相机各自内参和畸变系数的标定(单目标定) 2)两台相机之间相互位置的标定(双目标定) 提问:为什么要进行双目标定? 因为在许多三维重建算法中 ...

  2. 一文详解双目相机标定理论

    01 前言 双目相机标定,从广义上讲,其实它包含两个部分内容: 两台相机各自误差的标定(单目标定) 两台相机之间相互位置的标定(狭义,双目标定) 在这里我们所说的双目标定是狭义的,讲解理论的时候仅指两 ...

  3. SLAM 03.多传感器融合算法

    传感器标定是自动驾驶的基本需求,一个车上装了多个/多种传感器,而它们之间的时间和空间关系需要统一,传感器数据的标定主要为了定位的准确性. 1.传感器分类 机器人有多种传感器,每种数据类型不一样,数据精 ...

  4. opencv相机标定和人头姿态估计案例

    前言 头部驱动除了之前关注的表情驱动外,还有眼球驱动和头部方向驱动.本博客基于opencv官方文档和部分开源代码来研究如何基于人脸关键点获取头部的朝向. 国际惯例,参考博客: opencv:Camer ...

  5. MATLAB/OpenCV--基于棋盘格相机标定教程

    文章目录 1. 使用 Matlab 进行相机标定 1.1 原理推导 1.2 标定图资源下载 1.3 使用matlab 工具箱camera calibrator 流程 2. 使用 OpenCV 进行相机 ...

  6. 相机标定和ORBSLAM2/VINS测试

    目录 一.相机标定 1.1 标定目的 1.2 常见模型介绍 1.2.1 相机模型 1.2.2 畸变模型 1.3 双目标定 1.3.1 常见标定工具及对应使用场景 1.3.2 Kalibr标定 1.3. ...

  7. 元旦特惠!无人机/ROS2/三维重建点云/SLAM/多传感器/相机标定/深度估计等重磅干货教程...

    随着AI技术的大规模落地,国内外资本对AI视觉兴趣只增不减,自动驾驶.工业视觉.AR/VR.测量测绘.移动机器人等领域涌现了大量独角兽公司,相关产品更是受到重点关注. AI领域的热度和资本涌入持续增长 ...

  8. 彻底剖析激光-视觉-IMU-GPS融合SLAM算法:理论推导、代码讲解和实战

    应用背景介绍 自主导航是机器人与自动驾驶的核心功能,而SLAM技术是实现自主导航的前提与关键.现有的机器人与自动驾驶车辆往往会安装激光雷达,相机,IMU,GPS等多种模态的传感器,而且已有许多优秀的激 ...

  9. 【自动驾驶传感器融合系列】02自动驾驶中的多传感器同步理论

    [自动驾驶传感器融合系列]02自动驾驶中的多传感器同步理论 文前白话 1.传感器时空同步概念 2.传感器时间同步 · 时间硬同步 · 时间软同步 3.传感器时空同步 文前白话 同步理论整体架构: 1. ...

最新文章

  1. Mockito测试void方法会引发异常
  2. win10更名导致MySQL无法启动服务
  3. 销毁AWS资源:Cloud-Nuke还是AWS-Nuke?
  4. c oracle 存储图片,用c语言如何读取和保存jpg图片文件?
  5. android one s5,消费者报告:Galaxy S5比S6更值得购买
  6. devsecops automation
  7. 常见电脑蓝屏代码以及解决办法
  8. flowable设计器自定义自己的人员选择器
  9. Excel如何按照单元格背景颜色排序
  10. 小皮phpstudy无法启动mysql的解决方法
  11. XXS靶场haozi
  12. 网页截图及TDK抓取
  13. MD5 SHA1 CRC32是什么意思?主要有什么区别?
  14. 马云:阿里巴巴要培养更多的京东并让这些企业挣钱
  15. AFI - all in - 逍遥棋 - 游戏规则
  16. 怎么在添加为知笔记编辑器/为知笔记怎么用其他编辑器编辑/为知笔记怎么才能用Word/notepad++编辑
  17. 【学怵研究】计算机视觉CV方向的研究生第一篇论文该怎么写(水)?
  18. Linpus针对富士通LIFEBOOK MH330推出另外一款软件设计
  19. IEEE2022/遥感:Stagewise UnsupervisedDomain Adaptation WithAdversarial Self-Training for Road Segmentat
  20. 程序设计思维与实践第九周作业

热门文章

  1. idea设置自动导入包 idea自动import
  2. 使用PyQt5写一个桌面程序
  3. C语言数组初始化的三种方法
  4. CCIE-IPV6单播和组播地址
  5. Echarts 地图json数据汇总
  6. 国家为什么要使用双证书体系?
  7. Nios II 系统的Avalon总线
  8. 末日生存手游《文明重启》超强实战攻略,帮你苟到最后!
  9. 图卷积神经网络 国科大沈华伟 视频笔记
  10. HDU-1556-Color the ball (线段树和差分数组两种解法)