无人驾驶中如何识别颜色并跟踪的具体应用

news2025/4/8 1:31:52

摄像头对于颜色的识别,我们在上一篇文章中有具体的介绍,并介绍了OpenCV中的一些常见知识点,这里我们来对颜色识别在无人驾驶中,做一个具体应用。

有兴趣的可以先看下本人拍摄的一个视频:无人车识别颜色并跟踪  

通过视频我们可以看到无人车,会跟着自己设定的颜色而行驶,包括转弯的实现。那么无人车是如何识别颜色并跟踪的呢?其中的转弯又是怎么做到的呢?我们先来看下代码,代码就是很好的解释:

1、无人驾驶代码

from jetbotmini import Camera
from jetbotmini import bgr8_to_jpeg
import cv2
import numpy as np
import torch
import torchvision
import traitlets
import ipywidgets.widgets as widgets
from IPython.display import display
from jetbotmini import Robot

# 实例化摄像头
camera = Camera.instance(width=300, height=300)

# 蓝色上下限数组
color_lower = np.array([100,43,46])
color_upper = np.array([124, 255, 255])

# 初始化无人车驱动电机实例
robot = Robot()

# 图片、速度进度条、转弯进度条组件的显示
image_widget = widgets.Image(format='jpeg', width=300, height=300)
speed_widget = widgets.FloatSlider(value=0.4, min=0.0, max=1.0, description='speed')
turn_gain_widget = widgets.FloatSlider(value=0.5, min=0.0, max=2.0, description='turn gain')
display(widgets.VBox([widgets.HBox([image_widget]),speed_widget,turn_gain_widget]))

width = int(image_widget.width)
height = int(image_widget.height)

center_x = 0
def execute(change):
    # -----这块属于对图像的处理与颜色检测,上篇文章有详细介绍------
    frame = camera.value
    frame = cv2.resize(frame, (300, 300))
    frame_=cv2.GaussianBlur(frame,(5,5),0)
    hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
    mask=cv2.inRange(hsv,color_lower,color_upper)
    mask=cv2.erode(mask,None,iterations=2)
    mask=cv2.dilate(mask,None,iterations=2)
    mask=cv2.GaussianBlur(mask,(3,3),0)
    cnts=cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]
    # ------------------------------------------------------------------------

    # 检测到了目标
    if len(cnts)>0:
        cnt = max(cnts,key=cv2.contourArea)
        (color_x,color_y),color_radius=cv2.minEnclosingCircle(cnt)
        if color_radius > 10:
            # 将检测到的颜色标记出来
            cv2.circle(frame,(int(color_x),int(color_y)),int(color_radius),(255,0,255),2)
            # 偏离中心位置来判断是否转弯
            # [-1,1]
            center_x = (150 - color_x)/150
            robot.set_motors(
                float(speed_widget.value + turn_gain_widget.value * center_x),
                float(speed_widget.value - turn_gain_widget.value * center_x)
            )
    # 没有检测到就停止
    else:
        pass
        robot.stop()
    # 更新图像显示到Image组件
    image_widget.value = bgr8_to_jpeg(frame)

将摄像头初始化,并且定义了一个能够检测到颜色的方法,除了识别颜色之外,我们还做了一个颜色目标位置在摄像头左右的偏移量,这个是用来给左右马达更新不同的速度值的。这个就是为什么无人车可以进行转弯的原因了,目标的中心位置在图像中心位置的偏离值,我们将其添加到马达的速度中去,左右马达一个是加另一个是减,这样就形成了差速!
接下来我们调用这个方法:execute({'new': camera.value})
当然这种调用只能检测到一帧,我们需要的是实时更新摄像头的图像,实时的去跟踪变化的场景。
我们使用observe方法来实时处理:

camera.unobserve_all()
camera.observe(execute, names='value')

这样就可以实时检测蓝颜色目标,如果检测到目标,就会跟随目标行驶,如果没有检测到,无人车将会停止。

2、无人车停止

虽然上面代码可以在没有检测到目标的时候,无人车会自动停止,但有时候我们也想要强制停止无人车,如下:

import time
camera.unobserve_all()
time.sleep(1.0)
robot.stop()

我们可以看到上面的代码整体跟颜色识别章节差不多,区别在于多了一个无人车的加入,更准确来讲是多了左右两个轮子(马达),这两个轮子是差速轮,意思就是各自拥有一个马达驱动,速度可以不同(速度一样就是直行),这样才能够转弯和漂移等操作,根据识别到的颜色的中心位置来更新左右马达的速度,这样就有了跟踪的效果。

其中如何驱动无人车的更多详细介绍可以查阅:Jetson Nano驱动机器人的左右两路电机

3、camera.observe

observe(handler, names=traitlets.All, type='change')

设置一个在trait改变时调用的处理程序
其中handler是回调函数,调用的就是上面定义的execute函数,handler(change),其中change是一个字典,所以这也是调用execute时,参数是字典的原因{'new': camera.value}
在type为change的情况下,有以下几个键:

owner:HasTraits实例
old:修改后的trait属性的旧值
new:修改后的trait属性的新值
name:修改后的trait属性的名称

所以这里就做到了一个类似死循环的效果,可以对摄像头的每一帧进行更新。

4、camera.unobserve_all

camera.unobserve_all(name=traitlets.All)

删除指定名称的任何类型的trait更改处理程序。如果未指定名称,删除所有trait通知器。或者通俗来讲就是关闭视频流,释放资源的意思。
所以我们看到在camera.observe和robot.stop()之前都先做一步释放资源的处理以及停止无人车。

5、CSI摄像头

这里对摄像头做一个附加解释,随着人工智能的发展,自动驾驶,智能家居等应用都离不开摄像头,而一款低功耗低成本高清晰的摄像头就显得尤为重要了。一般大家见到的摄像头是USB接口,而这里是使用CSI接口协议的摄像头,如图:

可以看到这里是15针的排线,不是常见的USB接口,CSI接口是主机处理器与摄像头模块之间的高速串行接口,最关键点是能耗低,这也导致了现在手机高清摄像头的普及。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/765117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PICO4开发实战一:节奏光剑(VR)(需求文档)

PICO4开发实战一:节奏光剑(VR)(需求文档) 文章目录 PICO4开发实战一:节奏光剑(VR)(需求文档)一、V1 基础功能开发1、V1版本完成页面2、V1基本功能需求介绍&am…

81. 正则表达式

一、概述二、匹配单个字符三、匹配一组字符四、使用元字符五、重复匹配六、位置匹配七、使用子表达式八、回溯引用九、前后查找十、嵌入条件参考资料 一、概述 正则表达式用于文本内容的查找和替换。 正则表达式内置于其它语言或者软件产品中,它本身不是一种语言或…

学习react,复制一个civitai(C站)-更新3

更新内容 优化了一下加载速度 图片列表 初步更新了199张图片,大部分都有stable diffusion 的prompts。 可以直接复制到AI绘画里面使用。 先来看看效果图吧: 我还是挺喜欢这种砌砖流布局 技术点 同样使用了砌墙瀑布流布局:masonry js 安装方法 npm …

配置Propos检验

配置Propos检验 ​ 和vue不同react并未为我们直接配置props校验,(类型必填默认值),需要我们就手动进行配置

SqlServer数据库【基础-更删改查】

一、创建语句 (1)创建数据库 1.检查系统中是否存在这个数据库,存在则删除 格式: if exists(select * from sysdatabases where name数据库名) drop database 数据库名 go例子: if exists(select * from sysdataba…

Redis事务(4)

⭐ 作者简介:码上言 ⭐ 代表教程:Spring Boot vue-element 开发个人博客项目实战教程 ⭐专栏内容:个人博客系统 ⭐我的文档网站:http://xyhwh-nav.cn/ 文章目录 Redis事务1、Redis事务概念2、应用1、MULTI开启事务2、事务失败…

【数据库】数据库索引结构分析,MySQL单表最多能存放多少数据

经常听到MySQL单表最多能存放2千万数据,多了就要考虑分表,依据是什么呢? 本文以MySQL为例,默认数据页大小是16KB。 索引内容结构 非叶子节点 主键页号 假如: 主键是bigint,8bit;页号是4bit&…

Vue中v-html用法以及指令汇总

操作数组的方法 : push:数组最后位置新增元素 pop: 删除最后一个元素 shift: 删除第一个元素 unshift:往前面加一个元素 splice:在数组的指定位置插入、删除、替换一个元素 sort: 数组排序…

力扣算法数学类—Excel表列名称

目录 Excel表列名称 题解: 代码: Excel表列名称 168. Excel表列名称 - 力扣(LeetCode) 给你一个整数 columnNumber ,返回它在 Excel 表中相对应的列名称。 例如: A -> 1 B -> 2 C -> 3 ... Z -…

CENTOS安装 graylog5.0

我们直接开始 基础环境和java sudo yum install epel-release 并安装带有 sudo yum install pwgenyum install java-1.8.0-openjdk-headless.x86_64 MONGODB 安装数据库 6.0 [mongodb-org-6.0] nameMongoDB Repository baseurlhttps://repo.mongodb.org/yum/redhat/$relea…

ensp静态路由

要求: 1.全网可达 2.拓朴中所需地址全部基于192.168.0.0/24 3.静态路由(不许使用其他动态) 4.R2环回需要汇总 拓朴图: 将192.168.0.0/24划分为5个子网, 得: 192.168.0.0/27 192.168.0.32/27 192.168.0.64/…

在Windows Server2016上搭建Active Directory域控服务

搭建服务端 使用Windows2016数据中心版完成 1. 配置服务器角色 2. 选择服务器角色 3. 选择当前服务器4. 选择Active Directory和DNS角色5. 确认安装 6. 提升为Domain Controller域控服务器 7. 设置根域 8. 配置保护密码 9. DNS 10. NetBIOS配置 11. 指定数据文件位置 12. 确…

Flink AggregateFunction窗口函数,merge何时执行

1.前言 在我们使用Flink DataStream API编写业务代码时,aggregate()算子和AggregateFunction无疑是非常常用的。编写一个AggregateFunction需要实现4个方法: /** Licensed to the Apache Software Foundation (ASF) under one* or more contributor li…

瀚高企业版数据库V6单机安装指导手册(Linux)

目录 瀚高企业版数据库V6单机安装指导手册(Linux) 1. 环境准备 1.1 防火墙设置 1.1.1 开放数据库使用端口 1.1.2 关闭防火墙 1.2 检查时区和时间 1.3 创建highgo用户 1.4 检验安装包 2. 软件安装 2.1 图形化安装 3. 设置highgo用户环境变量 4.…

RocketMQ无损扩容实战

这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党 背景 假设目前我们的线上部署的RocketMQ部署的是一主一从,现在随着业务的发展,或者是我们需要做一些促销活动,会有突发流量高…

【unity细节】为什么发射炮弹实例化出来了却无法移动

👨‍💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 收录于专栏:unity细节和bug ⭐为什么发射炮弹实例化出来了却无法移动⭐ 文章目录 ⭐为什么发射炮弹实例化出来…

JS高级进阶

JavaScript 进阶 - 第1节 学习作用域、变量提升、闭包等语言特征,加深对 JavaScript 的理解,掌握变量赋值、函数声明的简洁语法,降低代码的冗余度。 理解作用域对程序执行的影响能够分析程序执行的作用域范围理解闭包本质,利用闭包…

java mybatis

1.框架介绍 为什么使用框架? (1)框架效率高,成本低 (2)框架是别人写好的构建,我们只需学会如何使用它【可维护性高】 (3)框架是基于MVC的思想【web层独有的思想】的拓展而开发的…

DeepC 实用教程(四)分析

目 录 一、前言二、DeepC分析三、新建分析 / New Analysis四、Response Storage五、Static Analysis Options六、Dynamic Analysis Options七、Multiple Analysis八、提交分析/执行分析九、参考文献 一、前言 SESAM (Super Element Structure Analysis Module&#…

【动手学深度学习】GPU初步认识与使用

【动手学深度学习】GPU初步认识与使用 查看显卡 使用nvidia-smi命令来查看显卡信息 pytorch中每一个数组都有一个设备,将其称之为环境,那么默认情况下都是在CPU上,有时候环境是GPU 计算设备 默认情况下,张量是在内存中创建的&a…