相机标定(Cameracalibration)原理、步骤
相机标定(Cameracalibration)原理、步骤
简介
在图像测量过程以及机器视觉应⽤中,为确定空间物体表⾯某点的三维⼏何位置与其在图像中对应点之间的相互关系,必须建⽴相机成
像的⼏何模型,这些⼏何模型参数就是相机参数。在⼤多数条件下这些参数必须通过实验与计算才能得到,这个求解参数的过程就称之
为相机标定(或摄像机标定)。⽆论是在图像测量或者机器视觉应⽤中,相机参数的标定都是⾮常关键的环节,其标定结果的精度及算
法的稳定性直接影响相机⼯作产⽣结果的准确性。因此,做好相机标定是做好后续⼯作的前提,提⾼标定精度是科研⼯作的重点所在。
常⽤术语
内参矩阵:IntrinsicMatrix
焦距:FocalLength
主点:PrincipalPoint
径向畸变:RadialDistortion
切向畸变:TangentialDistortion
旋转矩阵:RotationMatrices
平移向量:TranslationVectors
平均重投影误差:MeanReprojectionError
重投影误差:ReprojectionErrors
重投影点:ReprojectedPoints
1、坐标系的转换
1.1世界坐标系
世界坐标系(worldcoordinate)(xw,yw,zw),也称为测量坐标系,是⼀个三维直⾓坐标系,以其为基准可以描述相机和待测物体的空间
位置。世界坐标系的位置可以根据实际情况⾃由确定。
1.2相加坐标系
相机坐标系(cameracoordinate)(xc,yc,zc),也是⼀个三维直⾓坐标系,原点位于镜头光⼼处,x、y轴分别与相⾯的两边平⾏,z轴为
镜头光轴,与像平⾯垂直。
1.3世界坐标系转换为相机坐标系
其中R为3*3的旋转矩阵,t为3*1的平移⽮量,(xc,yc,zc,1)T(xc,yc,zc,1)T为相机坐标系的齐次坐
标,(xw,yw,zw,1)T(xw,yw,zw,1)T为世界坐标系的齐次坐标。###1.4像素坐标系、图像坐标系
-像素坐标系(pixelcoordinate)如图,像素坐标系uov是⼀
个⼆维直⾓坐标系,反映了相机CCD/CMOS芯⽚中像素的排列情况。原点oo位于图像的左上⾓,uu轴、vv轴分别于像⾯的两边平⾏。像
素坐标系中坐标轴的单位是像素(整数)。
像素坐标系不利于坐标变换,因此需要建⽴图像坐标系XOYXOY,其坐标轴的单位通常为毫⽶(mm),原点是相机光轴与相⾯的交
点(称为主点),即图像的中⼼点,XX轴、YY轴分别与uu轴、vv轴平⾏。故两个坐标系实际是平移关系,即可以通过平移就可得到。
图像坐标系转换为像素坐标系
其中,dX、dY分别为像素在X、Y轴⽅向上的物理尺⼨,u0,v0为主点(图像原点)坐标。
1.5针孔成像原理
如图,空间任意⼀点P与其图像点p之间的关系,P与相机光⼼o的连线为oP,oP与像⾯的交点p即为空间点P在图像平⾯上的投影。
该过程为透视投影,如下矩阵表⽰:
其中,ss为⽐例因⼦(ss不为0),ff为有效焦距(光⼼到图像平⾯的距离),(x,y,z,1)T(x,y,z,1)T是空间点PP在相机坐标系oxyzoxyz中
的齐次坐标,(X,Y,1)T(X,Y,1)T是像点pp在图像坐标系OXYOXY中的齐次坐标。
1.6世界坐标系转换为像素坐标系
其中,αx=f/dXαx=f/dX、
αy=f/dYαy=f/dY,称为u、v轴的尺度因⼦,M1称为相机的内部参数矩阵,M2称为相机的外部参数矩阵,M称为投影矩阵。
##2相机内参与畸变
参数###2.1相机内参-参看1.6节所述
2.2畸变参数
畸变参数(distortionparameters)
畸变(distortion)是对直线投影(rectilinearprojection)的⼀种偏移。
简单来说直线投影是场景内的⼀条直线投影到图⽚上也保持为⼀条直线。
畸变简单来说就是⼀条直线投影到图⽚上不能保持为⼀条直线了,这是⼀种光学畸变(opticalaberration),可能由于摄像机镜头的原
因。
畸变⼀般可以分为:径向畸变、切向畸变
1、径向畸变来⾃于透镜形状
2、切向畸变来⾃于整个摄像机的组装过程。畸变还有其他类型的畸变,但是没有径向畸变、切向畸变显著
下⾯是⼏张反应畸变的图像
径向畸变
实际摄像机的透镜总是在成像仪的边缘产⽣显著的畸变,这种现象来源于“筒形”或“鱼眼”的影响。如下图,光线在原理透镜中⼼的
地⽅⽐靠近中⼼的地⽅更加弯曲。对于常⽤的普通透镜来说,这种现象更加严重。筒形畸变在便宜的⽹络摄像机中⾮常厉害,但在⾼端
摄像机中不明显,因为这些透镜系统做了很多消除径向畸变的⼯作。
对于径向畸变,成像仪中⼼(光学中⼼)的畸变为0,随着向边缘移动,畸变越来越严重。
径向畸变包括:枕形畸变、桶形畸变
切向畸变
切向畸变是由于透镜制造上的缺陷使得透镜本⾝与图像平⾯不平⾏⽽产⽣的。
切向畸变可分为:薄透镜畸变、离⼼畸变
切向畸变图⽰:
2.2.1opencv中的畸变模型
径向畸变模型:
2.3相机标定
相机标定步骤
1、打印⼀张棋盘格,把它贴在⼀个平⾯上,作为标定物。
2、通过调整标定物或摄像机的⽅向,为标定物拍摄⼀些不同⽅向的照⽚。
3、从照⽚中提取棋盘格⾓点。
4、估算理想⽆畸变的情况下,五个内参和六个外参。
5、应⽤最⼩⼆乘法估算实际存在径向畸变下的畸变系数。
6、极⼤似然法,优化估计,提升估计精度。
注:本⽂只是为了⾃⼰备忘使⽤
3相机标定
3.1准备
OpenCV使⽤棋盘格板进⾏标定,如下图所⽰。为了标定相机,我们需要输⼊⼀系列三维点和它们对应的⼆维图像点。在⿊⽩相间的棋盘格
上,⼆维图像点很容易通过⾓点检测找到。⽽对于真实世界中的三维点呢?由于我们采集中,是将相机放在⼀个地⽅,⽽将棋盘格定标板进
⾏移动变换不同的位置,然后对其进⾏拍摄。所以我们需要知道(X,Y,Z)的值。但是简单来说,我们定义棋盘格所在平⾯为XY平⾯,即
Z=0。对于定标板来说,我们可以知道棋盘格的⽅块尺⼨,例如30mm,这样我们就可以把棋盘格上的⾓点坐标定义为(0,0,0),
(30,0,0),(60,0,0),···,这个结果的单位是mm。
3D点称为objectpoints,2D图像点称为imagepoints。
3.2检测棋盘格⾓点
为了找到棋盘格模板,我们使⽤openCV中的函数essboardCorners()。我们也需要告诉程序我们使⽤的模板是什么规格的,
例如88的棋盘格或者55棋盘格等,建议使⽤x⽅向和y⽅向个数不相等的棋盘格模板。下⾯实验中,我们使⽤的是107的棋盘格,每个⽅格
边长是20mm,即含有96的内部⾓点。这个函数如果检测到模板,会返回对应的⾓点,并返回true。当然不⼀定所有的图像都能找到需要
的模板,所以我们可以使⽤多幅图像进⾏定标。除了使⽤棋盘格,我们还可以使⽤圆点阵,对应的函数为rclesGrid()。
找到⾓点后,我们可以使⽤SubPix()可以得到更为准确的⾓点像素坐标。我们也可以使⽤
essboardCorners()将⾓点绘制到图像上显⽰。如下图所⽰:
3.3、标定
通过上⾯的步骤,我们得到了⽤于标定的三维点和与其对应的图像上的⼆维点对。我们使⽤ateCamera()进⾏标定,这个函数会
返回标定结果、相机的内参数矩阵、畸变系数、旋转矩阵和平移向量。
第三步我们已经得到了相机内参和畸变系数,在将图像去畸变之前,我们还可以使⽤imalNewCameraMatrix()优化内参数和畸
变系数,通过设定⾃由⾃由⽐例因⼦alpha。当alpha设为0的时候,将会返回⼀个剪裁过的将去畸变后不想要的像素去掉的内参数和畸变系
数;当alpha设为1的时候,将会返回⼀个包含额外⿊⾊像素点的内参数和畸变系数,并返回⼀个ROI⽤于将其剪裁掉。
然后我们就可以使⽤新得到的内参数矩阵和畸变系数对图像进⾏去畸变了。有两种⽅法进⾏去畸变:
(1)使⽤ort()
这是⼀个最直接的办法,只⽤直接调⽤函数就可以得到去畸变的图像,使⽤上⾯的ROI可以对其进⾏剪裁。代码如下:
#undistort
dst=ort(img,mtx,dist,None,newcameramtx)
#croptheimage
x,y,w,h=roi
dst=dst[y:y+h,x:x+w]
e('',dst)
(2)使⽤remmaping()
这是⼀个分两步的⽅法,⾸先计算⼀个从畸变图像到⾮畸变图像的映射,然后使⽤这个映射关系对图像进⾏去畸变。
代码如下:
#undistort
mapx,mapy=distortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst=(img,mapx,mapy,_LINEAR)
#croptheimage
x,y,w,h=roi
dst=dst[y:y+h,x:x+w]
e('',dst)
3.4反投影误差
通过反投影误差,我们可以来评估结果的好坏。越接近0,说明结果越理想。通过之前计算的内参数矩阵、畸变系数、旋转矩阵和平移向
量,使⽤tPoints()计算三维点到⼆维图像的投影,然后计算反投影得到的点与图像上检测到的点的误差,最后计算⼀个对于所
有标定图像的平均误差,这个值就是反投影误差。
代码
所有步骤的代码如下所⽰:
#coding:utf-8
importcv2
importnumpyasnp
importglob
#找棋盘格⾓点
#阈值
criteria=(_CRITERIA_EPS+_CRITERIA_MAX_ITER,30,0.001)
#棋盘格模板规格
w=9
h=6
#世界坐标系中的棋盘格点,例如(0,0,0),(1,0,0),(2,0,0)....,(8,5,0),去掉Z坐标,记为⼆维矩阵
objp=((w*h,3),32)
objp[:,:2]=[0:w,0:h].e(-1,2)
#储存棋盘格⾓点的世界坐标和图像坐标对
objpoints=[]#在世界坐标系中的三维点
imgpoints=[]#在图像平⾯的⼆维点
images=('calib/*.png')
forfnameinimages:
img=(fname)
gray=or(img,_BGR2GRAY)
#找到棋盘格⾓点
ret,corners=essboardCorners(gray,(w,h),None)
#如果找到⾜够点对,将其存储起来
ifret==True:
SubPix(gray,corners,(11,11),(-1,-1),criteria)
(objp)
(corners)
#将⾓点在图像上显⽰
essboardCorners(img,(w,h),corners,ret)
('findCorners',img)
y(1)
yAllWindows()
#标定
ret,mtx,dist,rvecs,tvecs=ateCamera(objpoints,imgpoints,[::-1],None,None)
#去畸变
img2=('calib/')
h,w=[:2]
newcameramtx,roi=imalNewCameraMatrix(mtx,dist,(w,h),0,(w,h))#⾃由⽐例参数
dst=ort(img2,mtx,dist,None,newcameramtx)
#根据前⾯ROI区域裁剪图⽚
#x,y,w,h=roi
#dst=dst[y:y+h,x:x+w]
e('',dst)
#反投影误差
total_error=0
foriinxrange(len(objpoints)):
imgpoints2,_=tPoints(objpoints[i],rvecs[i],tvecs[i],mtx,dist)
error=(imgpoints[i],imgpoints2,_L2)/len(imgpoints2)
total_error+=error
print"totalerror:",total_error/len(objpoints)
本文发布于:2022-12-28 12:07:05,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/46531.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |