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

使用OpenCV中SGBM+WLSFilter生成的视差图深度表示失真求助

视差图生成问题排查求助

我使用OpenCV中的SGBM结合WLSFilter生成视差图,输出结果中物体轮廓清晰,但深度表示严重失真且无规律,看起来像是原图的灰度画。怀疑代码存在问题,希望能得到帮助排查解决。

参数与输出情况

  • 样本图1
  • 真值图
  • BM算法输出1:参数为Block size = 5; NumDisp = 16; Greyscale = true
  • SGBM算法输出1:参数为Block size = 5; NumDisp = 10
  • 样本图2
  • 输出2:参数为Block size = 5; NumDisp = 50

问题代码

void StereoMatching::computeDisparity(cv::Mat &left, cv::Mat &right, cv::Mat &disp) {
  bool gray_scale = false;
  std::string algorithm = "StereoSGBM";
  int blur_kernel = 3;

  int block_size = 5, min_disp = 0, max_disp = 50, max_diff = 0, pre_fc = 0, unique_ratio = 0,
      speckle_size = 50, speckle_range = 10;
                            
  bool use_filter = true;                     
  int p1 = 8 * 3 * block_size * block_size;    
  int p2 = 32 * 3 * block_size * block_size;   

  double wsl_lambda = 6000.0, wsl_sigma = 1.0;

  if (gray_scale) {
    cv::cvtColor(left, left, cv::COLOR_BGR2GRAY);
    cv::cvtColor(right, right, cv::COLOR_BGR2GRAY);
  }

  cv::blur(left, left, cv::Size(blur_kernel, blur_kernel));
  cv::blur(right, right, cv::Size(blur_kernel, blur_kernel));
  cv::Ptr<cv::ximgproc::DisparityWLSFilter> wls_filter_;
  cv::Ptr<cv::StereoMatcher> stereo_matcher_;
  cv::Ptr<cv::StereoMatcher> stereo_matcher_r_;

  if (algorithm == "StereoBM") {
    stereo_matcher_ = cv::StereoBM::create(16, 5);
  }

  else if (algorithm == "StereoSGBM") {
    stereo_matcher_ =
        cv::StereoSGBM::create(min_disp, max_disp, block_size, p1, p2, max_diff, pre_fc,
                               unique_ratio, speckle_size, speckle_range, cv::StereoSGBM::MODE_HH);
  }

  if (use_filter) {
    wls_filter_ = cv::ximgproc::createDisparityWLSFilter(stereo_matcher_);
    stereo_matcher_r_ = cv::ximgproc::createRightMatcher(stereo_matcher_);
    wls_filter_->setLambda(wsl_lambda);
    wls_filter_->setSigmaColor(wsl_sigma);

    cv::Mat dispL, dispR;
    stereo_matcher_->compute(left, right, dispL);
    stereo_matcher_r_->compute(right, left, dispR);
    wls_filter_->filter(dispL, left, disp, dispR);
  }

  else {
    stereo_matcher_->compute(left, right, disp);
  }
}

排查与修复建议

1. 缺失视差图格式转换

OpenCV的SGBM输出的视差图是CV_16S格式(16位有符号整数),视差单位为1/16像素,直接输出会因数值范围异常导致显示失真。必须做归一化转换为8位无符号格式才能正确反映深度:
在函数末尾添加转换代码:

// 将视差图转换为可显示的8位格式
cv::Mat disp_normalized;
disp.convertTo(disp_normalized, CV_8U, 255.0 / (max_disp * 16));
disp = disp_normalized;

2. SGBM参数错误

  • max_disp必须是16的整数倍:当前设置的50不符合要求,会导致算法内部逻辑错误,建议改为48、64或80这类值。
  • 视差搜索范围过小:max_disp - min_disp是实际搜索范围,之前用的10无法覆盖场景深度变化,建议至少设置为64。
  • 关闭关键匹配约束:unique_ratio=0关闭了唯一性检测,容易产生错误匹配;pre_fc=0跳过了预处理滤波,建议将unique_ratio设为5-15,pre_fc设为5或7。

3. 图像预处理优化

  • 直接修改输入的left和right会破坏原始图像,建议克隆临时变量处理:
    cv::Mat left_proc = left.clone();
    cv::Mat right_proc = right.clone();
    // 后续预处理、匹配都使用left_proc和right_proc
    
  • 建议开启灰度转换(gray_scale=true),彩色图匹配稳定性不如灰度图,且会增加计算量。

4. WLSFilter参数调整

wsl_lambda=6000.0过大,会过度平滑视差图导致深度细节丢失,建议调整为800-2000之间;wsl_sigma=1.0可保持,若边缘模糊可降低至0.5。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:35:57