计算机视觉(四):相机标定与增强现实
一、针孔照相机模型1、照相机矩阵2、分解照相机矩阵3、计算照相机中心4、camera类代码
二、照相机标定1、简单的标定方法
2、棋盘格标定2.1 棋盘格2.2拍摄照片3、求解内外参数3.1 获得结果
三、增强现实3.1 PyGame和PyOpenGL3.1.1 安装OpenGL
一、针孔照相机模型
在针孔照相机模型中,在光线投影到图像平面之前,从唯一一个点经过,也就是照相机中心 C。 在针孔照相机中,三维点X投影为图像点x,使用齐次坐标可以表示为: P为3×4的照相机矩阵(投影矩阵),在齐次坐标系中,三维点X的坐标由4个元素组成,X=[X,Y,Z,W];标量
λ
\lambda
λ是三维点的逆深度。
1、照相机矩阵
照相机矩阵P可以分解为: R是描述照相机方向的旋转矩阵,t是描述照相机中心位置的三维平移向量,内标定矩阵K描述照相机的投影性质。 标定矩阵仅和照相机本身的情况有关,可以写成如下形式: 图像平面和照相机中心间的距离为焦距f。当像素数组在传感器上偏斜的时候,需要用到倾斜参数s,大多数情况下,s可以设置为0,也就是: 其中
f
x
f_x%
fx=
α
\alpha
α
f
y
f_y
fy
纵横比例参数
α
\alpha
α 是在像素元素非正※的情况下使用的,通常情况下默认为1,因此标定矩阵变为: 那么除焦距外。标定矩阵中还剩下唯一参数 光心的坐标c=[
c
x
c_x
cx,
c
y
c_y
cy],也就是光纤坐标轴和图像平面的交点,且坐标接近于图像宽度和高度的一半。
2、分解照相机矩阵
照相机可以分解成如下图所示,我们需要恢复内参数K和照相机的位置t和姿势R,矩阵分块操作成为因子分解。我们将使用RQ因子分解来进行矩阵因子分解。
from numpy import array, dot, hstack
import camera
K = array([[1000,0,500],[0,1000,300],[0,0,1]])
tmp = camera.rotation_matrix([0,0,1])[:3,:3]
Rt = hstack((tmp,array([[50],[40],[30]])))
cam = camera.Camera(dot(K,Rt))
print(K,Rt)
print(cam.factor())
3、计算照相机中心
给定照相机投影矩阵 P,我们可以计算出空间上照相机的所在位置。照相机的中心 C,是一个三维点,满足约束 PC=0。对于投影矩阵为 P=K[R|t] 的照相机,有如下公式: 所以照相机的中心C可用下述式子计算:
照相机的中心和内标定矩阵K无关
4、camera类代码
from numpy import dot, diag, sign, eye
from scipy import linalg
def rotation_matrix(a):
R = eye(4)
R[:3, :3] = linalg.expm([[0, -a[2], a[1]], [a[2], 0, -a[0]], [-a[1], a[0], 0]])
return R
class Camera(object):
def __init__(self,P):
# 初始化P=K【R/t】矩阵
self.P = P
self.K = None #标定矩阵
self.R = None #旋转
self.t = None #平移
self.c = None #照相机中心
def project(self,X):
# X的投影点,进行坐标归一化
X = dot(self.P,X)
for i in range(3):
X[i] /= X[2]
return X
def factor(self):
K,R = linalg.rq(self.P[:,:3])
T = diag(sign(diag(K)))
if linalg.det(T)<0:
T[1,1]*= -1
self.K = dot(K,T)
self.R = dot(T,R)
self.t = dot(linalg.inv(self.K),self.P[:,:3])
return self.K,self.R,self.t
def center(self):
if self.c is not None:
return self.c
else:
self.factor()
self.c = -dot(self.T.R,self.t)
return self.c
二、照相机标定
相机标定也就是同步标定内部参数和外部参数,一般包括两种策略: 1、光学标定:利用已知的几何信息(定长棋盘格)实现参数求解 2、自标定:在静态场景中利用structure from motion估算参数
1、简单的标定方法
大多数参数可以使用基本的假设来设定(正方形垂直的像素,光心位于图像中心),比较难处理的是获得正确的焦距。因此我们可以准备一个平面矩形的标定物体(一个书本)、用于测量的卷尺和直尺以及一个平面,具体步骤如下: a、测量选定的矩形标定物体的边长dX和dY b、将照相机和标定物体放置在平面上,使得照相机的背面和标定物体平行,同时物 体位于照相机图像视图的中心,你可能需要调整照相机或者物体来获得良好的对 齐效果 c、测量标定物体到照相机的距离 dZ; d、拍摄一副图像来检验该设置是否正确,即标定物体的边要和图像的行和列对齐; e、使用像素数来测量标定物体图像的宽度和高度 dx 和 dy。
使用上述相似三角形公式可以获得参数,摆放位置如下图所示:
2、棋盘格标定
过程:
打印一张棋盘格,贴在一个平面上,作为标定物固定相机或者棋盘格,拍摄不同角度的照片从照片中提取棋盘格角点估算11个待求解的内部和外部参数
2.1 棋盘格
助教上课的时候带来了高精度棋盘格,就不需要打印了,直接进入下一步。 标定板规格: GP340 12x9 25mm
2.2拍摄照片
我采用的是固定棋盘格,利用手机拍摄不同角度的照片,照片大概如下:
相机: VIVO S7
焦距:5.42mm
分辨率: 4608×3456
拍摄数量: 36
3、求解内外参数
这时候要请出matlab大哥进行角点的标定和提取
3.1 获得结果
虽然总共拍了36张图片但是有些图片出现没有拍全的情况所以最后真正能用的只有二十三张 但是又在一个博客上看到误差要小于0.5才能认为数据是可靠的,于是通过手动去除数据获得下面的数据(虽然还是大于0.5但是比最开始的1.03应该要好一点吧):
获得的相机参数如下:
cameraParams =
cameraParameters - 属性:
Camera Intrinsics
IntrinsicMatrix: [3×3 double]
FocalLength: [3.4620e+03 3.4497e+03]
PrincipalPoint: [2.2910e+03 1.7390e+03]
Skew: 0
RadialDistortion: [0.0159 -0.0137]
TangentialDistortion: [0 0]
ImageSize: [3456 4608]
Camera Extrinsics
RotationMatrices: [3×3×11 double]
TranslationVectors: [11×3 double]
Accuracy of Estimation
MeanReprojectionError: 0.5567
ReprojectionErrors: [88×2×11 double]
ReprojectedPoints: [88×2×11 double]
Calibration Settings
NumPatterns: 11
WorldPoints: [88×2 double]
WorldUnits: 'millimeters'
EstimateSkew: 0
NumRadialDistortionCoefficients: 2
EstimateTangentialDistortion: 0
三、增强现实
增强现实(Augmented Reality,AR)是将物体和相应信息放置在图像数据上的一系列操作的总称。 最经典的例子是放置一个三维计算机图形学模型,使其看起来属于该场景;如果在视频中,该模型会随着照相机的运动很自然地移动。
3.1 PyGame和PyOpenGL
PyGame 是非常流行的游戏开发工具包,它可以非常简单地处理显示窗口、输入设备、事件,以及其他内容。 PyOpenGL 是 OpenGL 图形编程的 Python 绑定接口。OpenGL 可以安装在几乎所有的系统上,并且具有很好的图形性能。OpenGL 具有跨平台性,能够在不同的操作系统之间工作。
GL 部分包含所有以“gl”开头的函数,其中包含我们需要的大部分函数;GLU 部分是 OpenGL 的实用函数库,里面包含了一些高层的函数。主要使用它来设置照相机投影。
pygame 部分用来设置窗口和事件控制;其中 pygame.image 用来载入图像和创建 OpenGL 的纹理,pygame.locals 用来设置 OpenGL 的显示区域。
3.1.1 安装OpenGL
pygame可以直接在pycharm里面安装,但是OpenGL不知道为什么现实安装不成功,于是找到了这篇教程 下载了这个东西:
下载链接
因为用原来的conda环境不知道为什么一直装不成功所以就重新开了一个conda环境
安装成功,成功跑出demo
文章来源
发表评论