这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战
有关这部分代码,可能是一年前左右就看过分享一系列关于无人驾驶 python 版本视频。这个视频还是有一定难度,所谓难度是对于我个人来说。当时也是怀着满腔热情准备大干角点法计算附加应力一番 coding 出一个自娱自乐的python下载 self driving。不过那Python时候只是 flowing 不知所云跟着 coding,而且还是遇到安装 python g2o 没有搞定,所以就此放弃了
想利用春节小长假期间,再次挑战一下,这一次也是在积累了一些知识,特别是视觉几何上积累了一些,以及 c++ 方面也有了小小提升,所以回来再次尝试一下,希望这一次有所突破,搞定 python 版本的 slam。
一点点要求,就是需要了解 python,以及 opencv 这个库。具有一定计算机视觉的知识。
基本思想
首先我们将视频读取显示出来便于观察效果,然后提取出每张特征点也就是角点,然后匹配前后帧之间运动appstore方向,和移动的角点法距离以及根据车辆。
显示视频
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)
我们简单观察一下检测结果,如上图计算机视觉的四个核心检测特征点并不是均匀分布,这样检测到的特征点并不是所期望的。看起来一团一团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
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苹果官网,然后利用前后帧视频间匹配角点间移动距离来进行地图的构建。