论文原文地址:GMS: Grid-based Motion Statistics for Fast, Ultra-robust Feature Correspondence
代码地址:github
论文认为:匹配对应该是平滑的,对于true match pair(l1,r1),l1附近的特征点对应的匹配点也应该在r1附近.
① 利用上面的平滑性质,建立统计分析模型(二项分布),过滤ORB matches中的false matches;
② 通过划分栅格来加速真假判断过程,两张图像各划分成m * m块,只需要对各块内及邻块的Feature统计,m建议是20;
③ 对于匹配块(pl1,pr1),对相邻的n * n块,分别进行统计,比如统计pl1的左上块与pr1的左上块的匹配数目,其他类似,以共同验证(pl1,pr1)是否是正确匹配块.这里n建议是3.
④ 论文验证了这个思路的可行性.
下图中,红星表示的是GMS,可以看出,确实很厉害,精度和时间都很好。
下面这张图是GMS整体思路的总结,主要利用了平滑性质。
下图是论文提到的统计概率模型,公式符号较多,建议结合论文阅读。
下图中,最大化P是为了将false match和true match分隔更远,这也验证了论文假设的合理性,有更多的空间去选取合理阈值。
下图描述了加速原理,主要是时间复杂度的改变,确实很厉害,简单有效!
gms_matcher gms(kp1, img1.size(), kp2, img2.size(), matches_all);
,构建gms_matcher对象,在默认构造器中:NormalizePoints(vkp1, size1, mvP1);
归一化点的坐标到(0,1)区间;ConvertMatches(vDMatches, mvMatches);
把opencv的matches转换成vector形式的matches;InitalizeNiehbors(mGridNeighborLeft, mGridSizeLeft);
,mGridNeighborLeft为400 * 9的Mat,400对应20 * 20 块,9对应每一块的邻块的序号.gms.GetInlierMask(vbInliers, false, false);
, 开始做GMS匹配筛选,第一个false表示不做多尺度(代码定义了5中尺度)缩放筛选,第二个false表示不做多旋转方向上(代码定义了8中旋转)的筛选,筛选后的结果保存在vbInliers中.void SetScale(int Scale)
,对不同Scale,缩放图片大小,再InitalizeNiehbors(mGridNeighborLeft, mGridSizeLeft);
,这个函数参照上面2.1中的③.int gms_matcher::run(int RotationType)
,正式进入筛选,参数RotationType为1~8的旋转编号.AssignMatchPairs(int GridType)
,该函数主要是为了统计两个参数—Mat mMotionStatistics
和vector mNumberPointsInPerCellLeft
.mMotionStatistics.at(lgidx, rgidx)
的值表示,在区块lgidx和rgidx中的匹配对的数目;mNumberPointsInPerCellLeft[lgidx]
的值表示区块lgidx和右图所有的匹配对的数目,不一定在rgidx中.VerifyCellPairs(int RotationType)
,核心函数,判断匹配的区块是否是inlier块.