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

OpenCV立体图像生成视差图失败求助:参数调试仍无合格结果

问题描述

我已完成相机校准,使用两台相机拍摄图像并完成校正保存,对应的校正图像如下:
左校正图像
右校正图像

尽管我尽了最大努力,仍无法从这些图像生成合格的深度图,目前得到的最佳效果如下:
生成的深度图

我用于调试参数的代码如下(其中Left_nice和Right_nice为上述校正图像):

import cv2
import numpy as np

cv2.namedWindow('disp', cv2.WINDOW_NORMAL)
cv2.resizeWindow('disp', 800, 1200)

cv2.createTrackbar('numDisparities', 'disp', 1, 50, nothing)
cv2.createTrackbar('blockSize', 'disp', 5, 50, nothing)
cv2.createTrackbar('preFilterType', 'disp', 1, 1, nothing)
cv2.createTrackbar('preFilterSize', 'disp', 2, 25, nothing)
cv2.createTrackbar('preFilterCap', 'disp', 5, 62, nothing)
cv2.createTrackbar('textureThreshold', 'disp', 10, 100, nothing)
cv2.createTrackbar('uniquenessRatio', 'disp', 15, 100, nothing)
cv2.createTrackbar('speckleRange', 'disp', 0, 100, nothing)
cv2.createTrackbar('speckleWindowSize', 'disp', 3, 25, nothing)
cv2.createTrackbar('disp12MaxDiff', 'disp', 0, 100, nothing)
cv2.createTrackbar('minDisparity', 'disp', 0, 25, nothing)

stereo = cv2.StereoBM_create()

Left_nice = cv2.imread('c:/calimages/nice_cam_left_.jpg')
Right_nice = cv2.imread('c:/calimages/nice_cam_right_.jpg')
Left_nice = cv2.cvtColor(Left_nice, cv2.COLOR_BGR2GRAY)
Right_nice = cv2.cvtColor(Right_nice, cv2.COLOR_BGR2GRAY)

while True:
    # Updating the parameters based on the trackbar positions
    numDisparities = cv2.getTrackbarPos('numDisparities', 'disp') * 16
    blockSize = cv2.getTrackbarPos('blockSize', 'disp') * 2 + 5
    preFilterType = cv2.getTrackbarPos('preFilterType', 'disp')
    preFilterSize = cv2.getTrackbarPos('preFilterSize', 'disp') * 2 + 5
    preFilterCap = cv2.getTrackbarPos('preFilterCap', 'disp')
    textureThreshold = cv2.getTrackbarPos('textureThreshold', 'disp')
    uniquenessRatio = cv2.getTrackbarPos('uniquenessRatio', 'disp')
    speckleRange = cv2.getTrackbarPos('speckleRange', 'disp')
    speckleWindowSize = cv2.getTrackbarPos('speckleWindowSize', 'disp') * 2
    disp12MaxDiff = cv2.getTrackbarPos('disp12MaxDiff', 'disp')
    minDisparity = cv2.getTrackbarPos('minDisparity', 'disp')

    # Setting the updated parameters before computing disparity map
    stereo.setNumDisparities(numDisparities)
    stereo.setBlockSize(blockSize)
    stereo.setPreFilterType(preFilterType)
    stereo.setPreFilterSize(preFilterSize)
    stereo.setPreFilterCap(preFilterCap)
    stereo.setTextureThreshold(textureThreshold)
    stereo.setUniquenessRatio(uniquenessRatio)
    stereo.setSpeckleRange(speckleRange)
    stereo.setSpeckleWindowSize(speckleWindowSize)
    stereo.setDisp12MaxDiff(disp12MaxDiff)
    stereo.setMinDisparity(minDisparity)

    # Calculating disparity using the StereoBM algorithm
    disparity = stereo.compute(Left_nice, Right_nice)
    # NOTE: Code returns a 16bit signed single channel image,
    # CV_16S containing a disparity map scaled by 16. Hence it
    # is essential to convert it to CV_32F and scale it down 16 times.

    # Converting to float32
    disparity = disparity.astype(np.float32)

    # Scaling down the disparity values and normalizing them
    disparity = (disparity / 16.0 - minDisparity) / numDisparities

    # Displaying the disparity map
    cv2.imshow("disp", disparity)
    # Close window using esc key
    if cv2.waitKey(1) == 27:
        break

请问我哪里操作出错了?


问题排查与解决建议

1. 缺失回调函数定义

代码中调用cv2.createTrackbar时传入了nothing作为回调函数,但未定义该函数,运行时会直接报错。需补充定义:

def nothing(x):
    pass

2. 视差图显示归一化逻辑错误

当前归一化代码(disparity / 16.0 - minDisparity) / numDisparities会导致数值超出OpenCV显示的有效范围,画面出现异常截断。建议改用cv2.normalize做标准化处理:

# 替换原归一化代码
disparity = disparity / 16.0
disparity = cv2.normalize(disparity, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

处理后视差图会被缩放到0-255的灰度范围,显示效果更直观。

3. StereoBM参数设置不合理

  • numDisparities:初始值设为1对应视差范围仅16,无法覆盖场景内的视差变化,建议初始值调高至3(对应48的视差范围)。
  • blockSize:过小会导致噪声过多,过大则丢失细节,结合你的图像分辨率,建议初始值设为11(对应blockSize=27)。
  • speckleRange和speckleWindowSize:当前初始值太小,无法有效去除斑点噪声,建议分别调至16和100左右。

4. 校正图像有效性存疑

  • 检查行对齐:校正后的左右图像需保证同一物体的像素在同一水平线上,若存在垂直偏移,说明相机校准过程有误,需重新校准。
  • 场景纹理不足:你提供的图像中大面积是单一颜色的墙面、地面,纹理信息匮乏,StereoBM这类块匹配算法在低纹理区域无法准确计算视差,这是深度图质量差的核心原因之一。建议更换纹理丰富的场景测试。

5. 算法选择局限性

StereoBM是基础块匹配算法,对低纹理、光照变化鲁棒性差。建议改用cv2.StereoSGBM_create()替代,SGBM加入半全局匹配逻辑,能显著提升视差图质量,尤其在低纹理区域。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:45:38