鱼眼相机内参标定
理论参考
https://niecongchong.blog.csdn.net/article/details/122944975
代码参考
https://blog.csdn.net/m0_58772523/article/details/121585684
准备工作
使用鱼眼相机从多个角度对棋盘格拍照(棋盘格可大可小,只要能检测出角点即可),并将其保存在同一文件夹下。
计算内参
import cv2
import numpy as np
import glob
def calib(inter_corner_shape, size_per_grid, path):
# 获取棋盘格角点个数
w, h = inter_corner_shape
# 世界坐标维度为三,与角点维度对齐
# 普通相机校正中世界坐标比角点坐标少一个维,在鱼眼相机校正中少一维会报错
cp_int = np.zeros((1, w * h, 3), np.float32)
cp_int[0, :, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2).astype(np.float64)
cp_world = cp_int * size_per_grid
# 检测亚像素角点
subpix_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)
# 标定方法
calibration_flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC + cv2.fisheye.CALIB_CHECK_COND + cv2.fisheye.CALIB_FIX_SKEW
# 图像尺寸
img_shape = None
# 世界坐标
obj_points = []
# 角点坐标
img_points = []
# 获取图片
images = glob.glob(path + '/*.jpg')
for fname in images:
img = cv2.imread(fname)
# 使用第一张图片得到图像尺寸
if img_shape == None:
img_shape = img.shape[:2]
else:
assert img_shape == img.shape[:2], "All images must share the same size."
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# print(gray_img)
# print(type(gray_img))
# 找角点
ret, corners = cv2.findChessboardCorners(gray_img, (w, h),
cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)
if ret == True:
obj_points.append(cp_world)
# 添加亚像素角点信息
cv2.cornerSubPix(gray_img, corners, (3, 3), (-1, -1), subpix_criteria)
img_points.append(corners)
# 实际图片数
imgs = len(obj_points)
# 初始化内参、畸变系数以及旋转和平移向量
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(imgs)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(imgs)]
# 鱼眼相机校正
rms, _, _, _, _ = cv2.fisheye.calibrate(
obj_points, img_points, gray_img.shape[::-1], K, D, rvecs, tvecs, calibration_flags,
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6))
# 用于图片校正时调整图片尺寸
DIM = img_shape[::-1]
print("Found " + str(imgs) + " valid images for calibration")
#只有检测出指定角点数量的图片才会用于计算,如果没有照片被检测出来则会报错。
print("DIM=" + str(img_shape[::-1])) #图片大小
print("K=np.array(" + str(K.tolist()) + ")") #
print("D=np.array(" + str(D.tolist()) + ")")
return DIM, K, D
if __name__ == '__main__':
inter_corner_shape = (9, 6) #棋盘格角点数量
size_per_grid = 0.06
path='back' #选择该镜头所拍照片所在文件
DIM, K, D = calib(inter_corner_shape, size_per_grid, path)