2021-05-23

Posted 差不多女生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-05-23相关的知识,希望对你有一定的参考价值。

相机标定

什么是相机标定?我们为什么需要相机标定?
其实相机标定就是确定相机内参和外参的过程,其结果精度会直接影响视觉系统后续工作的准确性

相机标定涉及到了四大坐标系,分别为:

像素坐标系(u,v):是一个二维直角坐标系,反映了相机中像素的排列情况。原点o位于图像的左上角,u轴、v轴分别于像面的两边平行。像素坐标系中坐标轴的单位是像素(整数)。

图像物理坐标系(x,y):其坐标轴的单位通常为毫米(mm),原点是相机光轴与相面的交点(称为主点),即图像的中心点,X轴、Y轴分别与u轴、v轴平行。故两个坐标系实际是平移关系,即可以通过平移就可得到。

相机坐标系(camera coordinate)(xc,yc,zc)也是一个三维直角坐标系,原点位于镜头光心处,x、y轴分别与相面的两边平行,z轴为镜头光轴,与像平面垂直

世界坐标系(world coordinate)(xw,yw,zw):也称为测量坐标系,是一个三维直角坐标系,以其为基准可以描述相机和待测物体的空间位置。世界坐标系的位置可以根据实际情况自由确定。

为了进行相机标定,必须已知世界坐标系中足够多的三维空间点坐标,找到这些空间点在图像中投影点的二维图像坐标,并建立对应关系。世界坐标系中某个给定点投影到图像坐标系中被分为两个步骤:

1、世界坐标系 → 相机坐标系

设 (Xw,Yw,Zw)表示世界坐标系中的点, (Xc,Yc,Zc)表示相机坐标系中的点,则世界坐标系到相机坐标系的变换,其实就是一个刚体变换,可以由旋转矩阵 R 和平移矩阵 t 来表示

其中, R 为 3x3 的旋转矩阵, t 为 3x1 的平移向量。化为齐次坐标形式

2、相机坐标系 →图像物理坐标系(成像平面坐标系)

设 (x,y) 是图像物理坐标系中的点, 由于点 (Xc,Yc,Zc) 和相机坐标系的原点(相机光心)之间的连线,穿过图像物理坐标系所在的平面,因此,由相似三角形可得

整理可得:
最后可化成齐次坐标形式

相机内参与畸变参数

畸变参数(distortion parameters)
畸变(distortion)是对直线投影(rectilinear projection)的一种偏移。简单来说直线投影是场景内的一条直线投影到图片上也保持为一条直线。畸变简单来说就是一条直线投影到图片上不能保持为一条直线了,这是一种光学畸变(optical aberration),可能由于摄像机镜头的原因。

畸变一般可以分为:径向畸变、切向畸变
1、径向畸变来自于透镜形状
2、切向畸变来自于整个摄像机的组装过程
畸变还有其他类型的畸变,但是没有径向畸变、切向畸变显著
径向畸变:实际摄像机的透镜总是在成像仪的边缘产生显著的畸变,这种现象来源于“筒形”或“鱼眼”的影响。
切向畸变:是由于透镜制造上的缺陷使得透镜本身与图像平面不平行而产生的。

相机标定的步骤

1、打印一张棋盘格,把它贴在一个平面上,作为标定物。
2、通过调整标定物或摄像机的方向,为标定物拍摄一些不同方向的照片。
3、从照片中提取棋盘格角点。
4、估算理想无畸变的情况下,五个内参和六个外参。
5、应用最小二乘法估算实际存在径向畸变下的畸变系数。
6、极大似然法,优化估计,提升估计精度

标定实验

1.选择标定物

2.提取角点
OpenCV中自带了提取棋盘格中内角点的函数:findChessboardCorners()。这个函数的功能是确定输入图像中是否有棋盘格图案,并检测棋盘格的内角点。如果所有的内角点都找到了,那么函数返回一个非0值;如果没有找到所有的内角点,就会返回0。

3.求相机参数:内参数矩阵mtx,畸变系数dist,旋转向量rvecs,平移向量tvecs,

我准备的是下图这种格子数为7×7,内角点为6×6的棋盘格图片,手机型号为华为nova3e,从不同角度拍摄10张照片作为实验素材

import cv2
import numpy as np
import glob

# 找棋盘格角点
# 阈值
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
#棋盘格模板规格
w = 6   #内角点个数,内角点是和其他格子连着的点
h = 6

# 世界坐标系中的棋盘格点,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐标,记为二维矩阵
objp = np.zeros((w*h,3), np.float32)
objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2)
# 储存棋盘格角点的世界坐标和图像坐标对
objpoints = [] # 在世界坐标系中的三维点
imgpoints = [] # 在图像平面的二维点

images = glob.glob(r'C:\\Users\\17912\\PycharmProjects\\untitled\\*.jpg')
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # 找到棋盘格角点
    # 棋盘图像(8位灰度或彩色图像)  棋盘尺寸  存放角点的位置
    ret, corners = cv2.findChessboardCorners(gray, (w,h),None)
    # 如果找到足够点对,将其存储起来
    if ret == True:
        # 角点精确检测
        # 输入图像 角点初始坐标 搜索窗口为2*winsize+1 死区 求角点的迭代终止条件
        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()
#标定、去畸变
# 输入:世界坐标系里的位置 像素坐标 图像的像素尺寸大小 3*3矩阵,相机内参数矩阵 畸变矩阵
# 输出:标定结果 相机的内参数矩阵 畸变系数 旋转矩阵 平移向量
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
# mtx:内参数矩阵
# dist:畸变系数
# rvecs:旋转向量 (外参数)
# tvecs :平移向量 (外参数)
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('picture/5_d.jpg')
h,w = img2.shape[:2]
# 我们已经得到了相机内参和畸变系数,在将图像去畸变之前,
# 我们还可以使用cv.getOptimalNewCameraMatrix()优化内参数和畸变系数,
# 通过设定自由自由比例因子alpha。当alpha设为0的时候,
# 将会返回一个剪裁过的将去畸变后不想要的像素去掉的内参数和畸变系数;
# 当alpha设为1的时候,将会返回一个包含额外黑色像素点的内参数和畸变系数,并返回一个ROI用于将其剪裁掉
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('calibresult.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))

总结
角点提取的结果

实现相机的标定,运行结果如下:


1.OpenCV中自带了提取棋盘格中内角点的函数findChessboardCorners():确定输入图像中是否有棋盘格图案,并检测棋盘格的内角点。如果所有的内角点都找到了,那么函数返回一个非0值;如果没有找到所有的内角点,就会返回0。

以上是关于2021-05-23的主要内容,如果未能解决你的问题,请参考以下文章

《安富莱嵌入式周报》第213期:2021.05.17--2021.05.23

2021-05-23

2021-05-23

2021-05-23

2021-05-23

2021-05-23