日更 SLAM 一边理论一边实践第三天—提取特征(3)

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

前言

自己作为 SLAM 技术的门外汉,许多知识点还是停留在表面,在分享中可能会有一些偏差,希望大家多多指正,我会尽自己最大努力来保证文章内容正确性。

术语

  • 视觉里程计:根据图像定量估算帧间相机的运动

提取特征点

引入依赖,对于计算机视觉当然少不了 numpy 和 opencv

import numpy as np
import cv2
np.set_printoptions(suppress=True)
复制代码

接下来要做就是在图像提取特征点,通常提取到特征点是具有一些良好性质、例如平移不变性、光照不变性和旋转不变性。基于具有良好性质特征点在在相邻 frame 间进行匹配。

orb = cv2.ORB_create()
kp = orb.detect(img,None)
kp, des = orb.compute(img,kp)
img = cv2.drawKeypoints(img,kp,None,color=(0,255,0),flags=0)
复制代码

在 SLAM 提取什么样特征点算是好的特征点,首先特征点最好是均匀分布,我们希望通过特征点来表达一个局部区域,如果特征点过于集中,不利于通过特征点来表达图。

通过 ORB_create 创建一个 ORB 实例 orb,然后使用 detectAndCompute 来进行提取特征点

kp,des = orb.detectAndCompute(img,None)

for p in kp:
    u,v = map(lambda x:int(round(x)),p.pt)
    cv2.circle(img,(u,v),3,(0,255,0))

复制代码

使用 orb 提取特征点并不是我们想要的那样均匀分布的特征点,也就是不利于下一步处理,所以去尝试其他方法。接下来尝试用 goodFeaturesToTrack 提取特征点

class FeatureExtractor(object):

    def __init__(self) -> None:

        self.orb = cv2.ORB_create()

    def extract(self,img):

        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        feats = cv2.goodFeaturesToTrack(gray,3000,qualityLevel=0.01,minDistance=3)

        return feats
复制代码
feats = extractor.extract(img)

for f in feats:

    u,v = map(lambda x: int(round(x)),f[0])

    cv2.circle(img,(u,v),3,(0,255,0))

复制代码

接下要做的是计算两 frame 图像之间相同的特征点,我们先来查看一个 goodFeaturesToTrack 返回数据格式。

[
[[411. 247.]]
[[800. 313.]]
]
复制代码

对于 goodFeaturesToTrack 是用于检测角点,是不同于 orb 算法,所以我们需要将 goodFeaturesToTrack 返回出数据进行适当的调整,也就是符合 orb 格式才能进行下一步的工作,也就是通过计算关键点的描述子来计算特征点的匹配。

将 goodFeaturesToTrack 返回结果转换为 KeyPoint


def extract(self,img):
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    feats = cv2.goodFeaturesToTrack(gray,3000,qualityLevel=0.01,minDistance=3)

    kps = [cv2.KeyPoint(x=f[0][0],y=f[0][1],_size=20) for f in feats]
return kps
复制代码

然后我们将 goodFeaturesToTrack 的特征角点转换为 KeyPoint 格式,再去用 orb.compute 来计算角点特征点描述子,描述子 des 也就是描述角点的信息,通过对比这些信息来找到 2 frame 之间相似点。

des = self.orb.compute(img,kps)
复制代码

根据角点的描述符信息进行匹配,这里使用 BFMatcher,关于 BFMatcher 是如何匹配,Brute-Force 匹配器很简单。就是从当前帧中一个特征点的描述子,然后选择一种计算距离方式,来计算上一帧中的所有特征点进行匹配。返回最按距离计算得到的一个特征点。

self.bf = cv2.BFMatcher()
复制代码

matches = self.bf.match(des,self.last['des'])

复制代码

猜你喜欢

转载自juejin.im/post/7125774097992302606