在这篇博客中【ZED】从零开始使用ZED相机(三):相机标定(张氏标定法)相机标定实现起来十分麻烦,且笔者测试下来标定的参数并不准确,而OpenCV中就是直接实现相机标定的库,调用起来十分方便,而且也比较准确。
1 cv2.calibrateCamera 实现单目相机校正首先肯定是先采集好棋盘格图像15-20张左右,放在一个文件夹下面如图(笔者采集的比较多,MATLAB计算的重投影误差太大时可以剔除掉一部分图象):
# 类二:相机标定执行函数(单目校正)
class Cam_calibrate(): # 执行校正
def __init__(self):
# 终止条件
self.criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 准备对象点,棋盘方块交界点排列:6行8列 如 (0,0,0), (1,0,0), (2,0,0) ....,(6,8,0)
self.row,self.col = 8,11
self.objpoints = np.zeros((self.row * self.col, 3), np.float32)
self.objpoints[:, :2] = np.mgrid[0:self.row, 0:self.col].T.reshape(-1, 2)
def exe(self,dir):
objectpoints = [] # 真实世界中的3d点
imgpoints = []
# 标定所用图像
images = glob.glob('%s/*'%dir)
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 寻找到棋盘角点
ret, corners = cv2.findChessboardCorners(img, (self.row, self.col), None)
# 如果找到,添加对象点,图像点(细化之后)
if ret == True:
# 添加每幅图的对应3D-2D坐标
objectpoints.append(self.objpoints)
corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1),self.criteria)
imgpoints.append(corners)
# 绘制并显示拐角
# cv2.drawChessboardCorners(img, (self.row, self.col), corners, ret)
# cv2.namedWindow('View')
# cv2.imshow("View", img)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# 输出:相机内参、畸变系数、旋转矩阵(每个点都会得到一个)、平移矩阵(同左)
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objectpoints, imgpoints, gray.shape[::-1], None, None)
print(ret,'n返回相机矩阵:%sn失真系数:%sn旋转矩阵:%sn%sn平移向量::%sn%s '%(mtx, dist, rvecs[0].shape,rvecs, tvecs[0].shape,tvecs))
函数调用如下:
if __name__ == "__main__":
# 单目校正
path = r'E:Alianyolov5zed-examples-masterimages1080L' # 棋盘格图片路径
cal = Cam_calibrate()
cal.exe(path)
终端打印结果如下:
如上图所示,第一个返回的值笔者还未找到其含义,随后依次是:相机内参,畸变系数,旋转矩阵和平移向量。
这里大家会注意到一个问题:旋转矩阵和平移向量都是一个列表且包含多项(3,1)维度的数组构成,如下解释:
(1)一个多元素的列表?
每个姿态拍摄的棋盘格图象都会求出该姿态下的旋转矩阵和平移向量,该列表的长度就是棋盘格图象的数量
(2)旋转矩阵列表的每个元素都为(3,1)?
按理旋转矩阵维度是3x3,但是由于旋转矩阵正交阵,该矩阵的特点是对角线的值为1,其他元素关于对角线对称,便于理解笔者将其表示如下图,可能是为了节省内存只保留有效的数值,因此得出的旋转矩阵参数也是(3,1)(以上是笔者的个人理解,有任何不对的地方还望指出哈!)
(1)相机内参
MATLAN结果:
OpenCV结果:
(2)畸变系数
MATLAN结果:(默认K3=0)
OpenCV结果:
旋转矩阵和平移数量过多就不放上来比较了,综上,内参还是相对比较接近的(不要求高精度的前提下),畸变就有一定差距了,总之MATLAB的标定效果肯定会更好的,其次标定过程的任何一步都会影响最终标定的结果(标定板精度,拍摄姿态角等)。



