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

如何提升长卡车环视(Bird View)系统双摄像头图像拼接精度?

卡车环视系统双摄像头拼接优化方案

一、基于4×6棋盘格实现精准拼接的方案

完全可以利用4×6棋盘格实现更高精度的拼接,棋盘格角点是人工标定的高精度特征,相比自然特征点(如KAZE)匹配更稳定,能有效减少单应性矩阵的计算误差,解决拼接不平整的问题。具体步骤:

  • 拍摄双摄像头同时覆盖的棋盘格图像,确保棋盘格位于两个摄像头的重叠区域,且尽可能占据更多重叠空间。
  • 检测两张图像中的棋盘格角点,获取精准的对应点对。
  • 用这些对应角点直接计算单应性矩阵,替代原有自然特征匹配的流程。

二、现有代码的核心问题与优化方向

原代码存在两个导致接缝明显、拼接不平整的核心问题:

  • 直接用原图覆盖拼接区域,没有做过渡融合,导致接缝生硬;
  • 自然特征点匹配存在误匹配,单应性矩阵精度不足,造成拼接错位。

针对这些问题,优化措施包括:

  1. 替换特征匹配为棋盘格角点匹配:提升单应性矩阵计算精度;
  2. 添加重叠区域渐变融合:对两张图的重叠区域做加权平均,消除接缝;
  3. 可选色彩校正:对齐两张图像的亮度与色彩,减少视觉差异。

三、修改后的完整代码

import cv2 as cv
import numpy as np

# 棋盘格参数:4行6列内角点
CHESSBOARD = (6, 4)

def get_chessboard_corners(img):
    # 转为灰度图
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # 检测棋盘格角点
    ret, corners = cv.findChessboardCorners(gray, CHESSBOARD, None)
    if not ret:
        print("未检测到棋盘格角点,请重新拍摄图像")
        exit(0)
    # 亚像素级优化角点精度
    criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
    corners = cv.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
    return corners

def compute_homography_from_chessboard(corners1, corners2):
    # 直接用棋盘格对应角点计算单应性矩阵
    H, status = cv.findHomography(corners2, corners1, cv.RANSAC, 5.0)
    return H, status

def get_new_frame_size(H, sec_shape, base_shape):
    h, w = sec_shape
    # 计算变换后副图的四个角点位置
    corners = np.float32([[0,0], [w-1,0], [w-1,h-1], [0,h-1]]).reshape(-1,1,2)
    transformed_corners = cv.perspectiveTransform(corners, H)
    # 获取所有角点的x、y极值
    x_coords = transformed_corners[:,:,0].flatten()
    y_coords = transformed_corners[:,:,1].flatten()
    min_x, max_x = int(np.floor(min(x_coords))), int(np.ceil(max(x_coords)))
    min_y, max_y = int(np.floor(min(y_coords))), int(np.ceil(max(y_coords)))
    # 计算新画布尺寸,确保容纳两张图
    new_w = max(base_shape[1], max_x) - min(min_x, 0)
    new_h = max(base_shape[0], max_y) - min(min_y, 0)
    # 偏移量,确保变换后图像不超出画布
    offset_x = abs(min_x) if min_x < 0 else 0
    offset_y = abs(min_y) if min_y < 0 else 0
    # 更新单应性矩阵,加入偏移
    translation_mat = np.array([[1,0,offset_x], [0,1,offset_y], [0,0,1]], dtype=np.float32)
    H_updated = np.dot(translation_mat, H)
    return (new_h, new_w), (offset_x, offset_y), H_updated

def blend_images(base_img, warped_sec_img, offset_x, offset_y):
    # 获取两张图的重叠区域范围
    base_start_x = offset_x
    base_end_x = offset_x + base_img.shape[1]
    base_start_y = offset_y
    base_end_y = offset_y + base_img.shape[0]
    
    # 计算重叠区域宽度,生成渐变权重掩码
    overlap_width = base_img.shape[1] - max(0, base_end_x - warped_sec_img.shape[1])
    overlap_mask = np.zeros_like(warped_sec_img, dtype=np.float32)
    
    if overlap_width > 0:
        # 横向渐变加权,让拼接过渡更自然
        for x in range(base_start_x, base_end_x):
            weight = (x - base_start_x) / overlap_width
            overlap_mask[base_start_y:base_end_y, x] = weight
    
    # 执行图像融合
    blended = warped_sec_img.astype(np.float32)
    blended[base_start_y:base_end_y, base_start_x:base_end_x] = \
        (1 - overlap_mask[base_start_y:base_end_y, base_start_x:base_end_x]) * base_img.astype(np.float32) + \
        overlap_mask[base_start_y:base_end_y, base_start_x:base_end_x] * warped_sec_img[base_start_y:base_end_y, base_start_x:base_end_x]
    return blended.astype(np.uint8)

# 读取图像
image1 = cv.imread('/home/msi-user/PycharmProjects/170Camera/1_camera.jpg')
image2 = cv.imread('/home/msi-user/PycharmProjects/170Camera/2_camera.jpg')

# 检测棋盘格角点
corners1 = get_chessboard_corners(image1)
corners2 = get_chessboard_corners(image2)

# 计算单应性矩阵
H, status = compute_homography_from_chessboard(corners1, corners2)

# 计算新画布尺寸与偏移量
new_size, offset, H_updated = get_new_frame_size(H, image2.shape[:2], image1.shape[:2])

# 变换副图像
warped_image2 = cv.warpPerspective(image2, H_updated, (new_size[1], new_size[0]))

# 融合图像,消除接缝
stitched_image = blend_images(image1, warped_image2, offset[0], offset[1])

# 显示与保存结果
cv.namedWindow("stitched_result", cv.WINDOW_NORMAL)
cv.imshow("stitched_result", stitched_image)
cv.imwrite("optimized_result.jpg", stitched_image)

while True:
    if cv.waitKey(1) == 27:
        break
cv.destroyAllWindows()

四、代码说明

  • 棋盘格角点检测:使用cv.findChessboardCorners结合亚像素优化,获取高精度的对应点对,替代原有的自然特征匹配,大幅提升单应性矩阵精度;
  • 渐变融合:对重叠区域做横向渐变加权,让两张图的过渡更自然,消除接缝;
  • 画布尺寸计算:更精准地计算拼接后的画布大小,避免图像被裁剪或出现黑边。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:15:52