标定的步骤如下:
1. 准备棋盘格,棋盘格图片可以自行打印,以下使用10*7方格的棋盘格,交点则为9*6,棋盘格的大小1mm,即 gridsize=1
2. 拍照,拍照的原则是多角度,根据理论至少要两种角度的拍照,实际中通常会拍20张左右;
3. 使用opencv提供的角点检测函数findChessboardCorners找到棋盘格中的角点,并将每幅图片的角点值存放到list中,同时将棋盘格的角点的三维坐标存放到另一个list。
4. 使用calibrateCamera函数获取内存矩阵、畸变矩阵、旋转矩阵以及转移矩阵。
5.使用undistort函数将畸变的图像进行校正并查看校正后的图片效果。
代码如下:
# coding:utf-8
"""
相机校正
学会用棋盘格进行相机校正(张正友标定法)
熟悉opencv相关函数
cv2.findChessboardCorners
cv2.cornerSubPix
cv2.drawChessboardCorners
cv2.calibrateCamera
cv2.undistort
"""
import numpy as np
import cv2
def calibrate_camera():
# 每个校准图像映射到棋盘角到数量
objPoints = {
1: (9, 6),
2: (9, 6),
3: (9, 6),
4: (9, 6),
5: (9, 6),
6: (9, 6),
7: (9, 6),
8: (9, 6),
9: (9, 6),
10: (9, 6),
11: (9, 6),
12: (9, 6),
13: (9, 6),
14: (9, 6),
15: (9, 6),
16: (9, 6),
17: (9, 6),
18: (9, 6),
19: (9, 6),
20: (9, 6),
}
# 目标点空间坐标
obj3DList = []
# 图像中棋盘格中的2D点
obj2DList = []
for k in objPoints:
nx, ny = objPoints[k]
######棋盘格对应3D坐标点,x为0-8, y为0-4(对应棋盘格横着9个点,纵着5个点), z = 0
obj = np.zeros((nx * ny, 3), np.float32)
obj[:, :2] = np.mgrid[0: nx, 0: ny].T.reshape(-1, 2)
fname = 'camera_cal_pic/calibration%s.jpg' % str(k)
img = cv2.imread(fname)
# 将图像转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
########查找角点,利用cv2.findChessboardCorners函数,函数返回
####ret:是否查找到; corners:角点坐标
#####################填空1 (一行代码)#####################################
ret, corners = cv2.findChessboardCorners(gray, (nx, ny))
#########################################################################
if ret == True:
obj3DList.append(obj)
# 利用cv2.cornerSubPix可以更精细的查找角点坐标,如果查找到了,用这个,没查找到用cv2.findChessboardCorners中找到的角点
corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1),
criteria=(cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001))
if corners2.any():
obj2DList.append(corners2)
else:
obj2DList.append(corners)
# 可以利用cv2.drawChessboardCorners显示每张图查找到的角点的坐标
# cv2.drawChessboardCorners(img, (nx, ny), corners, ret)
# cv2.imshow("img", img)
# cv2.waitKey(0)
else:
print('Warning: ret = %s for %s' % (ret, fname))
img = cv2.imread('testImage/straight_lines1.jpg')
img_size = (img.shape[1], img.shape[0])
# 利用图像中2d点和空间3d点计算旋转和平移矩阵,函数使用cv2.calibrateCamera,返回mtx(相机内参矩阵), dist(畸变矩阵)
################填空2(一行代码)################################################
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj3DList, obj2DList, img_size, None,None)
##############################################################################
return mtx, dist
if __name__ == '__main__':
mtx, dist = calibrate_camera()
print("mtx, dist", mtx, dist)
img = cv2.imread('./camera_cal_pic/calibration1.jpg')
##########将img进行校正,利用cv2.undistort这个函数,根据相机内参和外参进行相机校正,校正后的图像为dst
####################填空3(一行代码)#################################################
dst = cv2.undistort(img, mtx, dist)
###################################################################################
cv2.imwrite('./camera_cal_pic_undistort/calibration1_undistort.jpg', dst)
cv2.imshow("dst", dst)
cv2.waitKey()
完整项目代码gihub: