日更 SLAM 一边理论一边实践第一天—先睹为快(python 版本)

244 阅读3分钟

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

最近我被 SLAM 这门技术深深所吸引,从开始好奇到今天的沉迷,已经到了不能自拔的地步。通过一段时间的学习,我放弃了一口吃成胖子的想法,想踏踏实实一步一个脚印地学习 SLAM。SLAM 之所以具有这样魅力,可能正是其涉及到知识的广度和难度吧。可能还有就是 SLAM 现在实实在在许多方面的应用,例如扫地机器人和无人驾驶。

有一天能够靠 SLAM 维持生计固然好,即使不能,作为一门爱好也是不错选择。

以后可能会分享许多枯燥数学方面的知识,为了让自己维持学习的动力,

我一次应该是我记得的第 3 次来尝试自己跟着 george hotz 的分享来做 python 版本的 SLAM,希望会有所突破。清楚记得第一次放弃是因为自己多多视图几何方面基础知识太匮乏,仅是跟着 coding,总是以一头雾水,不知其所以然,为什么这么做。第二次是放弃就是因为对 c++ 方面是完全门外汉,特别是遇到编译错误,根本是无从下手。这一次有备而来,希望能跟着 george hotz 分享走远一点,希望大家多多支持。

george_hotz.jpeg

环境

先简单介绍一个环境,这个环境并不是最终环境,随时在改变

  • sys ubuntu 18.4
  • python 3.6.9

IDE

  • vscode 1.68.1

depencies

  • opencv 3.4.2.16
  • opencv-contrib-python 3.4.2.16
  • pysdl2-0.9.11
  • pysdl2-dll-2.0.20

显示驾驶视频

这里一段采集驾驶视频来做研究对象,这里采用 opencv 来读取视频

import cv2

if __name__ == "__main__":
    cap = cv2.VideoCapture("./videos/test_countryroad.mp4")

    while cap.isOpened():
        ret, frame = cap.read()
        if ret:
            print(frame.shape)
(1080, 1920, 3)
def process_frame(img):
    pass

if __name__ == "__main__":
    cap = cv2.VideoCapture("./videos/test_countryroad.mp4")

    while cap.isOpened():
        ret, frame = cap.read()
        if ret == True:
            print(frame.shape)
            process_frame(frame)
        else:
            break
W = 1920//2
H = 1080//2


def process_frame(img):
    img = cv2.resize(img,(W,H))

sdl2 display

sdl2 是用来开发游戏框架,原为支持 c++ 语言用于开发游戏的库,这里 sdl 来将视频显示在屏幕上

ImportError: could not find any library for SDL2 (PYSDL2_DLL_PATH: unset)

import sdl2
import sdl2.ext
class Display:
    def __init__(self,W,H,window_name) -> None:
        self.W = W
        self.H = H

        sdl2.ext.init()
        self.window = sdl2.ext.Window(window_name,size=(W,H),position=(100,100))
        self.window.show()

    def show(self,img):
        
        events = sdl2.ext.get_events()
        for event in events:
            if event.type == sdl2.SDL_QUIT:
                exit(0)

        self.surf = sdl2.ext.pixels3d(self.window.get_surface())
        self.surf[:,:,0:3] = img.swapaxes(0,1)
        self.window.refresh()

想要把视频每一帧图像绘制到屏幕上,首先会初始化 window 就是在屏幕上创建一个窗口,然后获取窗口 surface 可以理解为画布,然后将 opencv 读取到图像绘制到获取到画布上,这样一来就将视频帧图像绘制到屏幕上。

import cv2
from display import Display

W = 1920//2
H = 1080//2

display = Display(W,H,'slam')

def process_frame(frame):
    img = cv2.resize(frame,(W,H))
    display.show(img)

if __name__ == "__main__":
    cap = cv2.VideoCapture("./videos/test_countryroad.mp4")

    while cap.isOpened():
        ret, frame = cap.read()
        if ret == True:
            print(frame.shape)
            process_frame(frame)
        else:
            break

screen_shot.PNG

手上并没点云这样密集点的数据,有的自由图像。那么自然的想法就是利用图像上特征点,来找两帧之间同一个特征点来进行构建 3 维场景。

import cv2
from display import Display

W = 1920//2
H = 1080//2

display = Display(W,H,'slam')

orb = cv2.ORB_create()

def process_frame(frame):
    img = cv2.resize(frame,(W,H))
    #features extraction ,base on feature
    kp, des = orb.detectAndCompute(img,None)
    for p in kp:
        u,v = map(lambda x:int(round(x)),p.pt)
        print(u,v)
    
    display.show(img)

screen_shot_002.PNG