Python OpenCV 双目标定与测距指南

一、流程概述

在进行双目标定和测距之前,我们需要了解所需的步骤。整个过程可以分为以下几个步骤:

阶段 步骤 说明
数据采集 Camera Calibration Data 收集标定图像,获取相机内参数和畸变系数
标定 Stereo Calibration 进行双目标定,计算相机之间的关系
计算深度距离 Depth Calculation 使用视差计算测距

二、每一步的实现

1. 数据采集(Camera Calibration Data)

在此步骤中,我们需要准备一些用于标定的图像,通常使用棋盘格图案。采集多张图像后我们可以通过 OpenCV 进行相机标定,来获取相机的内参数和畸变系数。

获取相机内参数和畸变系数的代码示例
import cv2
import numpy as np
import glob

# 准备棋盘格模型
chessboard_size = (9, 6)  # 内角点数量(列,行)
square_size = 0.025  # 每个方格的真实世界尺寸(根据实际情况调整)

# 准备对象点和图像点
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

obj_points = []  # 3D点
img_points = []  # 2D点

# 读取标定图像
images = glob.glob('calibration_images/*.jpg')  # 图像路径

# 遍历图像进行角点检测
for img_path in images:
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)
    
    if ret:
        obj_points.append(objp)
        img_points.append(corners)

# 相机标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None)
注释
  • np.mgrid 用于生成棋盘格的3D模型;
  • cv2.findChessboardCorners 用于检测图像中的棋盘格角点;
  • cv2.calibrateCamera 用于获取相机的内参数(mtx)和畸变系数(dist)。

2. 双目标定(Stereo Calibration)

双目标定的目的是确定两个相机之间的相对位置和姿态。我们将使用两台相机的标定结果,构建立体视觉系统。

双目标定的代码示例
# 假设已经得到左相机和右相机的标定参数, obj_points, img_points_left, img_points_right
# img_points_left & img_points_right是左右相机获取的角点

flags = 0
flags |= cv2.CALIB_FIX_INTRINSIC  # 固定内参数
ret, _, _, _, _, R, T, E, F = cv2.stereoCalibrate(
    obj_points, img_points_left, img_points_right, mtx_left, dist_left, mtx_right, dist_right, gray.shape[::-1], flags=flags
)
注释
  • cv2.stereoCalibrate 用于进行双目标定,返回旋转矩阵(R)和平移向量(T)等信息。

3. 计算深度距离(Depth Calculation)

一旦我们得到了双目标定的参数,我们就可以计算图像中各个点的深度信息。这个通常通过计算视差来实现。

计算视差和深度的代码示例
# 读取左右图像
imgL = cv2.imread('left_image.jpg')
imgR = cv2.imread('right_image.jpg')

# 创建StereoSGBM对象
stereo = cv2.StereoSGBM_create(minDisparity=0,
                                numDisparities=16,  # 视差范围
                                blockSize=5)

# 计算视差图
disparity = stereo.compute(imgL, imgR).astype(np.float32) / 16.0

# 计算深度图
focal_length = mtx_left[0, 0]  # 使用左相机的焦距
baseline = np.linalg.norm(T)  # 基线距离
depth_map = (focal_length * baseline) / disparity
注释
  • cv2.StereoSGBM_create 创建一个立体匹配对象;
  • stereo.compute 用于计算视差图;
  • 根据视差计算深度图。

三、模型关系图

以下是模型的关系图,展示了相机、内参数和标定结果的关系:

erDiagram
    Camera {
        string id
        float focal_length
        float[] distortion_coefficients
    }
    
    CalibrationResult {
        float[] rotation_matrix
        float[] translation_vector
    }
    
    Camera ||--o| CalibrationResult : has

四、甘特图

下面的甘特图清晰地列出整个流程的时间安排:

gantt
    title 开发流程时间表
    dateFormat  YYYY-MM-DD
    section 数据采集
    摄像头标定图像采集 :a1, 2023-10-01, 7d
    section 双目标定
    双目标定和参数计算 :after a1, 5d
    section 深度计算
    深度图计算 :after a1, 3d

五、结尾

通过上述步骤和代码示例,你应该能够理解并实现“Python OpenCV 双目标定与测距”的完整流程。在实际操作中,可能会遇到各种边缘情况和问题,建议多做实验和调试,以加深对代码及其实现的理解。同时,可以参考OpenCV的官方文档,获取更多详细信息。祝你在计算机视觉的学习旅程中取得优异的成果!