端到端自动驾驶——cnn网络搭建
论文参考:https://arxiv.org/abs/1604.07316
demo
今天主要来看一个如何通过图像直接到控制的自动驾驶端到端的项目,首先需要配置好我的仿真环境,下载软件udacity:
https://d17h27t6h515a5.cloudfront.net/topher/2016/November/5831f3a4_simulator-windows-64/simulator-windows-64.zip
现在好的解压即可
运行时打开终端,然后将文件拖入终端中运行
选择合适的窗口大小
成功进入界面
然后配置一下python环境,对于已经有conda环境后,直接
conda create -n cnn python=3.8
conda activate cnn
安装以下依赖:
astor==0.8.1
bidict==0.21.2
certifi==2021.5.30
charset-normalizer==2.0.4
click==8.0.1
colorama==0.4.4
cycler==0.10.0
decorator==5.0.9
dnspython==1.16.0
eventlet==0.31.1
Flask==2.0.1
gast==0.3.3
greenlet==1.1.0
idna==3.2
itsdangerous==2.0.1
Jinja2==3.0.1
joblib==1.0.1
kiwisolver==1.3.1
MarkupSafe==2.0.1
matplotlib==3.4.2
numpy==1.19.3
opencv-python==4.5.3.56
paddlepaddle==2.1.2
pandas==1.3.1
Pillow==8.3.1
protobuf==3.17.3
pyparsing==2.4.7
python-dateutil==2.8.2
python-engineio==3.13.0
python-socketio==4.6.1
pytz==2021.1
requests==2.26.0
scikit-learn==0.24.2
scipy==1.7.1
six==1.16.0
threadpoolctl==2.2.0
urllib3==1.26.6
Werkzeug==2.0.1
代码
git clone https://github.com/chan-yuu/end_to_end_ws.git
数据集可以自己驾驶udacity的车辆收集,也可以直接下载下来训练师需要指定文件夹的路径,这里我使用的是一个csv文件来指定我的文件夹
主要文件放置的结构要写入csv文件中,分别是左中右的摄像头图片路径,方向盘,油门,刹车,速度信息。
打开仿真环境,进入training模式
通过键盘即可控制车辆运行。
可以点击record记录这个过程中的数据,之后就能自动生成需要的数据集内容
python train.py -d xxx.csv
我仔细研读了一下这个代码
import paddle
import argparse
import numpy as np
import paddle.nn as nnfrom paddle.optimizer import Adam
from paddle.callbacks import ModelCheckpoint, EarlyStoppingfrom car.model import build_model
from car.utils import CarDataset, load_data# 设置随机种子,确保结果可复现
np.random.seed(0)def train_model(model, args, X_train, X_valid, y_train, y_valid):"""Train the model"""# 创建一个模型检查点回调,用于在训练过程中保存模型checkpoint = ModelCheckpoint(save_dir=args.save_dir)# 创建一个早停回调,当监控的指标(这里是损失值)在一定轮数(patience)内没有改善时,停止训练earlystopping = EarlyStopping(monitor='loss',mode='min', # 监控损失值,希望其越小越好patience=10, # 允许损失值在 10 个 epoch 内没有改善verbose=1, # 打印早停信息min_delta=0, # 损失值的最小改善量baseline=None, # 基线值,这里不使用save_best_model=True) # 保存最佳模型# 根据命令行参数决定是否使用早停回调if args.early_stop:cbs = [checkpoint, earlystopping]else:cbs = [checkpoint]# 创建 Adam 优化器,用于更新模型的参数opt = Adam(learning_rate=args.learning_rate, parameters=model.parameters())# 将模型包装为 paddle.Model 对象,方便进行训练和评估model = paddle.Model(model)# 配置模型的损失函数和优化器model.prepare(loss=nn.MSELoss(), optimizer=opt)# 创建训练数据集对象train_dataset = CarDataset(args.data_dir, X_train, y_train, True)# 创建验证数据集对象val_dataset = CarDataset(args.data_dir, X_valid, y_valid, False)# 开始训练模型model.fit(train_data=train_dataset, # 训练数据集eval_data=val_dataset, # 验证数据集epochs=args.nb_epoch, # 训练的轮数batch_size=args.batch_size, # 每个批次的样本数量save_dir=args.save_dir, # 模型保存的目录callbacks=cbs, # 回调函数列表verbose=1) # 打印训练进度信息def s2b(s):"""Converts a string to boolean value"""# 将字符串转换为小写s = s.lower()# 判断字符串是否表示真return s == 'true' or s == 'yes' or s == 'y' or s == '1'def main():"""Load train/validation data set and train the model"""# 创建命令行参数解析器parser = argparse.ArgumentParser(description='Behavioral Cloning Training Program')# 添加数据目录参数,默认值为 'data'parser.add_argument('-d',help='data directory',dest='data_dir',type=str,default='data')# 添加模型保存目录参数,默认值为 'save'parser.add_argument('-s',help='save directory',dest='save_dir',type=str,default='save')# 添加测试集大小比例参数,默认值为 0.2parser.add_argument('-t',help='test size fraction',dest='test_size',type=float,default=0.2)# 添加 Dropout 概率参数,默认值为 0.5parser.add_argument('-k',help='drop out probability',dest='keep_prob',type=float,default=0.5)# 添加训练轮数参数,默认值为 100parser.add_argument('-n',help='number of epochs',dest='nb_epoch',type=int,default=100)# 添加批次大小参数,默认值为 40parser.add_argument('-b',help='batch size',dest='batch_size',type=int,default=40)# 添加学习率参数,默认值为 1.0e-4parser.add_argument('-l',help='learning rate',dest='learning_rate',type=float,default=1.0e-4)# 添加早停参数,默认值为 Falseparser.add_argument('-e',help='early stop',dest='early_stop',type=bool,default=False)# 解析命令行参数args = parser.parse_args()print('-' * 30)print('Parameters')print('-' * 30)# 打印所有命令行参数for key, value in vars(args).items():print('{:<20} := {}'.format(key, value))print('-' * 30)# 加载训练数据和验证数据data = load_data(args)# 构建模型model = build_model(args.keep_prob)# 调用训练函数进行模型训练train_model(model, args, *data)if __name__ == '__main__':# 程序入口,调用 main 函数main()
训练结束后可以得到对应的模型
使用这个模型进行测试
打开仿真软件的auto模式
此时是无法记录的,然后我可以加载模型并驾驶车辆
python drive.py ./pretrained_models/model_paddle_test2.pdparams
同样,自己写一边这个代码更容易理解:
import os
import base64
import paddle
import shutil
import argparse
import socketio
import eventlet
import numpy
import eventlet.wsgi
from PIL import Imagefrom io import BvtesIO
from flask import Flask
from datatime import datatime
from car.model import build_model
from car.utils import preprocess# 创建一个socket.IO服务器
sio = socket.Server()
app = Flask(__name__)
# 初始化模型变量,用于后续加载模型
model = None
# 初始化上一帧图像数组变量,用于记录上一帧的图像数据
prev_image_array = None# 定义最大速度和最小速度
MAX_SPEED = 25
MIN_SPEED = 10# 初始化速度限制为最大速度
speed_limit = MAX_SPEED# 定义一个事件处理函数,当接收到 'telemetry' 事件时触发
@sio.on('telemetry')
def telemetry(sid, data):if data:# 从接收到的数据中提取当前汽车的转向角度steering_angle = float(data["steering_angle"])# 从接收到的数据中提取当前汽车的油门值throttle = float(data["throttle"])# 从接收到的数据中提取当前汽车的速度speed = float(data["speed"])# 从接收到的数据中提取当前汽车中心摄像头的图像,并将其解码为 PIL 图像对象image = Image.open(BytesIO(base64.b64decode(data["image"])))# 如果指定了图像保存文件夹,则保存当前帧图像if args.image_folder != '':# 生成当前时间戳,用于作为图像文件名timestamp = datetime.utcnow().strftime('%Y_%m_%d_%H_%M_%S_%f')[:-3]# 构建图像文件的完整路径image_filename = os.path.join(args.image_folder, timestamp)# 保存图像为 JPEG 格式image.save('{}.jpg'.format(image_filename))try:# 将 PIL 图像对象转换为 NumPy 数组image = np.asarray(image)# 对图像进行预处理,例如裁剪、归一化等操作image = preprocess(image)# 为图像数组添加一个维度,使其成为 4D 数组,以满足模型输入要求image = np.array([image])# 使用模型对图像进行预测,得到转向角度的预测值steering_angle = model(image.astype('float32') / 127.5 - 1.0).item()# 根据当前速度调整速度限制和油门值global speed_limitif speed > speed_limit:# 如果当前速度超过速度限制,则将速度限制降低到最小速度,以减速speed_limit = MIN_SPEEDelse:# 如果当前速度低于速度限制,则将速度限制恢复到最大速度speed_limit = MAX_SPEED# 根据转向角度和速度计算油门值throttle = 1.0 - steering_angle**2 - (speed / speed_limit)**2# 打印当前的转向角度、油门值和速度print(f'steering_angle={steering_angle:.3f}, throttle={throttle:.3f}, speed={speed:.3f}')# 发送控制指令,包括转向角度和油门值send_control(steering_angle, throttle)except Exception as e:# 打印异常信息print(e)else:# 如果没有接收到数据,则发送手动控制指令sio.emit('manual', data={}, skip_sid=True)# 定义一个事件处理函数,当有新的客户端连接时触发
@sio.on('connect')
def connect(sid, environ):# 打印连接信息print("connect ", sid)# 发送初始控制指令,将转向角度和油门值都设为 0send_control(0, 0)# 定义一个函数,用于发送控制指令
def send_control(steering_angle, throttle):# 向客户端发送 'steer' 事件,包含转向角度和油门值sio.emit("steer",data={'steering_angle': steering_angle.__str__(),'throttle': throttle.__str__()},skip_sid=True)if __name__ == '__main__':# 创建一个命令行参数解析器parser = argparse.ArgumentParser(description='Remote Driving')# 添加一个必需的命令行参数,用于指定模型文件的路径parser.add_argument('model',type=str,help='Path to model h5 file. Model should be on the same path.')# 添加一个可选的命令行参数,用于指定图像保存文件夹的路径parser.add_argument('image_folder',type=str,nargs='?',default='',help='Path to image folder. This is where the images from the run will be saved.')# 解析命令行参数args = parser.parse_args()# 构建模型model = build_model()# 加载模型的参数params = paddle.load(args.model)# 将加载的参数设置到模型中model.set_dict(params)# 将模型转换为静态图模式,以提高推理速度model = paddle.jit.to_static(model)# 将模型设置为评估模式model.eval()# 如果指定了图像保存文件夹if args.image_folder != '':# 打印创建图像文件夹的信息print("Creating image folder at {}".format(args.image_folder))# 如果文件夹不存在,则创建它if not os.path.exists(args.image_folder):os.makedirs(args.image_folder)else:# 如果文件夹已存在,则先删除它,再重新创建shutil.rmtree(args.image_folder)os.makedirs(args.image_folder)# 打印记录运行信息print("RECORDING THIS RUN ...")else:# 如果没有指定图像保存文件夹,则打印不记录运行信息print("NOT RECORDING THIS RUN ...")# 使用 Socket.IO 中间件包装 Flask 应用app = socketio.Middleware(sio, app)# 使用 eventlet 启动一个 WSGI 服务器,监听 4567 端口eventlet.wsgi.server(eventlet.listen(('', 4567)), app)
即可实现基于视觉的自动驾驶功能。后面这篇文章还会继续完善论文中的一些观点和代码的一些学习过程。
https://github.com/naokishibuya/car-behavioral-cloning?tab=readme-ov-file
相关文章:

端到端自动驾驶——cnn网络搭建
论文参考:https://arxiv.org/abs/1604.07316 demo 今天主要来看一个如何通过图像直接到控制的自动驾驶端到端的项目,首先需要配置好我的仿真环境,下载软件udacity: https://d17h27t6h515a5.cloudfront.net/topher/2016/November…...

深度学习R8周:RNN实现阿尔兹海默症(pytorch)
🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 数据集包含2149名患者的广泛健康信息,每名患者的ID范围从4751到6900不等。该数据集包括人口统计详细信息、生活方式因素、病史、临床测量、认知和功…...
vuex中的state是响应式的吗?
在 Vue.js 中,Vuex 的 state 是响应式的。这意味着当你更改 state 中的数据时,依赖于这些数据的 Vue 组件会自动更新。这是通过 Vue 的响应式系统实现的,该系统使用了 ES6 的 Proxy 对象来监听数据的变化。 当你在 Vuex 中定义了一个 state …...

JavaScript系列05-现代JavaScript新特性
JavaScript作为网络的核心语言之一,近年来发展迅速。从ES6(ECMAScript 2015)开始,JavaScript几乎每年都有新的语言特性加入,极大地改善了开发体验和代码质量。本文主要内容包括: ES6关键特性:解构赋值与扩展运算符&am…...
【量化金融自学笔记】--开篇.基本术语及学习路径建议
在当今这个信息爆炸的时代,金融领域正经历着一场前所未有的变革。传统的金融分析方法逐渐被更加科学、精准的量化技术所取代。量化金融,这个曾经高不可攀的领域,如今正逐渐走进大众的视野。它将数学、统计学、计算机科学与金融学深度融合&…...

3d投影到2d python opencv
目录 cv2.projectPoints 投影 矩阵计算投影 cv2.projectPoints 投影 cv2.projectPoints() 是 OpenCV 中的一个函数,用于将三维空间中的点(3D points)投影到二维图像平面上。这在计算机视觉中经常用于相机标定、物体姿态估计、3D物体与2D图…...

26-小迪安全-模块引用,mvc框架,渲染,数据联动0-rce安全
先创建一个新闻需要的库 这样id值可以逐级递增 然后随便写个值,让他输出一下看看 模板引入 但是这样不够美观,这就涉及到了引入html模板 模板引入是html有一个的地方值可以通过php代码去传入过去,其他的html界面直接调用,这样页…...

【第14节】C++设计模式(行为模式)-Strategy (策略)模式
一、问题的提出 Strategy 模式:算法实现与抽象接口的解耦 Strategy 模式和 Template 模式要解决的问题是相似的,都是为了将业务逻辑(算法)的具体实现与抽象接口解耦。Strategy 模式通过将算法封装到一个类(Context&am…...
播放器系列4——PCM重采样
FFmpeg重采样过程 #mermaid-svg-QydNPsDAlg9lTn6z {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QydNPsDAlg9lTn6z .error-icon{fill:#552222;}#mermaid-svg-QydNPsDAlg9lTn6z .error-text{fill:#552222;stroke:#5…...

网络安全需要学多久才能入门?
网络安全是一个复杂且不断发展的领域,想要入行该领域,我们需要付出足够多的时间和精力好好学习相关知识,才可以获得一份不错的工作,那么网络安全需要学多久才能入门?我们通过这篇文章来了解一下。 学习网络安全的入门时间因个人的…...
通俗版解释:分布式和微服务就像开餐厅
一、分布式系统:把大厨房拆成多个小厨房 想象你开了一家超火爆的餐厅,但原来的厨房太小了: 问题:一个厨师要同时切菜、炒菜、烤面包,手忙脚乱还容易出错。 解决方案: 拆分成多个小厨房(分布式…...

JAVA安全—手搓内存马
前言 最近在学这个内存马,就做一个记录,说实话这个内存马还是有点难度的。 什么是内存马 首先什么是内存马呢,顾名思义就是把木马打进内存中。传统的webshell一旦把文件删除就断开连接了,而Java内存马则不同,它将恶…...

【神经网络】python实现神经网络(一)——数据集获取
一.概述 在文章【机器学习】一个例子带你了解神经网络是什么中,我们大致了解神经网络的正向信息传导、反向传导以及学习过程的大致流程,现在我们正式开始进行代码的实现,首先我们来实现第一步的运算过程模拟讲解:正向传导。本次代…...
历年湖南大学计算机复试上机真题
历年湖南大学计算机复试机试真题 在线评测:https://app2098.acapp.acwing.com.cn/ 杨辉三角形 题目描述 提到杨辉三角形。 大家应该都很熟悉。 这是我国宋朝数学家杨辉在公元 1261 年著书《详解九章算法》提出的。 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 …...

[LeetCode]day33 150.逆波兰式求表达值 + 239.滑动窗口最大值
逆波兰式求表达值 题目链接 题目描述 给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意: 有效的算符为 ‘’、‘-’、‘*’ 和 ‘/’ 。 每个操作数(运…...

【银河麒麟高级服务器操作系统实际案例分享】数据库资源重启现象分析及处理全过程
更多银河麒麟操作系统产品及技术讨论,欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer…...
C#中泛型的协变和逆变
协变: 在泛型接口中,使用out关键字可以声明协变。这意味着接口的泛型参数只能作为返回类型出现,而不能作为方法的参数类型。 示例:泛型接口中的协变 假设我们有一个基类Animal和一个派生类Dog: csharp复制 public…...
【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-附录B-严格模式
附录B、严格模式 严格模式 ECMAScript 5 首次引入严格模式的概念。严格模式用于选择以更严格的条件检查 JavaScript 代码错误,可以应用到全局,也可以应用到函数内部。严格模式的好处是可以提早发现错误,因此可以捕获某些 ECMAScript 问题导致…...
跨平台 C++ 程序崩溃调试与 Dump 文件分析
前言 C 程序在运行时可能会由于 空指针访问、数组越界、非法内存访问、栈溢出 等原因崩溃。为了分析崩溃原因,我们通常会生成 Dump 文件(Windows 的 .dmp,Linux 的 core,macOS 的 .crash),然后用调试工具分…...
缺陷VS质量:为何软件缺陷是质量属性的致命对立面?
为何说缺陷是质量的对立面? 核心逻辑:软件质量的定义是“满足用户需求的程度”,而缺陷会直接破坏这种满足关系。 对立性:缺陷的存在意味着软件偏离了预期行为(如功能错误、性能不足、安全性漏洞等)&#…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...

02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...

Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...