照相机标定

一、照相机标定的原理

1、什么是相机标定

在图像测量过程以及计算机视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立相机成像的几何模型,这些几何模型的参数就是相机参数。求解这些参数的过程叫相机标定。
求解参数:相机的内、外参数,畸变参数

2、坐标系

2.1世界坐标系:

物体在真实世界中的三维坐标

2.2相机坐标系:

三维坐标系,(X,Y,Z)以相机光学中心为原点的坐标系,光轴与z轴重合

2.3图像坐标系:

(x,y),二维坐标系,相机拍摄图像的坐标系,原点为相机光轴与成像平面的交点,是图像的中心点

2.4像素坐标系:

(u,v),是二维坐标系,原点位于图像的左上角,与图像坐标系同处于一个平面。

2.5图像坐标系转换为像素坐标系

像素坐标系是由图像坐标系向左上方移动得到的
在这里插入图片描述

2.6相机坐标系转换为图像坐标系

如下图,图像点 x 是由图像平面与连接三维点 (空间中的一点)X 和照相机中心 C 的直线相交而成的。

照相机的光学坐标轴和 z 轴一致,因此可以简化成相似三角形

根据相似三角形的比例关系,可得:

所以图像坐标系与相机坐标系之间的矩阵变换关系为:

2.7 世界坐标系转换为相机坐标系

世界坐标系和相机坐标系都是三维坐标,任意两个三维坐标之间均可以通过旋转和平移进行转换:
在这里插入图片描述

x,y,z是相机坐标系的坐标,xw,yw,zw是世界坐标系的坐标,R是旋转矩阵,t是平移量

2.8世界坐标系转化为像素坐标系

在这里插入图片描述

二、使用棋盘格标定

1、标定的过程:

1.打印一张棋盘格A4纸张(黑白间距已知),并贴在一个平板上
2.针对棋盘格拍摄若干张图片(一般10-20张)
3.在图片中检测特征点(Harris特征)
4.利用解析解估算方法计算出5个内部参数,以及6个外部参数
5.根据极大似然估计策略,设计优化目标并实现参数的refinement

2、代码实现

2.1获取标定板角点在世界坐标系中的位置

将世界坐标系建立在标定板上,所有点的z坐标全部为0,所以只需要赋值x和y

objp = np.zeros((w*h,3), np.float32)
objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2)

标定工具需要有极高的精度,包括不同平面的角度、特征点的物理距离等,制作标定工具十分困难,拍摄标定板时还要确保标定板是绝对平行的,自己尝试拍了几张会出现运行错误,最后还是采用了学长提供的标定板,共14张。

打印出标定板的世界坐标为:
在这里插入图片描述

2.2找到棋盘格角点
ret, corners = cv2.findChessboardCorners(gray, (w,h),None)

三个参数分别表示:
棋盘图像(8位灰度或彩色图像)
棋盘尺寸
存放角点的位置
返回值:
retval:是否检测出角点。
corners:角点的位置。

2.3角点精确检测
cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)

参数:输入图像 角点初始坐标 搜索窗口为2*winsize+1 死区 求角点的迭代终止条件
返回值:角点位置

2.4显示角点位置
cv2.drawChessboardCorners(img, (w,h), corners, ret)

在这里插入图片描述

2.5标定图像
cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

输入:世界坐标系里的位置、像素坐标、图像的像素尺寸大小、3*3矩阵,相机内参数矩阵、畸变矩阵
输出:标定结果、相机的内参数矩阵、 畸变系数、 旋转矩阵、 平移向量

2.6优化参数

由上,我们已经得到了相机内参和畸变系数,在将图像去畸变之前,我们还可以使用cv.getOptimalNewCameraMatrix()优化内参数和畸变系数,通过设定自由自由比例因子alpha。当alpha设为0的时候,将会返回一个剪裁过的将去畸变后不想要的像素去掉的内参数和畸变系数; 当alpha设为1的时候,将会返回一个包含额外黑色像素点的内参数和畸变系数,并返回一个ROI用于将其剪裁掉。

2.7去畸变的方法:
dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# 根据前面ROI区域裁剪图片
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult10.jpg',dst)

img2:待校正图像
dst:输出图像

2.8反投影误差

通过反投影误差,我们可以来评估结果的好坏。越接近0,说明结果越理想。通过之前计算的内参数矩阵、畸变系数、旋转矩阵和平移向量,使用cv2.projectPoints()计算三维点到二维图像的投影,然后计算反投影得到的点与图像上检测到的点的误差,最后计算一个对于所有标定图像的平均误差,这个值就是反投影误差。

2.9代码
import cv2
import numpy as np
import glob

# 找棋盘格角点
# 阈值
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
#棋盘格模板规格
w = 6   #内角点个数,内角点是和其他格子连着的点
h = 4
# 世界坐标系中的棋盘格点
objp = np.zeros((w*h,3), np.float32)
objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2)
# 储存棋盘格角点的世界坐标和图像坐标对
objpoints = [] # 在世界坐标系中的三维点
imgpoints = [] # 在图像平面的二维点
i=0
images = glob.glob(r'E:/Vision/work4/picture/*.jpg')
print(images)
for fname in images:
    print(fname)
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    
    # 找到棋盘格角点
    ret, corners = cv2.findChessboardCorners(gray, (w,h),None)
    # 如果找到足够点对,将其存储起来
    if ret == True:
        # 角点精确检测
        cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        objpoints.append(objp)
        imgpoints.append(corners)
        # 将角点在图像上显示
        cv2.drawChessboardCorners(img, (w,h), corners, ret)
        cv2.imshow('findCorners',img)
        cv2.waitKey(1000)
cv2.destroyAllWindows()

#标定、去畸变
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
print (("ret:"),ret)
print (("mtx:\n"),mtx)        # 内参数矩阵
print (("dist:\n"),dist)      # 畸变系数   distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print (("rvecs:\n"),rvecs)    # 旋转向量  # 外参数
print (("tvecs:\n"),tvecs)    # 平移向量  # 外参数
# 去畸变
img2 = cv2.imread('E:/Vision/work4/picture/10_d.jpg')
h,w = img2.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),0,(w,h)) # 自由比例参数
dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# 根据前面ROI区域裁剪图片
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult10.jpg',dst)

# 反投影误差
total_error = 0
for i in range(len(objpoints)):
    imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
    total_error += error
print (("total error: "), total_error/len(objpoints))


运行结果:
内参数矩阵mtx、畸变系数dist、旋转矩阵rvecs、平移向量tvecs分别为:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
输出的反投影误差为total error的结果为0.03427647962630596,接近0,说明误差小,标定效果还可以。获取相机的参数后就可以应用于构建三维模型和识别物体。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值