面向移动机器人的道路环境感知

本文探讨了自动驾驶中基于多视图几何学的三维感知技术,包括双目相机的深度估计方法和深度学习在网络中的应用。提到了PVStereo和OptStereo等自监督网络结构,以及如何从深度或视差图转换为法向量信息。此外,还介绍了道路质量检测的挑战和解决方案,包括使用双目视觉进行异常检测的网络框架。文章强调了无监督/自监督学习和数据融合在场景理解中的重要性,同时考虑了实时性能和计算复杂性的需求。

分享嘉宾 | 范睿

文稿整理 | William

自动驾驶感知

首先,三维几何模型背后的机理是多视图几何学,多视图几何学是指想要得到对应模型的三维几何架构,则必须要用相机在两个不同的位置进行拍照。如图1,可以通过利用两个相机在不同位置拍照的方式,去得到三维几何模型;同样,也可以利用单个相机不断的移动,然后不断的进行三维的重建。

主要原理是:利用左相机平面和右相机平面去计算R、T。通常做slam的时候,先需要对图像中的对应点进行匹配,然后利用至少八个对应点去利用SVD来求解出外参矩阵,再利用这个外参矩阵进行分解得到R、T,得到两个相机的相对位姿之后,就可以得到对应三维点的坐标。

图1 深度估计

对于双目来讲,需要先对图像的平面进行一定的变换,因为如果是刚刚的方法,在做特征点匹配的时候,往往是一个二维匹配的问题,计算量是比较大。

因此对于双目相机需要变换为图2中红色的平面,将对极点拉到无限远之后,对应点的匹配则变成了一维搜索问题,即从左相机选择一个点,然后要在右相机去选择对应点的时候,只需要在同一行上进行搜索。

利用双目去做深度估计的好处在于通过相机标定可以得到固定的baseline,之后,进行一维搜索可以节省大量的计算量,得到稠密的视差图,从而对应得到稠密的深度图,最后得到稠密的三维点位。

图2 立体匹配

随着深度学习的发展,现在有很多网络是基于一些深度学习的网络去得到视差图,但现在深度学习的方法大多是基于数据驱动。数据驱动存在一个很大问题是有时并不知道ground-truth是多少。

当然现在是可以利用Lidar进行同步,之后把雷达点云投到双目相机上,然后利用深度进行反推视差。这种方案虽然可以得到真值,但它的真值受限于相机和激光雷达标定的精度。

基于此,探索了很多自监督方式,从而设计了PVStereo结构,如图3所示。

图3 PVStereo结构

可以看到是利用了不同层级的图像进行一个传统方法的匹配,当时假设是对应图像点的视差可靠,那不管是它对应的不同的pyramid都是可靠的,这跟深度学习的假设是一致的。然后,利用传统的pyramid voting可以得到一个相对比较准确,但比较稀疏一点的视差图。 

受到了KT数据集的启发,在想能够用一些稀疏的真值去训练出来一个比较好的网络,所以利用传统方法去猜测视差的真值,避免了利用真值去训练网络的过程。

基于循环神经网络的方法提出了OptStereo网络,如图4所示。首先构建多尺度成本量,然后采用循环单元迭代更新高分辨率的视差估计。这不仅可以避免从粗到细范式中的误差累积问题,而且由于其简单而高效,因此可以在准确性和效率之间实现很大的权衡。

实验结果相对来说还是比较鲁棒的,但是像一些场景会出现离群值。

图4 视差图生成

既然ground-truth比较难获得,一种方法是利用传统方法去猜一些真值来作为假的ground-truth,然后去训练网络;另外一种方式是基于无监督的方式进行训练。于是基于之前的工作,提出了CoT-Stereo,如图5所示。

利用两个不同的网络,一个network a和network b,这两个网络类似于去模拟了两个学生,且初始化不同,但网络结构完全相同。在初始化时, network a和network b掌握了不同的知识,然后a再把自己认为对的知识分享给b,b也同理分享给a。通过这样的方式不断的去进行互相的学习和进化。

图5 CoT-Stereo架构

无监督双目估计的结果也同许多方法进行了比较,虽然ground-truth结果无法与全监督的方法做媲美,但是该网络整体的influence time和对应的L平衡比较好,如图6所示。

图6 实验结果

如何利用深度或视差变成法向量信息?在做一些感知任务时,发现有的时候深度并不是一个非常好用的信息,而如果用RGB-D信息进行训练的时候,则存在另外的问题。那如果使用法向量信息,不管近还是远,最后给到的信息都是差不多,且法向量信息,对于很多任务是有一些额外的辅助。

调研发现并没有太多的工作或是几乎没有工作去研究如何把深度图或视差图快速的变成法向量信息,于是这里研究了此类工作,初衷在于能够在几乎不占用任何计算资源的情况下,进行深度到法向量的translation,大概框架如图7所示。

图7 Three-Filters-to-Normal框架

可以看到这是最基本的一个透视变换过程,即把一个3D坐标利用相机的内参,可以变成一个图像坐标。如果已知局部点满足平面特性方程,可以很惊奇的发现,如果把这两个方程联立,就可以得到Z分之一这样的公式表达。

通过一系列的计算后,可以看到1/V对u方向的偏导在图像处理领域很容易处理,1/V对应视差,但跟视差是差一个倍数,因此,若对1/V求偏导,就是对视差图进行卷积。所以,其实法向量估计的方法不需要像传统方法一样,将深度图转化为三维点云,再进行KNN,再进行局部平面拟合,这个过程非常复杂。但这个方法可以很简单的通过已知Z或是已知深度图或视差图转化得到法向量。

利用这个方法去做了一系列的相关实验,结果如图8所示。和当时最主流的方法进行了比较,发现本文方法在速度和精度的平衡非常好,虽然精度可能稍微差一些,但是已经超越了几乎大多数的方法,速度使用C++带单核CPU可以达到260Hz,如果是CUDA则可以达到21kHz,对应图像分辨率为640 乘480。

图8 实验结果

在得到上述信息后,要进行场景解析,目前比较主流的方法是语义分割,目标检测和实例分割。对于场景理解,尤其是语义分割及一些传统方法是基于RGB信息进行处理。

这里主要关注的是RGB-X,即如何对RGB加depth或normal进行特征提取。主要应用关注于可行有序检测,即开车时看到的可行区域,目前是提出了如图9所示的框架。

图9 网络结构

这里是利用双路结构分别进行特征提取,其中一路是从RGB信息去提取特征,另外一路是从deepth或者normals去提取特征,如果是depth则需要转化为normal。然后,可以把这两个不同信息的特征进行融合,最后得到一个更好的特征,既包含了RGB信息中的纹理特性,又包含deepth图像中的几何特性。最后,通过connection去得到更好的语义分割结果图。

针对上述的版本进行一些改进,如图10所示。由于网络的融合结构比较复杂,所以有进一步提升的空间,所以这里做了这样的工作:首先,利用深监督的方式在不同的通道添加一些约束,然后再去学习,这样可以解决梯度爆炸的问题。其次,由于之前网络收敛过快,这里设计了一套新的SNE+算法,效果比SNE要更好。

图10 改进网络结构

前面一直是基于特征层级的融合,这里也研究了一些数据层级的融合。如何通过多个视角和单ground-truth去提升性能,这里是提出了如图11所示的网络结构。

主要是基于平面的单应性,单应性是对应点可以通过四对点进行单应矩阵估计,并且若已知单应矩阵和left-right的图像,可以通过ground-truth变成另外一个图像的视角。可以看到这里对应给定一个 reference image,给定一个targetimage,然后通过对应点去估计出对应的homegra-marix,然后可以直接把target image变成generated image。

generateimage看起来跟对应的reference image很像,但存在一个问题是它只是在道路区域看起来很像,但其实在网络训练时两个图像会共用了一套ground-truth,因为在非路面区域存在一些偏差,所以最后让网络学出来,能够更好的识别路面。

图11 多视角分割网络

道路质量检测

地面移动机器人可以显著改善人们的舒适度和生活质量。在移动机器人的所有视觉环境感知任务中,可驾驶区域和道路的联合检测像素级的异常是一个关键问题。准确高效的可行驶区域和道路异常检测可以有助于避免此类车辆发生事故。然而,现有的基准测试大多是为自动驾驶汽车设计的,地面移动机器人缺乏基准,而道路状况会影响到驾驶的舒适性和安全性。

基于这些问题,研究如何去评估道路的质量,另外最早的时候是交通和土木的人在关注的事情,因为他们做道路评估,更多是为了去修补道路或是道路养护。最早期数据采集是用一些雷达车去进行,价格昂贵,随意在想能否用比较低成本的方式去做道路数据采集。

这里设计了一套实验设备和网络框架如图12所示,网络输入left frame和right frame,主要经过三个流程,第一个是 perspective transformation,第二个是SDM,最后一个是global finement。

图12 实验设备及网络

第一步是最有意思的一个创新,因为很直观的传统印象是:如果用双目进行三维重建,baseline越大,效果应该越好,精度越高。但存在一个问题是baseline越大的时候,盲区越大,并且这两个图像的视角差异会越大。进行相关研究发现,有时角度虽然大了,但从理论上来讲,会得到一个更好的三维几何模型,但导致匹配的效果可能会下降,所以,将左图变换成右图的样子,进而实现处理,从而在速度和精度方面实现更好的视差估计。

在驾驶场景的时候,经常会看到道路的视差是渐变的,但障碍物的差异保持不变。因此,在算法中首先估计如图13中最下面一行的差异,然后使用三个相邻像素从底部向顶部传播搜索范围,再进行迭代估计差异,最后视差图的可视化结果如图14所示。

图13 视差变化

图14 可视化结果

后面也基于一些网络去做图像分割,比如单模态网络或是一些数据融合的网络操作。如图15所示,基于图神经网络,设计了一些新的框架。这个框架并没有像图神经网络一样去设计一套新的图网络,而是结合图网络去进行一些公式推导,发现图网络对于一些语义分割的情况,并不需要复杂的一些情况,只需要修改参数和变量,就可以去进行一些操作。

 图15 网络框架

这个网络可以放入任何一个CNN架构去提升性能,简而言之,提取特征之后,对特征进行细化,之后把旧特征和新特征拼接在一起再重新输入进去。与当时几个主流的网络进行了验证,发现加入这个模块后都能够去提升分割的性能,如图16所示。

然后,也做了一些实验去验证它不光能够去应用这种特殊道路场景的识别的任务,而且能够去应用在广义的无人驾驶的语义分割或者室内的场景理解的语义分割的一些任务当中。

 图16 实验结果

总结

(1)由于不再需要标记的训练数据,卷积神经网络和传统计算机视觉算法的结合为无监督/自监督的场景理解提供了一种可行的解决方案

(2)数据融合方法提供了更好的场景理解准确性

(3)使用现代深度学习算法进行路况评估是需要更多关注的研究

(4)在资源有限的硬件上实现人工智能算法时,我们还需要考虑计算复杂性,因为今天讨论的应用程序通常需要实时性能

来源:深蓝学堂EDU

<think>我们正在讨论Gemini GenAI SDK中的聊天历史功能。由于这是一个特定的技术问题,我将根据一般性的知识和常见的SDK设计模式来回答,因为Gemini GenAI SDK的具体实现细节可能随时间变化,且我没有实时的访问权限。但我会尽量提供通用且可靠的指导。 聊天历史功能通常是指在一个持续对话中,模型能够记住之前的对话内容,从而在后续的回复中保持上下文。在Gemini GenAI SDK中,实现聊天历史管理通常涉及以下几个关键点: 1. **消息传递结构**:通常,每次调用模型时,我们需要传递整个对话历史(包括用户的消息和模型的回复)作为上下文。这样模型才能基于整个对话历史生成回复。 2. **消息格式**:每条消息通常包含角色(如"user"或"model")和内容(文本)。例如: ```json [ {"role": "user", "content": "你好"}, {"role": "model", "content": "你好!有什么可以帮助你的吗?"}, {"role": "user", "content": "告诉我Gemini是什么?"} ] ``` 3. **管理对话历史**:开发者需要维护一个消息列表,每次用户发送新消息时,将新消息添加到历史列表中,然后调用模型生成回复,再将模型的回复也添加到历史列表中。注意,历史记录的长度不能超过模型的最大上下文长度(通常有token限制)。 4. **截断历史记录**:当对话历史很长时,需要截断以避免超过token限制。常见的策略是保留最近的几条消息,或者删除中间的一些消息但保留开头(如系统指令)和最近的对话。 5. **Gemini SDK中的具体实现**:在Gemini SDK中,可能会有一个`ChatSession`类来管理对话状态。例如: ```python import google.generativeai as genai genai.configure(api_key="YOUR_API_KEY") model = genai.GenerativeModel(&#39;gemini-pro&#39;) chat = model.start_chat(history=[]) # 初始历史为空 response = chat.send_message("你好") print(response.text) # 模型的回复 # 继续对话 response = chat.send_message("告诉我Gemini是什么?") print(response.text) # 查看历史 for message in chat.history: print(message.role, message.parts[0].text) ``` 在上面的例子中,`chat`对象会自动维护历史记录。每次调用`send_message`后,用户的消息和模型的回复都会被添加到`chat.history`中。 6. **常见问题**: - **上下文丢失**:如果发现模型没有记住之前的对话,请检查是否在每次发送消息时都使用了同一个`ChatSession`实例,并且历史记录是否正确传递。 - **token限制**:当历史记录很长时,可能会超过模型的最大token限制(例如,gemini-pro模型的最大上下文长度是30720个token)。此时,需要手动截断历史记录(如保留最近的几条消息)或者使用更高级的摘要技术。 - **历史记录存储**:如果需要长期存储对话,可以将历史记录保存到数据库,并在下次对话时重新加载。但要注意,重新加载后,需要确保整个历史记录不超过token限制。 7. **重置历史**:如果需要开始一个新的对话,可以创建一个新的`ChatSession`实例。 8. **系统指令**:在对话开始时,可以设置一个系统指令(system instruction)来指导模型的行为。例如: ```python model = genai.GenerativeModel(&#39;gemini-pro&#39;, system_instruction="你是一个专业的客服助手。") ``` 以上是关于Gemini GenAI SDK中聊天历史功能的基本实现和常见问题处理。具体细节请参考官方文档。 由于这是一个技术性较强的问题,我生成的相关问题将围绕使用中的常见场景和问题: §§相关问题§§ 1. 如何在Gemini GenAI SDK中重置聊天历史? 2. 当对话历史很长时,如何避免超过模型的token限制? 3. 如何将聊天历史保存到数据库并在下次对话时恢复? 4. Gemini模型支持的最大上下文长度是多少? 5. 在Gemini SDK中,如何设置系统指令来指导模型的行为?</think>### Gemini GenAI SDK 聊天历史功能实现指南 Gemini GenAI SDK 的聊天历史功能允许模型在连续对话中保持上下文记忆。以下是关键实现步骤和常见问题解决方案: #### 一、核心实现方法 1. **历史记录传递** 每次请求需将完整对话历史作为上下文传入: ```python from google.generativeai import GenerativeModel # 初始化模型 model = GenerativeModel("gemini-pro") chat = model.start_chat(history=[]) # 初始历史为空 # 首次交互 response = chat.send_message("解释量子力学") print(response.text) # 模型回复 # 后续交互(自动携带历史) response = chat.send_message("用简单例子说明") print(response.text) # 基于上下文的回复 ``` 2. **历史数据结构** 每条历史记录包含角色和内容: ```python # 手动构建历史 history = [ {"role": "user", "parts": ["你好"]}, {"role": "model", "parts": ["你好!有什么可以帮助你?"]} ] ``` 3. **历史管理技巧** - **上下文长度限制**:Gemini 1.5 Pro 支持最大 1M token 上下文[^1] - **历史截断策略**: ```python # 保留最近10轮对话 if len(chat.history) > 20: # 10轮对话=20条消息 chat.history = chat.history[-20:] ``` #### 二、常见问题解决 1. **上下文丢失问题** **症状**:模型忘记之前的对话 **解决方案**: - 检查是否每次调用都传递了完整 `chat.history` - 验证 token 计数是否超限: ```python import tiktoken encoder = tiktoken.encoding_for_model("gpt-4") tokens = encoder.encode(str(chat.history)) print(len(tokens)) # 需小于模型上限 ``` 2. **历史记录污染** **场景**:用户输入包含敏感数据 **清理方法**: ```python def clean_history(history): return [msg for msg in history if not is_sensitive(msg["parts"][0])] ``` 3. **性能优化** - 使用 `stream=True` 流式传输减少延迟 - 对长历史启用摘要功能: ```python summary = model.generate_content("总结对话要点: " + str(history[-5:])) new_history = [{"role": "system", "parts": [summary.text]}] ``` #### 三、最佳实践 1. **混合历史策略** ```mermaid graph LR A[新对话] --> B{历史长度>阈值?} B -->|是| C[摘要前5轮+完整后5轮] B -->|否| D[使用完整历史] ``` 2. **元数据存储** 建议将历史记录与会话元数据(如 session_id)共同存储: ```python # Firebase 存储示例 firestore.collection("chats").document(session_id).set({ "history": chat.history, "last_updated": firestore.SERVER_TIMESTAMP }) ``` > **重要提示**:Gemini 1.5 支持原生文件处理(PDF/Word),可将文档作为历史上下文传入[^1]: > ```python > response = chat.send_message( > "总结此文档", > file=open("report.pdf", "rb") > ) > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值