双目立体匹配算法:Patch Match Stereo详解

本文详细介绍了Patch Match在双目立体匹配中的应用,通过随机采样和匹配传递,寻找最佳的3D视差平面。算法能处理亚像素视差和倾斜表面,但对噪声和弱纹理场景鲁棒性不足。此外,讨论了算法的局限性和GPU并行处理的优化方法。
摘要由CSDN通过智能技术生成

        PatchMatch主要用于在两幅二维图像中搜索最近领域中相似度最高的patch。其主要基于随机采样(random sampling)思想,并根据图像区域相似性,提供一种在整个图像区域快速propagate以提高搜索与匹配效率的机制(算法原理如下图)。目前主要应用于图像编辑工具,也扩展到诸如双目匹配、AR等多个研究领域。

        最小化匹配代价来为每一个像素找到一个最优的3D视差平面。这个问题可以通过patch match来解决:首先对所有像素的视差平面进行随机初始化或根据某些先验信息进行初始化,然后基于迭代传播(空间传播、视图传播、帧间传播、平面细化)不断地更新所有像素的平面参数。patch match的优点是只要至少有一个像素的初始化视差平面位于或接近最优平面,就可以找到剩余所有像素的最优平面。

step1.映射关系初始化

将S划分为M个patch,随机定义一个矩阵,这个矩阵中的每个向量代表着S中的patch与T中对应patch的映射关系,当然由于是随机初始化,这个映射关系是相当不准确的,但总会有或者说至少有一个是较好匹配的;如下图所示,A 中的蓝patch随机映射到B中的蓝色patch,其周围的红色框和绿色框分别对应B图中的红框和绿框

以下是双目立体匹配算法SGM的实时代码: ``` #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; const int max_image_size = 960; const int max_disparity = 64; const int P1 = 5; const int P2 = 70; const int penalty_scale = 10; const int uniqueness_ratio = 15; const int speckle_window_size = 100; const int speckle_range = 32; int main(int argc, char** argv) { if(argc != 3) { cout << "Usage: ./sgm_stereo left_image right_image" << endl; return -1; } Mat imgL = imread(argv[1], IMREAD_GRAYSCALE); Mat imgR = imread(argv[2], IMREAD_GRAYSCALE); if(imgL.empty() || imgR.empty()) { cout << "Error: Could not open or find the images" << endl; return -1; } int width = imgL.cols; int height = imgL.rows; if(width > max_image_size || height > max_image_size) { cout << "Error: Image size too large" << endl; return -1; } int min_disparity = 0; int max_disparity = 64; Mat disparity_map = Mat::zeros(height, width, CV_8UC1); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { int min_cost = INT_MAX; int best_disparity = min_disparity; for(int d = min_disparity; d < max_disparity; d++) { int sum = 0; int count = 0; for(int dy = -1; dy <= 1; dy++) { for(int dx = -1; dx <= 1; dx++) { int xl = x + dx; int xr = x + dx - d; if(xl < 0 || xl >= width || xr < 0 || xr >= width) { continue; } int diff = abs((int)imgL.at<uchar>(y+dy, x+dx) - (int)imgR.at<uchar>(y+dy, xr)); sum += diff; count++; } } int cost = sum / count; if(d > min_disparity) { int diff = abs(d - best_disparity); cost += (diff == 1) ? P1 : (P1 + (diff - 1) * P2); } if(cost < min_cost) { min_cost = cost; best_disparity = d; } } disparity_map.at<uchar>(y, x) = best_disparity; } } Ptr<StereoSGBM> stereo = StereoSGBM::create(min_disparity, max_disparity, penalty_scale, 8 * imgL.channels() * speckle_window_size * speckle_window_size, 32 * speckle_range, uniqueness_ratio, StereoSGBM::MODE_SGBM_3WAY); stereo->compute(imgL, imgR, disparity_map); namedWindow("Disparity Map", WINDOW_NORMAL); imshow("Disparity Map", disparity_map); waitKey(0); return 0; } ``` 需要注意的是,此代码只是SGM算法的实现之一,针对不同的场景和需求,实现方式可能会有所不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋水 墨色

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值