使用python和opencv实现相机标定

本文详细介绍了如何使用Python和OpenCV进行相机标定,包括准备标定板图像、标定步骤(角点检测、优化、收集数据、标定计算和参数保存),以及实际的代码示例。相机标定对于计算机视觉和三维重建至关重要,能精确映射像素坐标到世界坐标。
摘要由CSDN通过智能技术生成

使用python和opencv实现相机标定

相机标定

相机标定是确定相机内部参数(例如焦距、光学中心)和畸变(镜头失真)的过程,以便将像素坐标转换为世界坐标或者将世界坐标转换为像素坐标,从而在计算机视觉、三维重建等领域中准确地理解和处理图像信息。

输入数据通常包括拍摄的图像或者视频序列,以及相机的参数信息(例如相机型号、传感器尺寸等)。输出结果通常是相机的内部参数矩阵(如相机的焦距、主点坐标等)和外部参数(相机的位置和朝向),以及可能的畸变参数(用于校正图像失真)。一般情况下,通过在不同位置、角度、距离下拍摄标定板的图像,你可以收集到不同视角下标定板在图像中的像素坐标以及标定板上已知的三维坐标(通常是平面上的点)。这些数据将用于相机标定,从而推导出相机的内部参数(如焦距、主点坐标等)和外部参数(相机的位置和朝向)。

1. 准备标定板图像

准备一个已知尺寸和形状的标定板,一般使用(checkboard)棋盘格,拍摄多张包含这个标定板的图像。确保标定板在图像中的各种角度和位置都有覆盖。
checkboard
以上为标定板的样例。

2. 标定代码

实现相机标定的基本步骤为哦噢:

(1). 棋盘格角点检测:使用cv2.findChessboardCorners函数检测棋盘格图案在图像中的角点。这个函数寻找特定大小的棋盘格内角点的位置。

(2). 优化角点像素坐标:对检测到的角点进行优化,使用cv2.cornerSubPix函数对像素级别的角点坐标进行精确化处理。这个步骤提高了检测到的角点的精度。

(3). 收集标定数据:将优化后的角点坐标(二维图像中的坐标)和已知的棋盘格上的三维坐标(世界坐标系中的坐标)对应起来,并保存这些数据,用于后续的相机标定。

(4). 相机标定:使用cv2.calibrateCamera函数根据已知的三维-二维点对来进行相机标定。该函数利用收集到的标定数据,计算出相机的内部参数(如相机矩阵、畸变参数等)和外部参数(相机的位置和朝向)。

(5). 保存相机参数:最后,将计算得到的相机内参、畸变参数、相机位置和朝向等数据,以便后续使用。

整个过程基于相机成像原理和棋盘格的已知几何特征,通过收集标定图像上的棋盘格角点信息,利用这些已知的2D-3D点对,计算出相机的内部和外部参数,从而实现相机的标定。以下为基于python的代码:

import glob
import cv2
import pickle
import numpy as np

# 定义棋盘格的维度
CHECKERBOARD = (6, 8) # 我的棋盘格是7*9
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

objpoints = []
imgpoints = []

# 定义世界坐标系中的3D点
objp = np.zeros((1, CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32)
objp[0, :, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
prev_img_shape = None

images = glob.glob('./checkboard/*.jpg')
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD,
                                             cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)

    if ret == True: # 如果找到角点
        objpoints.append(objp)
        corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
        imgpoints.append(corners2)

        # 画图并展示角点
        img = cv2.drawChessboardCorners(img, CHECKERBOARD, corners2, ret)

    desired_width = 640  # 替换为你想要的宽度
    desired_height = 480  # 替换为你想要的高度
    img_resized = cv2.resize(img, (desired_width, desired_height))
    cv2.imshow('Visualize IMG', img_resized)
    cv2.waitKey(100)
cv2.destroyAllWindows()

h, w = img.shape[:2]

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

print("Camera matrix : \n")
print(mtx)
print("dist : \n")
print(dist)
print("rvecs : \n")
print(rvecs)
print("tvecs : \n")
print(tvecs)

运行上述代码之后,我的相机标定结果为:

Camera matrix : 
[[3.49017392e+03 0.00000000e+00 2.33493976e+03]
 [0.00000000e+00 3.48812132e+03 1.73653124e+03]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00]]

dist : 
[[ 4.31081356e-02 -2.14314100e-01  3.16324064e-04  1.37368140e-05
   3.83524452e-01]]

rvecs : 
(array([[0.10733804],
       [0.03581478],
       [1.57752917]]), array([[0.26197925],
       [0.17000535],
       [1.52887916]]), array([[ 0.23831319],
       [-0.29249928],
       [ 1.55283966]]), array([[-0.14243786],
       [-0.0783745 ],
       [-1.53007322]]), array([[-0.12563654],
       [-0.30528986],
       [ 1.5596221 ]]))

tvecs : 
(array([[ 3.69696489],
       [-2.4605232 ],
       [10.3670443 ]]), array([[ 2.80876299],
       [-2.61246982],
       [ 8.01137576]]), array([[ 3.81541091],
       [-1.83905007],
       [ 8.49963633]]), array([[-3.33722804],
       [ 2.02980881],
       [ 9.65504995]]), array([[ 4.49071749],
       [-2.72048691],
       [10.77570147]]))

3. 总结

相机标定确定了相机的内部和外部参数,包括焦距、畸变等,使得像素坐标能够准确映射到世界坐标或相反。这为位姿估计提供了基础,通过相机标定获得的参数,可以在计算机视觉中精确地定位物体、重建场景,实现位姿估计并在增强现实、三维重建等领域中应用。

要进行相机标定,可以使用OpenCV库中的`cv2.calibrateCamera()`函数。相机标定是指确定相机的内参数(焦距、主点)和外参数(旋转矩阵、平移向量)的过程。 以下是一个简单的相机标定的示例代码: ```python import cv2 import numpy as np # 需要标定的棋盘格尺寸 pattern_size = (9, 6) square_size = 0.025 # 棋盘格方块尺寸(米) # 准备棋盘格角点的世界坐标 object_points = np.zeros((np.prod(pattern_size), 3), dtype=np.float32) object_points[:, :2] = np.indices(pattern_size).T.reshape(-1, 2) * square_size # 存储图像角点的世界坐标和图像坐标 world_points = [] image_points = [] # 打开摄像头并读取图像 cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: break # 检测棋盘格角点 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) ret, corners = cv2.findChessboardCorners(gray, pattern_size, None) # 如果检测到角点,则添加到列表中 if ret: world_points.append(object_points) image_points.append(corners) # 在图像上绘制角点 cv2.drawChessboardCorners(frame, pattern_size, corners, ret) # 显示图像 cv2.imshow('Calibration', frame) # 按下 'q' 键退出 if cv2.waitKey(1) & 0xFF == ord('q'): break # 关闭摄像头 cap.release() cv2.destroyAllWindows() # 相机标定 ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(world_points, image_points, gray.shape[::-1], None, None) # 打印相机内参数和外参数 print("Camera Matrix:\n", camera_matrix) print("Distortion Coefficients:\n", dist_coeffs) print("Rotation Vectors:\n", rvecs) print("Translation Vectors:\n", tvecs) ``` 在这个示例中,我们使用了一个9x6大小的棋盘格作为标定板,每个格子的尺寸为0.025米。程序会打开摄像头,读取图像,并检测棋盘格角点。检测到的角点会存储在`world_points`和`image_points`列表中。最后使用`cv2.calibrateCamera()`函数进行相机标定,得到相机的内参数(`camera_matrix`)和畸变参数(`dist_coeffs`),以及每张图片对应的旋转矩阵(`rvecs`)和平移向量(`tvecs`)。 注意,相机标定需要至少10-20幅棋盘格图像来获得较好的结果。此外,在实际应用中,可能需要对图片进行去畸变处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值