资讯专栏INFORMATION COLUMN

GTAV智能驾驶源码详解(一)——制作数据集

lookSomeone / 3088人阅读

摘要:本暂且称之为借鉴了美国死宅的方案,只使用截图捕捉的画面以模拟摄像头数据作为的输入,并没有真实的智能驾驶所涉及的传感器与雷达数据。在游戏中人为驾驶小时,将每一帧图片以及其所对应的操作向量记录在数据集张量中。每帧保存一次数据集设置为暂停键。

项目介绍

场景足够丰富,操作足够简单,有大量的交通工具和驾驶视角可供选择,游戏《Grand Theft Auto 5》是一个相对廉价且适合初级人工智能探索的自动驾驶试验场。

本AI(暂且称之为ScooterV2)借鉴了美国死宅Harrison Kinsley的Charles方案,只使用截图捕捉的画面以模拟摄像头数据作为AI的输入,并没有真实的智能驾驶所涉及的传感器与雷达数据。AI的决策过程目前只停留在CNN(AlexNet)对单张图片进行分类选择操作的阶段,尚未引入记忆,无法处理时间序列数据,因而相比于引入循环神经网络,目前的ScooterV2任然需要大量的数据进行fit训练(目前已完成的ScooterV3采用了强化学习,不需要任何训练数据集,但是由于驾驶场景过于复杂,尚未设计出完美的奖励机制,虽然降低了训练成本但是效果不如目前的V2版本)。

但由于机能限制和存储能力限制(其实是因为不想花太多训练时间,以及经常改方案、丢数据、丢模型),ScooterV2相对于Charles做了一些简化:

Charles的驾驶载体为民用车(GTA5抢劫神车Kuroma装甲轿车),视角为引擎盖视角(为了模拟真实的摄像头),设计目标为保证在当前道路上保持车道行驶的同时尽量避开障碍物(由于Kuroma装甲车速度很快,避开障碍物主要以变道的形式完成),且仿制出了许多真实的智能驾驶模块(前碰撞预警、障碍物探测、行人检测)。

我做的ScooterV2驶载体为摩托车(DoubleT),视角为第三人称视角(为了看到更大的场景区域,为了捕捉到的车道线斜率范围更大,期望以更小的样本量在更少的时间训练出足够好的效果),设计目标为在当前道路上保持车道行驶(使用Mod屏蔽了所有交通和行人),且没有设计其他模块(由于机能限制,串联其它CNN模块会成倍增加单帧处理时间,使得模型的测试效果不美观)。

模型的训练分为三个部分:

数据集制作:监督式学习,数据集分为input data和label,其中输入数据为经过灰度处理、区域屏蔽和大小缩放的图像数据,截取自1280720分辨率的GTA5游戏画面,缩放为16090的大小;标签数据为每一个图像样本对应的1*3规格的操作向量,分别代表向左、向右、前进(Press A/W/D)。在游戏中人为驾驶5小时,将每一帧图片以及其所对应的操作向量记录在数据集张量中。数据集分5批录制完成,对不同操作所对应的图片进行数量平衡(W:A:D = 8:1:1)打乱数据集后取1000张图片作为测试集,其他的为训练集。

训练模型:创建AlexNet初始网络,对保存下来的数据集进行拟合。总共进行了约240000次权值更新,学习耗时3天左右。

测试模型,用getkey函数与keycheck函数定义操作向量与按键联系,用训练好的AlexNet对捕捉到的图片进行分类预测,执行当前类别对应的按键操作以进行驾驶。

制作数据集

导入依赖库:

import numpy as np
import cv2
import time
from grabscreen import grab_screen
from getkeys import key_check
import os

cv2进行图像处理;time用来记录单帧的处理时间;grab_screen从现有的py文件中导入,作用是截取屏幕上的一定区域;key_check用来处理当前帧的操作按键,将其转化为向量。

定义屏蔽函数:

vertices = np.array([[1,60],[1,89],[159,89],[159,60],[80,35],], np.int32)

def roi(img, vertices):
    mask = np.zeros_like(img)   
    cv2.fillPoly(mask, vertices, 255)
    masked = cv2.bitwise_and(img, mask)
    return masked

为了减少图像无用区域对训练过程的影响,需要将图像上方天空区域以及两侧街景进行涂黑屏蔽。
vertices定义了一个区域,roi函数将此区域外的像素用255灰度涂黑。

将操作转化为标签向量:

def keys_to_output(keys):
    output = [0,0,0]
    
    if "A" in keys:
        output[0] = 1
    elif "D" in keys: 
        output[2] = 1
    else:
        output[1] = 1
    return output

若按键A,则标签向量为[1,0,0];
若按键d,则标签向量为[0,0,1];
否则,则标签向量为[0,1,0];

数据集录制:

file_name = "training_data_X.npy"

if os.path.isfile(file_name):
    print("File exists, loading previous data!")
    training_data = list(np.load(file_name))
else:
    print("File does not exist, starting fresh!")
    training_data = []

初始化空数据集,其中"training_data_X.npy"中的X应用数字表示当前录制批次。

def collect():
    
    for i in list(range(10))[::-1]:
        print(i+1)
        time.sleep(1)
        
        
    last_time = time.time()
    
    paused = False
    while True:
        if not paused:
            screenshot =  grab_screen(region=(0,32,1280,752))
            print("Frame took {} seconds".format(time.time()-last_time))
            last_time = time.time()
            screen = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)
            screen = cv2.resize(screen, (160,90))
            screen = roi(screen, [vertices])
            keys = key_check()
            output = keys_to_output(keys)
            training_data.append([screen,output])
            cv2.imshow("window2",screen)

            if cv2.waitKey(25) & 0xFF == ord("q"):
                cv2.destroyAllWindows()
                break

            if len(training_data) % 5000 == 0:
                print(len(training_data))
                np.save(file_name,training_data)
                
        keys = key_check()
        
        if "T" in keys:
            if paused:
                paused = False
                print("unpaused!")
                time.sleep(1)
            else:
                print("Pausing!")
                paused = True
                time.sleep(1)

加入倒计时,在执行程序与开始录制数据集之间留下10秒空余,用以调整姿态与视角。

截取大小为1280*720的游戏区域,并对其进行缩小、灰化和屏蔽操作。

用key_check提取当前操作按键,并用函数转化为标签向量,与处理过的图片一起append到数据集中。

每5000帧保存一次数据集;设置T为暂停键。

平衡数据:

import numpy as np
import pandas as pd
from collections import Counter
from numpy.random import shuffle

train_1 = np.load("training_data_1.npy")
print("done1")
train_2 = np.load("training_data_2.npy")
print("done2")
train_3 = np.load("training_data_3.npy")
print("done3")
train_4 = np.load("training_data_4.npy")
print("done4")
train_5 = np.load("training_data_5.npy")
print("done5")

train = np.concatenate([train_1,train_2,train_3,train_4,train_5])

lefts = []
rights = []
forwards = []

shuffle(train)

for data in train:
    img = data[0]
    choice = data[1]

    if choice == [1,0,0]:
        lefts.append([img,choice])
    elif choice == [0,1,0]:
        forwards.append([img,choice])
    elif choice == [0,0,1]:
        rights.append([img,choice])
    else:
        print("no matches")


forwards = forwards[:8*len(lefts)][:8*len(rights)]
lefts = lefts[:len(forwards)]
rights = rights[:len(forwards)]

final_data = forwards + lefts + rights
shuffle(final_data)

np.save("training_data_after_shuffle.npy", final_data)

将5批数据集合并在一起后进行随机排序,并依据不同的标签划分为3个数组,按一定的比例进行截取后合并再进行随机排序,最后保存为training_data_after_shuffle.npy文件

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/40977.html

相关文章

  • GTAV智能驾驶源码详解(二)——Train the AlexNet

    摘要:智能驾驶源码详解二模型简介本使用进行图像分类前进左转右转。其性能超群,在年图像识别比赛上展露头角,是当时的冠军,由团队开发,领头人物为教父。 GTAV智能驾驶源码详解(二)——Train the AlexNet 模型简介: 本AI(ScooterV2)使用AlexNet进行图像分类(前进、左转、右转)。Alexnet是一个经典的卷积神经网络,有5个卷积层,其后为3个全连接层,最后的输出...

    jayzou 评论0 收藏0
  • GitChat · 人工智能 | 自动驾驶的技术架构和生态发展

    摘要:目前每年全球有万人死于车祸,损失,相关于很多国家的,自动驾驶可以很大效率的减少车祸,拯救生命。美国汽车工程师协会和美国高速公路安全局将自动驾驶技术进行了分级。特定场所的高度自动驾驶。这叫基于规则的一种自动驾驶,简单的。 来自 GitChat 作者:刘盼更多IT技术分享,尽在微信公众号:GitChat技术杂谈 进入 GitChat 阅读原文我们先以汽车在现代科技领域的演进来开始这次的ch...

    X1nFLY 评论0 收藏0
  • 机器学习

    摘要:用离散信一文清晰讲解机器学习中梯度下降算法包括其变式算法无论是要解决现实生活中的难题,还是要创建一款新的软件产品,我们最终的目标都是使其达到最优状态。 提高驾驶技术:用GAN去除(爱情)动作片中的马赛克和衣服 作为一名久经片场的老司机,早就想写一些探讨驾驶技术的文章。这篇就介绍利用生成式对抗网络(GAN)的两个基本驾驶技能: 1) 去除(爱情)动作片中的马赛克 2) 给(爱情)动作片中...

    wums 评论0 收藏0
  • 视频编解码行业及发展方向简述

    摘要:了解华为海思的方案海思的前身是华为的半导体部门,主要产品线包括智能手机处理器麒麟系列,视频采集和编解码处理器系列,无线通信方向芯片等。 目录 一、视频行业1、视频...

    dance 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<