You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在OpenCV Python中获取适配不同距离的跨相机Homography矩阵以叠加图像?

不同距离下RGB与DVS图像匹配解决方案

问题本质

单应性(Homography)矩阵只适用于两种场景:

  • 拍摄目标是严格平面
  • 相机只有旋转,没有平移/距离变化

当拍摄距离改变时,相机存在平移,三维场景的投影会产生透视差异,单应性矩阵没法建模这种和深度相关的变换,所以靠多组距离的棋盘格求解单应性根本没用。

正确解决思路:双目联合标定+透视矫正

要实现任意距离下的图像匹配,必须先完成两台相机的联合标定,拿到各自的内参、畸变系数,以及相机之间的相对位姿(旋转矩阵R、平移向量T),之后通过透视矫正把两台相机的图像对齐到同一平面,就能完美叠加。

步骤1:双目联合标定

用棋盘格拍多组不同姿态(不同距离、角度)的图像,用OpenCV的stereoCalibrate完成标定:

import cv2
import numpy as np

# 棋盘格参数:格子数量(内角点)、单格实际尺寸(单位:米)
chessboard_size = (8, 5)
square_size = 0.02

# 生成世界坐标系下的棋盘格点
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 = []       # 世界坐标系点
rgb_img_points = []   # RGB相机像素点
dvs_img_points = []   # DVS相机像素点

# 遍历所有标定图像对
for rgb_path, dvs_path in zip(rgb_path_list, dvs_path_list):
    rgb_img = cv2.imread(rgb_path)
    dvs_img = cv2.imread(dvs_path)

    rgb_gray = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2GRAY)
    dvs_gray = cv2.cvtColor(dvs_img, cv2.COLOR_BGR2GRAY)

    # 检测棋盘格角点
    ret_rgb, corners_rgb = cv2.findChessboardCorners(rgb_gray, chessboard_size, cv2.CALIB_CB_ADAPTIVE_THRESH)
    ret_dvs, corners_dvs = cv2.findChessboardCorners(dvs_gray, chessboard_size, cv2.CALIB_CB_ADAPTIVE_THRESH)

    if ret_rgb and ret_dvs:
        # 亚像素优化角点,提升标定精度
        corners_rgb = cv2.cornerSubPix(rgb_gray, corners_rgb, (11,11), (-1,-1), 
                                       (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))
        corners_dvs = cv2.cornerSubPix(dvs_gray, corners_dvs, (11,11), (-1,-1), 
                                       (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))
        
        obj_points.append(objp)
        rgb_img_points.append(corners_rgb)
        dvs_img_points.append(corners_dvs)

# 执行双目标定
ret, mtx_rgb, dist_rgb, mtx_dvs, dist_dvs, R, T, E, F = cv2.stereoCalibrate(
    obj_points, rgb_img_points, dvs_img_points,
    None, None, None, None, rgb_gray.shape[::-1],
    criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-5),
    flags=cv2.CALIB_FIX_INTRINSIC  # 如果已经单独标定过内参,改成CALIB_USE_INTRINSIC_GUESS
)

步骤2:透视矫正与图像叠加

利用标定得到的参数,把两台相机的图像矫正到同一平面,之后直接叠加即可:

# 获取图像尺寸
h_rgb, w_rgb = rgb_img.shape[:2]
h_dvs, w_dvs = dvs_img.shape[:2]

# 计算双目矫正参数
R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(
    mtx_rgb, dist_rgb, mtx_dvs, dist_dvs, (w_rgb, h_rgb), R, T,
    alpha=1.0  # alpha=1保留所有像素,alpha=0只保留有效区域
)

# 生成矫正映射表
map_rgb_x, map_rgb_y = cv2.initUndistortRectifyMap(mtx_rgb, dist_rgb, R1, P1, (w_rgb, h_rgb), cv2.CV_32FC1)
map_dvs_x, map_dvs_y = cv2.initUndistortRectifyMap(mtx_dvs, dist_dvs, R2, P2, (w_rgb, h_rgb), cv2.CV_32FC1)

# 对图像进行矫正
rgb_rectified = cv2.remap(rgb_img, map_rgb_x, map_rgb_y, cv2.INTER_LINEAR)
dvs_rectified = cv2.remap(dvs_img, map_dvs_x, map_dvs_y, cv2.INTER_LINEAR)

# 叠加显示
dst = cv2.addWeighted(rgb_rectified, 0.5, dvs_rectified, 0.5, 0)
cv2.imshow('Aligned Overlay', dst)
cv2.waitKey(0)

重要提示

  • 标定图像要够多:至少拍10组不同姿态的图像,棋盘格要出现在画面的不同位置、不同角度,避免标定误差过大。
  • 畸变必须先矫正:不管是单相机还是双目,畸变都会严重影响匹配精度,必须在标定后进行矫正。
  • 三维场景的特殊处理:如果拍摄的是复杂三维场景,仅靠矫正还不够,需要结合深度信息(比如通过双目匹配生成深度图)才能让RGB图像精准投影到DVS视角。

内容的提问来源于stack exchange,提问作者Robin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 13:14:56