这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战

有关这部分代码,可能是一年前左右就看过分享一系列关于无人驾驶 python 版本视频。这个视频还是有一定难度,所谓难度是对于我个人来说。当时也是怀着满腔热情准备大干角点法计算附加应力一番 coding 出一个自娱自乐的python下载 self driving。不过那Python时候只是 flowing 不知所云跟着 coding,而且还是遇到安装 python g2o 没有搞定,所以就此放弃了

想利用春节小长假期间,再次挑战一下,这一次也是在积累了一些知识,特别是视觉几何上积累了一些,以及 c++ 方面也有了小小提升,所以回来再次尝试一下,希望这一次有所突破,搞定 python 版本的 slam。

一点点要求,就是需要了解 python,以及 opencv 这个库。具有一定计算机视觉的知识。

基本思想

首先我们将视频读取显示出来便于观察效果,然后提取出每张特征点也就是角点,然后匹配前后帧之间运动appstore方向,和移动的角点法距离以及根据车辆。

显示视频

从头手写无人驾驶(1)

import time
from turtle import position
import cv2
import sdl2
import sdl2.ext
sdl2.ext.init()
W = 1920//2
H = 1080//2
window = sdl2.ext.Window('SLAM', size=(W,H),position=(-500,-500))
window.show()
def process_frame(img):
    img = cv2.resize(img,(W,H))
    events = sdl2.ext.get_events()
    for event in events:
        if event.type == sdl2.SDL_QUIT:
            exit(0)
    # print(dir(window))
    surf = sdl2.ext.pixels2d(window.get_surface())
    surf[:] = img.swapaxes(0,1)[:,:,0]
    window.refresh()
if __name__ == "__main__":
    # get video stream
    cap = cv2.VideoCapture("test.mp4")
    # 
    while cap.isOpened():
        # read frame of video
        ret, frame = cap.read()
        if ret == True:
            process_frame(frame)
        else:
            break

读取视频的图像,然后对图像进行缩放到原有计算机视觉是什么图像 2 倍,appstore然后是 sdl2 将视频显示出来。

window = sdl2.ext.Window('SLAM', size=(W,H),position=(-500,-500))

sdl2 定义一个窗口,第 1 个参数窗口名,第 2 参数窗口的大小,第 3 参数定python怎么读义窗口的左上角位置。

img.swapaxes(0,1)[:,:,0]

交换 0 和 1 轴位置,也python基础教程就是需要将宽度和高度位置。这是因为 sdl2 显示和 cv2 读取到图像不匹配的问题。

提取特征点


orb = cv2.ORB_create()
def process_frame(img):
    img = cv2.resize(img,(W,H))
    kp, des = orb.detectAndCompute(img,None)
    for p in kp:
        x,y = map(lambda x:round(x), p.pt)
        cv2.circle(img,(x,y),color=(0,255,0),radius=3)
    display.paint(img)

从头手写无人驾驶(1)

我们简单观察一下检测结果,如上图计算机视觉的四个核心检测特征点并不是均匀分布,这样检测到的特征点并不是所期望的。看起来一团一团APP。也就是 opencv 提供 ORB 特征点提取的效果并不令人满意。

class FeatureExtractor(object):
    GX = 16//2
    GY = 12//2
    def __init__(self) -> None:
        self.orb = cv2.ORB_create()
    def extract(self,img):
        sy = img.shape[0] // self.GX
        sx = img.shape[1] // self.GY
        akp = []
        for ry in range(0, img.shape[0],sy):
            for rx in range(0, img.shape[1], sx):
                img_chunk = img[ry:ry + sy, rx:rx + sx]
                kp = self.orb.detect(img_chunk,None)
                for p in kp:
                    p.pt = (p.pt[0]  + rx, p.pt[1] + ry)
                    akp.append(p)
        return akp

这部分代码因为检测效果不理想,没有最终被保留,既然没有用到,但是还是想拿出来分享一下,原因是通过代码我们了解如何对图像进行分块进行处理的方式。

class FeatureExtractor(object):
    def __init__(self) -> None:
        self.orb = cv2.ORB_create()
    def extract(self,img):
        feats = cv2.goodFeaturesToTrack(np.mean(img,axis=2).astype(np.uint8),
            3000, qualityLevel=0.01, minDistance=3)
        print(feats)
        return feats

从头手写无人驾驶(1)

class FeatureExtractor(object):
    def __init__(self) -> None:
        self.orb = cv2.ORB_create()
    def extract(self,img):
        feats = cv2.goodFeaturesToTrack(np.mean(img,axis=2).astype(np.uint8),
            3000, qualityLevel=0.01, minDistance=3)
        kps = [cv2.KeyPoint(x=f[0][0], y=f[0][1],_size=20) for f in feats]
        des = self.orb.compute(img, kps)
        return kps,des

opencv 提供 go运动世界校园odFeaturesToTrack 方法,通过 Shi-Tomasi方法(可以通过指定来选用 Harris Corner Detection,角点检测)找到图像中最优的角点。首先接收灰度图,这里 np.mean(img,axis=2).astype(np.uint8) 方法来获取一张灰度图像,3000 表示最大检测角点的数量,qualityLevel 取值范围是 0 到 1 ,小于指定质量等级的角点将被舍弃。指定检测到的角点之间的最小得距离。

然后我们就要计算这角点描述值,这些点的描述值用于随后进行角点间匹配,基本思想是我们找到角点apple苹果官网,然后利用前后帧视频间匹配角点间移动距离来进行地图的构建。