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

相机校准异常与立体视差图计算故障技术求助

问题描述

我正在开发一个基于立体视觉的项目,目标是计算人与物体到相机的深度和距离。硬件采用Jetson Nano开发套件搭配Waveshare IMX219-83双目相机,软件基于OpenCV实现。

运行视差计算代码时遇到以下问题:

  • 已使用标定好的XML参数文件,但校正后的图像向右倾斜
  • 视差图存在大量噪点,近处物体无法识别,整体呈现模糊状态
  • 所有640x480分辨率的测试图像均出现该问题
相关代码

视差计算代码

from __future__ import print_function
import numpy as np
import cv2


def main():
    cv_file = cv2.FileStorage()
    cv_file.open('stereoMap.xml', cv2.FILE_STORAGE_READ)
    stereoMapL_x = cv_file.getNode('stereoMapL_x').mat()
    stereoMapL_y = cv_file.getNode('stereoMapL_y').mat()
    stereoMapR_x = cv_file.getNode('stereoMapR_x').mat()
    stereoMapR_y = cv_file.getNode('stereoMapR_y').mat()
    
    imgL = cv2.imread("EpipolarGeometryAndStereoVision/left-images/left/fotoeditada.jpg", 0)
    imgL = cv2.resize(imgL, (640, 480))
    imgL = cv2.remap(imgL, stereoMapL_x, stereoMapL_y, 0, 0, 0)

    imgR = cv2.imread("EpipolarGeometryAndStereoVision/right-images/right/fotoeditadaright.jpg", 0)
    # imgR = cv2.resize(imgR, (640, 480))
    imgR = cv2.remap(imgR, stereoMapR_x, stereoMapR_y,  0, 0, 0)

    # StereoSGBM算法参数设置
    minDisparity = 1
    numDisparities = 60 - minDisparity
    blockSize = 5
    uniquenessRatio = 1
    speckleWindowSize = 3
    speckleRange = 3
    disp12MaxDiff = 100
    P1 = 8 * 3 * blockSize ** 2
    P2 = 32 * 3 * blockSize ** 2

    stereo = cv2.StereoSGBM_create(
        minDisparity=minDisparity,
        numDisparities=numDisparities,
        blockSize=blockSize,
        uniquenessRatio=uniquenessRatio,
        speckleWindowSize=speckleWindowSize,
        speckleRange=speckleRange,
        disp12MaxDiff=disp12MaxDiff,
        P1=P1,
        P2=P2
    )

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

    cv2.imshow('leftview',imgL)
    cv2.imshow('rightview', imgR)
    cv2.imshow('disparity', (disparity - minDisparity) / numDisparities)
    cv2.waitKey()


if __name__ == '__main__':
    main()
    cv2.destroyAllWindows()

立体相机标定代码

import numpy as np
import cv2 as cv
import glob

##### 查找棋盘格角点 - 物体点与图像点
chessboardSize = (8,6)
frameSize = (480, 640)

# 终止准则
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 准备物体点(棋盘格方块尺寸24mm)
objp = np.zeros((chessboardSize[0] * chessboardSize[1], 3), np.float32)
objp[:,:2] = np.mgrid[0:chessboardSize[0],0:chessboardSize[1]].T.reshape(-1,2)
objp = objp * 24
print(objp)

# 存储所有图像的物体点和图像点
objpoints = []  # 真实世界中的3D点
imgpointsL = []  # 左图的2D图像点
imgpointsR = []  # 右图的2D图像点

imagesLeft = glob.glob('calibration/camera1/*.jpg')
imagesRight = glob.glob('calibration/camera0/*.jpg')

for imgLeft, imgRight in zip(imagesLeft, imagesRight):
    imgL = cv.imread(imgLeft)
    imgR = cv.imread(imgRight)
    grayL = cv.cvtColor(imgL, cv.COLOR_BGR2GRAY)
    grayR = cv.cvtColor(imgR, cv.COLOR_BGR2GRAY)

    # 查找棋盘格角点
    retL, cornersL = cv.findChessboardCorners(grayL, chessboardSize, None)
    retR, cornersR = cv.findChessboardCorners(grayR, chessboardSize, None)

    # 若左右图均找到角点,添加物体点和优化后的图像点
    if retL and retR:
        objpoints.append(objp)

        cornersL = cv.cornerSubPix(grayL, cornersL, (11,11), (-1,-1), criteria)
        imgpointsL.append(cornersL)

        cornersR = cv.cornerSubPix(grayR, cornersR, (11,11), (-1,-1), criteria)
        imgpointsR.append(cornersR)

        # 绘制并显示角点
        cv.drawChessboardCorners(grayL, chessboardSize, cornersL, retL)
        cv.imshow('img left', grayL)
        cv.drawChessboardCorners(grayR, chessboardSize, cornersR, retR)
        cv.imshow('img right', grayR)
        cv.waitKey(1000)

cv.destroyAllWindows()

####################### 单目标定
retL, cameraMatrixL, distL, rvecsL, tvecsL = cv.calibrateCamera(objpoints, imgpointsL, frameSize, None, None)
heightL, widthL, channelsL = imgL.shape
newCameraMatrixL, roi_L = cv.getOptimalNewCameraMatrix(cameraMatrixL, distL, (widthL, heightL), 1, (widthL, heightL))

retR, cameraMatrixR, distR, rvecsR, tvecsR = cv.calibrateCamera(objpoints, imgpointsR, frameSize, None, None)
heightR, widthR, channelsR = imgR.shape
newCameraMatrixR, roi_R = cv.getOptimalNewCameraMatrix(cameraMatrixR, distR, (widthR, heightR), 1, (widthR, heightR))

############ 立体标定 #######
flags = 0
flags |= cv.CALIB_FIX_INTRINSIC

# 固定内参,仅计算旋转、平移、本质矩阵和基础矩阵
criteria_stereo = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 计算两相机间的变换关系及本质/基础矩阵
retStereo, newCameraMatrixL, distL, newCameraMatrixR, distR, rot, trans, essentialMatrix, fundamentalMatrix = cv.stereoCalibrate(objpoints, imgpointsL, imgpointsR, newCameraMatrixL, distL, newCameraMatrixR, distR, grayL.shape[::-1], criteria_stereo, flags)

########## 立体校正 #################################################
rectifyScale= 1
rectL, rectR, projMatrixL, projMatrixR, Q, roi_L, roi_R = cv.stereoRectify(newCameraMatrixL, distL, newCameraMatrixR, distR, grayL.shape[::-1], rot, trans, rectifyScale,(0,0))

stereoMapL = cv.initUndistortRectifyMap(newCameraMatrixL, distL, rectL, projMatrixL, grayL.shape[::-1], cv.CV_16SC2)
stereoMapR = cv.initUndistortRectifyMap(newCameraMatrixR, distR, rectR, projMatrixR, grayR.shape[::-1], cv.CV_16SC2)

print("Saving parameters!")
cv_file = cv.FileStorage('stereoMap.xml', cv.FILE_STORAGE_WRITE)

cv_file.write('stereoMapL_x',stereoMapL[0])
cv_file.write('stereoMapL_y',stereoMapL[1])
cv_file.write('stereoMapR_x',stereoMapR[0])
cv_file.write('stereoMapR_y',stereoMapR[1])

cv_file.release()
问题排查与解决方案

图像倾斜问题

  1. 帧尺寸匹配修正:标定代码中frameSize = (480, 640)格式错误,OpenCV要求frameSize为**(宽, 高)**,需改为(640, 480),重新标定生成参数文件。
  2. 左右图像尺寸统一:视差计算代码中仅对左图做了resize,右图注释掉了该操作,若左右图原始尺寸不一致会导致校正错位,需确保左右图在校正前均resize为640x480。

视差图噪点与模糊问题

  1. StereoSGBM参数优化:
    • numDisparities:必须是16的整数倍,当前60-1=59不符合要求,建议改为64 - minDisparity(如minDisparity设为0时用64);
    • blockSize:从5增大到7或9,提升低纹理区域的匹配稳定性;
    • uniquenessRatio:从1提高到5-15,过滤模糊匹配结果;
    • speckleWindowSize和speckleRange:分别调整为50和2,减少小面积噪点;
    • disp12MaxDiff:从100降至10-20,限制左右视差的最大差值。
  2. 图像预处理:在校正后添加高斯模糊(cv2.GaussianBlur(imgL, (3,3), 0))或直方图均衡化(cv2.equalizeHist(imgL)),提升图像对比度,降低噪点干扰。
  3. 标定精度提升:采集至少20组不同角度、距离的棋盘格图像,确保角点识别准确,重新标定以获取更可靠的内参和外参。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 13:37:04