原理+代码详解 | 稠密重建之SGM/tSGM算法

本文详细介绍了计算机视觉中的立体匹配算法,重点讲解了半全局匹配(SGM)和改进版tSGM算法。SGM通过一维路径聚合优化匹配代价,提高效率并保持良好效果。tSGM进一步优化,使用金字塔图像和限制搜索范围来减少计算量。文章包括算法原理、代价计算、代价聚合和代码实现。
摘要由CSDN通过智能技术生成

原文链接

注:本文来自计算机视觉life独家课程 视觉三维重建:原理剖析+逐行代码详解 中的课件及注释代码。

立体匹配算法介绍
  • 全局立体匹配算法

  • 全局立体匹配算法主要是采用了全局的优化理论方法估计视差,建立全局能量函数,通过最小化全局能量函数得到最优视差值;

  • 通过二维相邻像素视差之间的约束(如平滑性约束)而得到更好的匹配效果,但是对内存的占用量大,速度慢不适合实时运行。主要的算法有图割(graph cuts)、信念传播(belief propagation)、动态规划等算法。

  • 局部立体匹配算法

  • 主要是采用局部优化方法进行视差值估计,局部立体匹配算法有 SAD,SSD 等算法,与全局立体匹配算法一样,也是通过能量最小化方法进行视差估计,但是在能量函数中,只有数据项,而没有平滑项;

  • 该算法由于每个像素计算互不干扰可以并行计算,所以可以实时。但由于所基于的局部窗口视差相同的假设在很多情况下并不成立导致匹配效果较差。

  • 半全局立体匹配算法SGM

  • 综合上述局部和全局算法的优缺点,半全局算法依旧采用全局框架,但是在计算能量函数最小化的步骤时使用高效率的一维路径聚合方法来代替全局算法中的二维最小化算法,使用一维最优来近似二维最优,得到的视差图在效果上和全局算法没有太大的差别,但是算法效率却有非常大的提升。

SGM算法
  • 参考文献:

  • [1]Stereo Processing by Semi-global Matching and Mutual Information

  • [2]SURE: Photogrammetric Surface Reconstruction from Imagery

  • SGM算法详细介绍

  • 匹配代价计算

    文献[1]中介绍的SGM的代价计算是基于互信息(Mutual Information,MI)的匹配测度计算算法来计算匹配代价,互信息是一种对影像明暗变化不敏感的相关性测度。但由于原理复杂且计算需要迭代效率比较低,在实际应用中,更简单有效的方法如Census变换,故在此不再介绍MI。

  • Census变换:

  • 使用像素邻域内的局部灰度差异将像素灰度转换为比特串即为census值;

  • 基于Census变换的匹配代价计算方法是计算左右影像对应的两个像素的Census变换值的汉明(Hamming)距离(两个比特串的对应位不相同的数量:先进行异或运算,再统计运算结果中1的个数)

图片

  • 代价聚合

    采用全局立体匹配算法,即找到每个像素的最优视差使得整体能量最小。能量方程如下:

左右滑动可以查看完整公式)

SGM能量方程如下公式:

这是一个二维优化问题,为了提高优化效率,SGM将问题转化为使用一维路径聚合的方式来近似二维最优,提高效率的同时也保证了效果。

左右滑动可以查看完整公式)

式中,为匹配代价,第二项和第三项是平滑项,我们期望的是视差是连续的。所以如果当前像素与邻域像素视差相差比较小(1个像素)我们会给一个比较小的惩罚,如果大于一个像素则给一个大的惩罚。但是实际场景中肯定会有一些视差不连续区域相差比较大(比如:前景和背景)如图示:

图片

为了处理这种情况,我们对 进行调整:

左右滑动可以查看完整公式)

思考:为什么这样调整第二个惩罚项?

答案:如果像素和它的邻域像素亮度差很大,那么该像素很可能是位于视差非连续区域,则一定程度上允许其和邻域像素的视差差值超过1个像素,对于超过1个像素的惩罚力度就适当减小一点。

具体求解过程中,SGM路径代价聚合的思路:

将像素所有视差下的匹配代价进行像素周围所有路径上的一维聚合得到路径下的路径代价值,然后将所有路径代价值相加得到该像素聚合后的匹配代价值。

一维聚合路径示意图(图中各个箭头方向就是聚合各个路径):

图片

某一维路径代价计算公式如下:

左右滑动可以查看完整公式)

式子中

则最终代价值(所有路径之和)

  • 视差计算

代价聚合后, 每个像素直接找聚合代价最小对应的视差值就是我们所要求的视差值。

  • 视差优化

  • 视差一致性检查

    将左右图互换,得到R-L视差图。与L-R视差图对比,根据左图的视差找到在右图中的对应视差,如果两者小于阈值则认为是准确的,反之是错的把该值剔除。如下图:

    图片

  • 亚像素计算

    上述计算的视差图是像素级别的,在实际使用中精度是无法满足需求的。SGM通过在上述计算的最小代价的视差层附近进行插值找到亚像素级的精度。如下图:

图片

tSGM算法
  • 与SGM基本相同,区别主要是在代价聚合的时候:

  • 使用金字塔图像计算视差(由粗糙到精细即从低分辨率到高分辨率计算匹配代价)

  • 每个像素的视差范围都不同,只在真值附近搜索大大减少搜索范围和内存占用,如下图:

    图片

每个像素的视差范围计算方法:

如果当前像素的视差值无效,在搜索窗口=31, 反之=7 以当前像素为中心,窗口大小搜索所有有效视差存储在中,的大小是,中值是,最大值,最小值:

图片

图片

  • 代价聚合时,SGM由于每个像素视差范围都一样,所以各个搜索路径都有对应的视差,tSGM由于每个像素视差范围不一样有的可能都没有重叠范围,所以之前的代价聚合计算方法需要调整,把没有重合的情况考虑进去。

调整如下:

d < d _ m i n ( x _ b − r _ i ) : d<d\_{min}(x\_b-r\_i): d<d_min(x_br_i):< p=""></d_{min}(x_b-r_i):$<>

SGM/tSGM代码实现

代码框架

图片

部分代码实现

左右滑动可以查看完整代码)


//参考文献:SGM:Stereo Processing by Semiglobal Matching and Mutual Information
//        tSGM:SURE: Photogrammetric surface reconstruction from imagery
// SGM 算法主要实现两种经典SGM和tSGM,主要区别是代价聚合的视差搜索范围不同,故聚合代价有区别。经典SGM使用的全局视差范围,每个
// 像素的视差范围都是相同。tSGM 视差搜素范围每个像素的范围都不一样。这样可以大大减少代价聚合的计算量。
void SemiGlobalMatcher::Match(const Scene& scene, IIndex idxImage, IIndex numNeighbors, unsigned minResolution)
{
   
 const Image& leftImage = scene.images[idxImage];
 const float fMinScore(MAXF(leftImage.neighbors.front().score*     (OPTDENSE::fViewMinScoreRatio*0.1f), OPTDENSE::fViewMinScore));
 FOREACH(idxNeighbor, leftImage.neighbors) {
   
  const ViewScore& neighbor = leftImage.neighbors[idxNeighbor];
  // exclude neighbors that over the limit or too small score
  // 分数较小的邻域帧不参与计算
  ASSERT(scene.images[neighbor.idx.ID].IsValid());
  if ((numNeighbors && idxNeighbor >= numNeighbors) ||
   (neighbor.score < fMinScore))
   break;
  // check if the disparity-map was already estimated for the same image pairs
  // 判断是否已经进行视差图计算,如果已经计算则不再计算
  const Image& rightImage = scene.images[neighbor.idx.ID];
  const String pairName(MAKE_PATH(String::FormatString("%04u_%04u", leftImage.ID, rightImage.ID)));
  if (File::isPresent((pairName+".dimap").c_str()) || File::isPresent(MAKE_PATH(String::FormatString("%04u_%04u.dimap", rightImage.ID, leftImage.ID))))
   continue;
  TD_TIMER_STARTD();
  IndexArr points;
  Matrix3x3 H; Matrix4x4 Q
  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值