使用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
相关产品推荐
相关产品推荐

