基于python的双目标定

文章目录

    • 前言
    • 程序与解析:


前言

  在双目视觉中,标定摄像机是一个非常重要的步骤。本文将展示如何用Python和OpenCV对双目相机进行标定。

程序与解析:

  首先,需要准备标定图片,将分别从左侧和右侧拍摄多张不同角度的标定图片,并把它们存储在两个不同的文件夹中。接下来,需要定义一个棋盘格参数,这里我使用了一个8x11格的黑白棋盘格,每个方块大小为15毫米。

  接着,使用OpenCV读取所有的标定图片,并检测棋盘格角点。使用cornerSubPix函数进行亚像素级别的角点检测,以得到更加准确的角点坐标。如果左右图像的角点都被检测到,则将角点存储到对应的列表中。

  存储完角点之后,使用cv2.calibrateCamera函数计算摄像机的内参数矩阵和畸变系数。需要注意的是,需要分别对左右摄像机进行标定。有了左右摄像机的内参数矩阵和畸变系数之后,接下来就可以进行双目相机的标定了。

  使用cv2.stereoCalibrate函数来标定双目相机。在此函数中,需要传递左右摄像机的内参数矩阵和畸变系数,以及之前存储的角点坐标。函数将返回一些重要的参数供后续使用,比如旋转矩阵、平移矩阵、本质矩阵、基础矩阵等等。

  最后,打印出计算出来的一些重要参数的值,比如左右摄像机的内参数矩阵、畸变系数、旋转矩阵、平移矩阵、本质矩阵和基础矩阵。

import numpy as np
import cv2
import os

# 获取标定图片路径
path_left = "./data/left/"
path_right = "./data/right/"

# 定义棋盘格参数
CHESSBOARD_SIZE = (8, 11)
CHESSBOARD_SQUARE_SIZE = 15  # mm

# 获取图片列表
img_list_left = sorted(os.listdir(path_left))
img_list_right = sorted(os.listdir(path_right))

# 定义物理坐标系下的角点坐标
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) * CHESSBOARD_SQUARE_SIZE

# 定义检测角点的终止准则
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 定义用于存储角点坐标的列表
obj_points = []
img_points_left = []
img_points_right = []

# 读取标定图片并检测角点
for i in range(len(img_list_left)):
    img_l = cv2.imread(path_left + img_list_left[i])
    print(img_list_left[i])
    img_r = cv2.imread(path_right + img_list_right[i])
    gray_l = cv2.cvtColor(img_l, cv2.COLOR_BGR2GRAY)
    gray_r = cv2.cvtColor(img_r, cv2.COLOR_BGR2GRAY)

    # 检测角点
    ret_l, corners_l = cv2.findChessboardCorners(gray_l, CHESSBOARD_SIZE, None)
    ret_r, corners_r = cv2.findChessboardCorners(gray_r, CHESSBOARD_SIZE, None)

    # 如果左右图像的角点都被检测到,则将角点存储到对应的列表中
    if ret_l and ret_r:
        obj_points.append(objp)

        # 通过亚像素级别的角点检测得到更准确的角点坐标
        cv2.cornerSubPix(gray_l, corners_l, (11, 11), (-1, -1), criteria)
        img_points_left.append(corners_l)
        cv2.drawChessboardCorners(img_l, CHESSBOARD_SIZE, corners_l, ret_l)
        cv2.imshow("Chessboard Corners - Left", cv2.resize(img_l,(img_l.shape[1]//2,img_l.shape[0]//2)))
        cv2.waitKey(50)

        cv2.cornerSubPix(gray_r, corners_r, (11, 11), (-1, -1), criteria)
        img_points_right.append(corners_r)
        cv2.drawChessboardCorners(img_r, CHESSBOARD_SIZE, corners_r, ret_r)
        cv2.imshow("Chessboard Corners - Right", cv2.resize(img_r,(img_r.shape[1]//2,img_r.shape[0]//2)))
        cv2.waitKey(50)

cv2.destroyAllWindows()

print("Number of chessboard images used for calibration: ", len(obj_points))

# 标定摄像机
ret_l, mtx_l, dist_l, rvecs_l, tvecs_l = cv2.calibrateCamera(obj_points, img_points_left, gray_l.shape[::-1],None,None)
ret_r, mtx_r, dist_r, rvecs_r, tvecs_r = cv2.calibrateCamera(obj_points, img_points_right, gray_r.shape[::-1],None,None)

# 标定双目摄像机
flags = 0
flags |= cv2.CALIB_FIX_INTRINSIC
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
ret, M1, d1, M2, d2, R, T, E, F = cv2.stereoCalibrate(
        obj_points, img_points_left, img_points_right,
        mtx_l, dist_l, mtx_r, dist_r,
        gray_l.shape[::-1], criteria=criteria, flags=flags)

print("内参数矩阵M1:\n", M1)
print("畸变系数d1:\n", d1)
print("内参数矩阵M2:\n", M2)
print("畸变系数d2:\n", d2)
print("旋转矩阵R:\n", R)
print("平移矩阵T:\n", T)
print("本质矩阵E:\n", E)
print("基础矩阵F:\n", F)


你可能感兴趣的:(双目视觉,python,opencv,计算机视觉)