AliceVision代码阅读【4】

main_featureMatching.cpp→aliceVision_featureMatching

  • 【90-253】设置输入参数,并对输入进行configure
  • 【263-267】与之前一样,从之前的cameraInit.sfm读取sfmData
  • 【280-301】读取上一步获取的pair
  • 【304-308】将所有出现在pair里面的id存到filter里面
  • 【313-328】载入之前提取的feature,描述子到regoinPerview
  • 【335-352】看这些pair的位姿是否有定义
  • 【354-361】有位姿情况下的匹配方式
    • match函数
      • 对于每个pair,先获取对应的位姿,相机内参(如果不是pinhole就不行)
      • 【118-119】计算相机投影矩阵乘以位姿
      • 【121】计算基本矩阵https://blog.csdn.net/weixin_45485946/article/details/125493895 https://blog.csdn.net/u011089570/article/details/79040948
      • 【122】获得每个pair共有的描述子类型
      • 【124】allImagePairMatches是一个map,索引是描述子类型,成员是std::vectormatching::IndMatch,matching::IndMatch三个成员,其中两个表示这两个id所表示的描述子是相近的,第三个成员函数表示有多近(可以看后续代码离着这个成员)。每个view都有一个allImagePairMatches,表示这个view,每个描述子类型下,图中每个描述子和其最相似的描述子编号。
      • 【142】左侧相机在右侧相机图像中的位置
      • 【145】guidedMatchingFundamentalFast,参考Rajvi Shah, Vanshika Shrivastava, and P J Narayanan Geometry-aware Feature Matching for Structure from Motion Applications.
        • 其最简单的实现就是对比pair里面每个描述子,可以参考函数guidedMatching
        • 通过极线约束,可以加快上面方法的速度。
        • 【390-392】创立一个buckets,用来存放极线与图像四个边框交点,buckets是个vector,从图像原点开始,顺时针方向增长(可以看函数pix_to_bucket)
        • 【399】算出极线(基本矩阵乘以左图的点,得到应该是直线参数ab
        • c)
        • 【402】找到极线与图像四个边框的交点:line_to_endPoints
          • 【32,49】??判断极线是否在右侧图像上??为什么极线不能平行坐标轴(a=0或者b=0?)
          • 先假设这里可以判断出极线就在右侧图像上
        • ???剩下的看的都不是很懂,比如极线的搜索范围的设定。应该就是找到每个左侧描述子对应的最像的右侧描述子
  • 无位姿情况下的匹配过程
    • (ANN_L2)
      • 【49-54】把pair重新放到一个map里面,原文说目的是Sort pairs according the first index to minimize the MatcherT build operations
      • 【71】创建matcher
        • 构造函数里面有一个createRegionsMatcher,会根据matcherType和特征是scalar还是binary为成员_regionsMatcher创建不同的值
        • 以ANN_L2为例,分配了RegionsMatcher<ArrayMatcher_kdtreeFlann>
        • 里面有个成员ArrayMatcher_kdtreeFlann matcher_,在构造函数时候会调用一个函数Build
      • 【96】根据上面的_regionsMatcher类型,进行match,细节在RegionsMatcher.cpp这个文件里面
        • 这里的match输入的query是另一个region的所有描述子,对每一个描述子都要查找离他最近的NNN_=2的邻居
        • 【140】同上,获得查找的矩阵0行0列的地址
        • 【147】SearchNeighbours,到ArrayMatcher_kdtreeFlann.hpp这个文件
          • 【110】看之前的flann的kdtree初始化了没
          • 【113-119】构建距离和索引矩阵,应为一个regions里面每个描述子个数都要查,所以共有描述子个数行,NNN_列
          • 【126】开始查询
          • 【130-139】将查找结果保存
        • 【158-164】查找的第一个结果和第二个结果距离要差的足够大才可以
        • 【166-175】符合结果的pair保存
      • 【90-115】重复上面的步骤,只不过把左右view切换,看得到结果是否一样
      • 【120-125】保存这个pair,这个描述子类型下,结果相同描述子匹配matches
    • (FAST_CASCADE_HASHING_L2)
      • 不同的nearestMatchingMethod,匹配方法不同,(基类IImageCollectionMatcher),后文以ANN_L2作为例子
      • 先看mapPutativesMatches的类型:PairwiseMatches=std::map<Pair, MatchesPerDescType> = std::map<Pair, std::map<feature::EImageDescriberType, std::vectormatching::IndMatch> 以单个pair做索引,成员是(一个索引是描述子类型,成员是该pair下的所有描述子对)的一个map
      • 【228】调出第一个view下的,对应描述子类型的regions(基类,实际是包含该view下所有特征和描述子的FeatDescRegions类)
      • 【233】typeid:https://www.geeksforgeeks.org/typeid-operator-in-c-with-examples/
      • (剩下的先跳过)
  • 【383-388】检查匹配结果是否是空的
  • 【390-403】如果geometricFilterType是HOMOGRAPHY_GROWING的话,需要对前面得到的匹配的分数(第一近的距离除以第二近的距离,越小越好)进行排序
  • 【462-545】根据不同的geometricFilterType进行filter,下文FUNDAMENTAL_MATRIX为例
    • omp parallel for schedule https://blog.csdn.net/drzhouweiming/article/details/1844762
    • dynamic_cast https://blog.csdn.net/weixin_44212574/article/details/89043854
    • uniform_int_distribution https://blog.csdn.net/Andyooper/article/details/89314678
    • 【471】robustModelEstimation函数,里面的参数GeometricFilterMatrix_F_AC是一个拟函数(Functor)表示使用的方法是Fundamental matrix+ACransac方法
      • 【70】geometricEstimation函数,以GeometricFilterMatrix_F_AC.hpp为例
        • 【100】同之前一样,获得左右图相同类型的描述子
        • 【107】fillMatricesWithUndistortFeaturesMatches函数获得左右图特征点其原始undistort的点,注意这边把所有描述子类型的点全放在一起了
        • 【112】判断是否是鱼眼类型的相机 dynamic_cast https://blog.csdn.net/weixin_44212574/article/details/89043854
        • 【130】geometricEstimation_Mat_ACRANSAC 模板Fundamental7PSolver表示用7点求基本矩阵 Mat3Model表示基本矩阵
          • 【269】RelativePoseKernel
            • 里面FundamentalEpipolarDistanceError的error是Sampson error,参考书Multiple View Geometry in Computer Vision
              • 先看4.1,里面讲了单应性矩阵
              • 再看4.2.1,里面讲了代数误差,就是误差的模
              • 再看4.2.2,讲了几何误差,指的是投影过去的点和匹配点的距离
              • 4.2.3,重投影误差,指的是投影过去+投影过来的误差和
              • 4.2.5,几何误差的几何解释,引入变量V,和4维空间,V在这个四维空间里面就是两个超平面的相交
              • 4.2.6 Sampson error,可以参考https://blog.csdn.net/weixin_39461878/article/details/106457174https://www.zhihu.com/question/38586401
            • 参数UnnormalizerT则表示将匹配点对们进行归一化,参考书的4.4.4
            • 初始化过程:RelativePoseKernel.hpp
              • 【54-55】归一化过程,可以自己对照程序,拿一个1010图片和10010图片做例子来理解这个归一化
              • 【63】_logalpha0,参考ransac里面的误差项前面的归一项
          • 【283】ACRANSAC 原理看https://zhuanlan.zhihu.com/p/483852907 + https://blog.csdn.net/u012348774/article/details/79802957 + 原文1.2 Automatic Homographic Registration of a Pair of Images, with A Contrario Elimination of Outliers http://www.ipol.im/pub/art/2012/mmm-oh/article.pdf
            • 大致原理
              1. 在匹配点中抽取若干个点(比如在这里七点法求F,就取7个点)
              2. 解出模型(F的值)
              3. 算出剩下点的残差(sampson距离),从小到大排列
              4. 根据排列依次加入之前的若干点,求NFA,然后保留最小的NFA对应的点
              5. 重复多次
            • 【168】std::itoa https://cplusplus.com/reference/numeric/iota/
            • 【173】生成 ( n l ) \binom{n}{l} (ln) l = 0 , 1... n l=0,1...n l=0,1...n ( l k ) \binom{l}{k} (kl) l = 0 , 1... n l=0,1...n l=0,1...n
            • 【188-192】随机选择7个点的索引到vec_sample里
            • 【195】根据这7个点,解出F
            • 【202】求Sampson error
            • 【204-213】如果设置了阈值,那就先筛选并判断阈值内点够吗
            • 【225-233】上面讲的ACRANSAC第4步
            • 【235-252】如果找到就复制出inlier
            • 【258】找不到合适的model
            • 【262】对应找了model和循环已经结束的情况
              • 【264-268】找不到,继续找
              • 【272-277】找到了,在找到的模型中选取点再来一次
            • 【289】将F unnormalize,参考上文
            • 返回,得到内点
        • 【160】copyInlierMatches函数,由于【107】把所有描述子类型点放进去了,因此需要根据index对应的类型
        • 【163】计算(在sift例子下)0.14*内点数是否大于7(如果是求F)
        • guidedmatching:之前得到了F,对于一个pair,两个图片下的特征点,利用F,得到一个error(guidedMatching.hpp 【260】),如果小于阈值,计算这两个点之间的距离,和之前一样(第一近的距离除以第二近的距离,越小越好),小于阈值这加入matches
    • 如此,就得到最终的matches了
  • 【556-606】gridFiltering,如果设置了最大特征点数目numMatchesToKeep 则需要选取的特征点足够分散。将图片划分成一个网格,类似于亚像素,然后依次,每个网格提取一个(每个网格可能有多个特征点,这样就可以分散特征点了)
    • 【577】将特征点按特征点的scale从大到小排序
    • 【582】matchesGridFiltering:(默认的是3*3网格,以此为例)
      • 【77-80】算出每一个网格的长宽
      • 【82】左右图各保留3*3的网格空间,因此乘以2
      • 【84-87】假设有90个特征点,则每个网格可以储存5个。因为有左右两图,有9个网格,所以一共存储529=90个
      • 【91-103】根据x y 得到grid的坐标,【99-100】代码应该有错,最大值可以设置gridSize*gridSize-1
      • 【105-112】先把match储存在前面,如果有重复则放后面
      • 【129-139】精华部分,注意里面的循环依次扫描网格,最外层的是每个网格里面匹配点的编号,也就是前面说的:然后依次,每个网格提取一个(每个网格可能有多个特征点,这样就可以分散特征点了)
  • 【609】保存match
    • 主要函数saveTxt,先保存pair的编号,再保存pair有几种类型的描述子,之后是这个类型名称和这个类型下描述子个数,最后就是这些匹配点的编号
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值