使用OpenCV进行双目摄像头的标定与矫正

双目摄像头标定是计算机视觉中的一项重要技术,它可以帮助我们恢复场景的三维信息。本文将介绍如何使用OpenCV进行双目摄像头的标定与矫正,并提供相应的Python代码示例。

1. 环境准备

在开始之前,请确保已经安装了OpenCV库。可以通过以下命令安装:

pip install opencv-python opencv-python-headless numpy

2. 采集标定图像

进行双目标定的第一步是获取一组标定图像。通常使用棋盘格(如9x6)作为标定板。使用双目摄像头拍摄多组不同角度的棋盘格图像,并保存到文件夹中。

3. 计算棋盘角点

以下代码将读取棋盘格的图像,寻找角点,并保存它们的世界坐标和图像坐标:

import cv2
import numpy as np
import glob

# 设置标定板规格
chessboard_size = (9, 6)  # 内角点数
square_size = 1.0  # 每个方格的实际大小,单位可选

# 生成世界坐标点
objp = np.zeros((chessboard_size[0] * chessboard_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2) * square_size

# 用于保存对象点和图像点
objpoints = []  # 3D点在世界坐标系
imgpoints_left = []  # 2D点在左摄像头图像平面
imgpoints_right = []  # 2D点在右摄像头图像平面

# 读取左右图像
images_left = glob.glob('left/*.jpg')  # 左摄像头图像路径
images_right = glob.glob('right/*.jpg')  # 右摄像头图像路径

for img_left, img_right in zip(images_left, images_right):
    gray_left = cv2.imread(img_left, cv2.IMREAD_GRAYSCALE)
    gray_right = cv2.imread(img_right, cv2.IMREAD_GRAYSCALE)

    ret_left, corners_left = cv2.findChessboardCorners(gray_left, chessboard_size, None)
    ret_right, corners_right = cv2.findChessboardCorners(gray_right, chessboard_size, None)

    if ret_left and ret_right:
        objpoints.append(objp)
        imgpoints_left.append(corners_left)
        imgpoints_right.append(corners_right)

print("成功收集到的标定点数:", len(objpoints))

4. 双目标定

进行双目标定的另一重要步骤是通过以下代码计算相机内参数和外参数:

# 标定双目相机
ret, camera_matrix_left, dist_coeffs_left, camera_matrix_right, dist_coeffs_right, R, T, E, F = cv2.stereoCalibrate(
    objpoints,
    imgpoints_left,
    imgpoints_right,
    None,  # 左相机矩阵
    None,  # 左相机畸变系数
    None,  # 右相机矩阵
    None,  # 右相机畸变系数
    gray_left.shape[::-1],  # 图像尺寸
    criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
)

print("左相机内参:\n", camera_matrix_left)
print("右相机内参:\n", camera_matrix_right)
print("旋转矩阵:\n", R)
print("平移向量:\n", T)

5. 校正图像

为确保双目图像的畸变被消除,可以对获取的图像进行矫正:

def rectify_images(img_left, img_right):
    # 得到新的相机矩阵和ROI
    R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(
        camera_matrix_left, dist_coeffs_left, 
        camera_matrix_right, dist_coeffs_right, 
        gray_left.shape[::-1], R, T
    )

    # 获取矫正映射
    map1_left, map2_left = cv2.initUndistortRectifyMap(camera_matrix_left, dist_coeffs_left, R1, P1, gray_left.shape[::-1], cv2.CV_32FC1)
    map1_right, map2_right = cv2.initUndistortRectifyMap(camera_matrix_right, dist_coeffs_right, R2, P2, gray_right.shape[::-1], cv2.CV_32FC1)

    # 进行矫正
    rect_left = cv2.remap(img_left, map1_left, map2_left, cv2.INTER_LINEAR)
    rect_right = cv2.remap(img_right, map1_right, map2_right, cv2.INTER_LINEAR)

    return rect_left, rect_right

# 示例矫正图像
img_left = cv2.imread('left/sample.jpg')
img_right = cv2.imread('right/sample.jpg')
rect_left, rect_right = rectify_images(img_left, img_right)

cv2.imshow('Rectified Left', rect_left)
cv2.imshow('Rectified Right', rect_right)
cv2.waitKey(0)
cv2.destroyAllWindows()

6. 总结

以上就是使用OpenCV进行双目摄像头标定及矫正的基本步骤。从标定图像的采集,到计算相机内外参数,再到图像的矫正,每一步都至关重要。希望这篇文章和代码能帮助你更好地理解并应用双目摄像头标定技术。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部