likes
comments
collection
share

日更 SLAM 一边理论一边实践第 4 天—过滤特征(4)

作者站长头像
站长
· 阅读数 5

前言

将相邻 2 帧图像上特征点提取并进行匹配,接下来就是匹配特征点过滤掉那些误匹配特征点。尝试用两种方法来消除误匹配的关键点。

将会了解哪些内容

  • BFMatcher 关键匹配器使用方法
  • 误匹配的原因
  • 过滤掉误匹配的方法,交叉验证和 Ratio test

特征点匹配


matches = None

if self.last is not None:
    matches = self.bf.match(des,self.last['des'])
    matches = zip([kps[m.queryIdx] for m in matches],[self.last['kps'][m.trainIdx] for m in matches])

    # update last
    self.last = {'kps':kps,'des':des}
    # return kps,des,matches

return matches

Brute Force Matcher

其实我们只关心那些匹配上点,对于没有匹配的关键点我们其实并不关心。现在我们来简单看一下 BFMatcher 的 API 其返回值的格式如何,返回数据结构为 DMatch 列表的数据结构

  • distance: 表示描述符(descriptors) 之间距离,距离小表示两个值越接近
  • trianIdx: 表示在训练集(对应于代码中 des )描述符(descriptors)的索引
  • qureyIdx: 表示搜索数据(对应于 self.last['des']
  • imgIdx: 训练图像索引

trianIdx 和 queryIdx 分别是 2 组关键点的索引,queryIdx 索引到第一组关键点,而 trainidx 索引到第二组关键点

绘制特征点

通过 opencv 提供 circle 来绘制特征点,然后用 line 连接前后帧的匹配关键点

for pt1,pt2 in matches:

# print(pt1)

    u1,v1 = map(lambda x:int(round(x)),pt1.pt)

    u2,v2 = map(lambda x:int(round(x)),pt2.pt)

    cv2.circle(img,(u1,v1),3,(0,255,0))

    cv2.line(img,(u1,v1),(u2,v2),color=(255,0,0))

日更 SLAM 一边理论一边实践第 4 天—过滤特征(4)

从上图来看存在许多误匹配点

误匹配的原因

  • FP 将非匹配特征点检测为匹配,对于这样误判为匹配特征点,是可以通过优化将其提出
  • FN 为检测出的特征点,对于这种类型是因为 Match 算法没有检测出来,所以无法优化

优化误匹配

匹配距离衡量方法换成 cv2.NORM_HAMMING ,然后BFMatchercrossCheck=True ,也就是开启交叉验证。匹配条件就会更加严格,只有到 A 关键点集合中的第 i 个特征点与 B 关键点集合中的第 j 个特征点距离最近,并且 B 关键点集合中的第 j 个特征点到 A 关键点集合中的第 i 个特征点也是最近时才会返回最佳匹配(i,j),这就是所谓交叉验证

self.bf = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=True)

简单总结一下

  • goodFeaturesToTrack 提取特征点
  • 用这些提取特征点(ORB)来计算 descriptor 关键点的描述符
  • 用 BFMatcher 来基于关键点的描述符来对邻近两 frame 匹配关键点

简单调整了 BFMatcher ,采用对匹配点按距离进行过滤,只有满足条件

self.bf = cv2.BFMatcher(cv2.NORM_HAMMING)

ret = []

if self.last is not None:
    matches = self.bf.knnMatch(des,self.last['des'],k=2)

    for m,n in matches:
        if m.distance < 0.75*n.distance:
            ret.append((kps[m.queryIdx],self.last['kps'][m.trainIdx]))

# update last
self.last = {'kps':kps,'des':des}
# return kps,des,matches
return ret
  • knnMatch 方法中 k=2 表示每个 match 得到两个最接近的描述子(descriptor),然后计算最接近距离和次接近距离的比值,当比值大于既定值,才作为最终 match 的一对关键点

日更 SLAM 一边理论一边实践第 4 天—过滤特征(4)

日更 SLAM 一边理论一边实践第 4 天—过滤特征(4)

随后为了提升匹配的精度,可以采用随机样本一致性(RANSAC)方法,这个将在下一次分享展开来介绍。