花费200元,我用全志H616和雪糕棒手搓了一台可UI交互的视觉循迹小车

news2025/3/10 14:46:35

常见的视觉循迹小车都具备有路径识别、轨迹跟踪、转向避障、自主决策等基本功能,如果不采用红外避障的方案,那么想要完全满足以上这些功能,摄像头、电机、传感器这类关键部件缺一不可,由此一来小车成本也就难以控制了。

但如果,有这样一款视觉循迹小车,它可以完全自己手搓,并用成本极低的雪糕棒来搭建车体架构,不仅保留了传统循迹小车具备的所有功能,还额外适配上一块小屏幕并配上UI界面用于升级人机交互方式。

在这里插入图片描述

在这里插入图片描述

更重要的是,它的器件成本被压缩到200元左右,这样的视觉循迹小车能让你心动吗~

在这里插入图片描述

核桃派视觉循迹小车简介

核桃派H616视觉循迹小车的循迹功能和人机交互界面整体代码由Python+Qt实现,它通过摄像头获取周围环境的图像信息,并利用图像处理算法识别出特定的标记或路径,然后根据标记或路径的形状和方向信息,自动控制小车的行驶方向和速度,以实现沿着预定轨迹自动行驶的目的。

在这里插入图片描述

手搓一台视觉循迹小车所需要用到的基础硬件材料如下:

1、核桃派H616开发板+LCD屏幕≈178元;
2、四个电机+车轮≈16元;
3、电机驱动模块≈4元;
4、摄像头≈50元;
5、移动电源≈20元;
6、雪糕棒若干≈4元(也可以≈不要钱);

循迹功能实现

要让小车实现循迹自运动的操作,其实也可以说是一个在教小车如何精准识别线路并做出判断的过程,想要小车的摄像头实现对路线的准确判断,就需要用到一个目前循迹小车最广泛采用的技术手段——二值化。

在这里插入图片描述

二值化是图像分割的一种方法,用于将图像中的像素点矩阵的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。

在二值化过程中,将大于某个临界灰度值的像素灰度设为灰度极大值(通常是255),将小于这个值的像素灰度设为灰度极小值(通常是0),从而实现二值化。

# 根据不同模式,用不同的hsv上下限值
upper_hsv = (180,255,100)
lower_hsv = (0,0,0)
grayImage = cv2.inRange(hsvImage, np.array(lower_hsv), np.array( upper_hsv)) # 颜色二值化

在这里插入图片描述

二值化图像后,整个画面会被区分为黑白分明的两种颜色,之后就需要进行路线轮廓的描绘以及质心的标注,这个操作的目的是让小车知道该往左拐还是往右拐,进而控制两边车轮的速度。

  • 获取最大轮廓
# 获取所有轮廓,画出所有轮廓
contours, hierarchy = cv2.findContours(grayImage, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
areas = [cv2.contourArea(c) for c in contours]]
cv2.drawContours(rgbImage,contours, -1,(0,255,0),3)
  • 计算质心
# 计算面积最大轮廓的质心
areas = [cv2.contourArea(c) for c in contours]
   try:
      M = cv2.moments(contours[areas.index(max(areas))])
   except:
      pass
   M10=M.get("m10")
   M01=M.get("m01")
   M00=M.get("m00")
   if M00 <= 0 :
      continue
   cX = int(M10 / M00)
   cY = int(M01 / M00)
# 绘制质心
cv2.circle(rgbImage, (cX, cY), 15, (255, 0, 255), -1)

在这里插入图片描述

在绘制轮廓与质心后就需要进行质心坐标的判断,这里的原理很简单,就是质心偏左就往左转,质心偏右就往右转,在判断的同时通过电机来控制两边车轮的速度进而控制小车的行驶方向。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

根据质心的位置计算车轮速度的控制参数postion,根据具体的计算公式可以得知,postion的取值范围为-50到+50,其中0代表质心在正中间,+越大质心越往左,-越大质心越往右,则进行下面的速度计算和控制,否则将速度设置为0,再根据postion和delta_sum的值以及其他参数的调整,计算并控制左右车轮的速度。


# 车轮速度控制
if self.flag_start.status() == True :
    # -50 ~ +50  :0为正中间,+越大则越往左,-越大则越往右,
    postion = int(int(center_x - cX) / int(center_x / 50)) 
    # postion += self.delta_sum 

    step = self.postion_last - postion
    self.delta_sum += (postion - step)*0.01
    if self.delta_sum > 100:
        self.delta_sum =  100
    elif self.delta_sum < -100:
        self.delta_sum =  -100
    if abs(postion) < 5 :
        self.delta_sum = 0
       
    # print("self.delta_sum", self.delta_sum)
    self.postion_last = postion
         
    speed_l = 50 - postion - int(self.delta_sum) 
    speed_r = 50 + postion + int(self.delta_sum) 

    motor.L.speed(speed_l)
    motor.R.speed(speed_r)
    self._slider_l.setValue(speed_l)
    self._slider_r.setValue(speed_r)

在这里插入图片描述

人机交互界面

核桃派H616开发板上预装了PyQt,所以可以使用Qt自带的设计器软件来画窗口,在设计好后通过命令一键转化为Python代码,再去核桃派的开发文档复制一段显示案例的代码,就可以轻松在电脑上预览到刚刚的窗口画面。

在这里插入图片描述

为了在远程服务器上运行图形界面应用程序,通过设置os.environ[“DISPLAY”] = ":0.0"允许Thonny远程运行。

# 允许Thonny远程运行
import os
os.environ["DISPLAY"] = ":0.0"

定义了一个名为event_press的函数,用于处理QPushButton按钮的released事件。当按钮被释放时,切换work.flag_start的状态,并根据状态改变按钮的文本。

def event_press():
    if work.flag_start.status():
        work.flag_start.disable()
        ui.pushButton.setText("点击开始")
    else :
        work.flag_start.enable()
        ui.pushButton.setText("点击结束")

在这里插入图片描述

为了处理三个不同按钮的released事件,定义了change_to_mode三个函数,这些函数用于将work.flag_mode的模式设置为不同的值。


def change_to_mode0():
    work.flag_mode.set_mod( 0 )
def change_to_mode1():
    work.flag_mode.set_mod( 1 )
def change_to_mode2():
    work.flag_mode.set_mod( 2 )
ui.pushButton.released.connect(event_press)
ui.pushButton_auto.released.connect(change_to_mode0)
ui.pushButton_black.released.connect(change_to_mode1)
ui.pushButton_white.released.connect(change_to_mode2)

以上这些代码片段是构成一个由PyQt所创建GUI的关键部分。它通过创建一个窗口,并在窗口中显示了一些UI元素,同时定义了一些事件处理函数,这个应用程序根据用户的操作来控制某些功能,并使用定时器来让解释器每隔一段时间运行一次,以保持界面响应性能,最后进入主循环等待事件的触发和处理。

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

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

相关文章

欢迎来到IT时代----盘点曾经爆火全网的计算机电影

计算机专业必看的几部电影 计算机专业必看的几部电影&#xff0c;就像一场精彩的编程盛宴&#xff01;《黑客帝国》让你穿越虚拟世界&#xff0c;感受高科技的魅力&#xff1b;《社交网络》揭示了互联网巨头的创业之路&#xff0c;《源代码》带你穿越时间解救世界&#xff0c;这…

LabVIEW声速测定实验数据处理

LabVIEW声速测定实验数据处理 介绍了一个基于LabVIEW的声速测定实验数据处理系统的应用。该系统利用LabVIEW的强大数据处理和分析能力&#xff0c;通过设计友好的用户界面和高效的算法&#xff0c;有效提高了声速测定实验的数据处理效率和准确性。通过这个案例&#xff0c;可以…

2024最新uniapp基础腾讯IM

即时通信 IM 快速入门&#xff08;uniapp vue2/vue3&#xff09;-快速入门-文档中心-腾讯云

行人重识别综述

Deep Learning for Person Re-identification: A Survey and Outlook 论文地址https://arxiv.org/pdf/2001.04193 1. 摘要 we categorize it into the closed-world and open-world settings. closed-world&#xff1a;学术环境下 open-world &#xff1a;实际应用场景下 2…

瑞_23种设计模式_适配器模式

文章目录 1 适配器模式&#xff08;Adapter Pattern&#xff09;1.1 介绍1.2 概述1.3 适配器模式的结构 2 类适配器模式2.1 案例2.2 代码实现 3 对象适配器模式&#xff08;推荐&#xff09;★3.1 案例3.2 代码实现 4 拓展——JDK源码解析 &#x1f64a; 前言&#xff1a;本文章…

Java项目,营销抽奖系统设计实现

作者&#xff1a;小傅哥 博客&#xff1a;https://bugstack.cn 项目&#xff1a;https://gaga.plus 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; 大家好&#xff0c;我是技术UP主&#xff0c;小傅哥。 经过这个假期的嘎嘎卷&#x1f9e8;…

VMware下安装银河麒麟V10操作系统

VMware下安装银河麒麟V10操作系统 文章目录 下载在VMware中应用编辑虚拟机设置 在麒麟系统内安装 下载 官网下载&#xff1a;https://www.kylinos.cn/ 银河麒麟、中标麒麟、开放麒麟、星光麒麟 在VMware中应用 1.新建虚拟机 2.稍后安装操作系统 3.新建虚拟机向导&#xff0…

设计模式三:工厂模式

工厂模式包括简单工厂模式、工厂方法模式和抽象工厂模式&#xff0c;其中后两者属于23中设计模式 各种模式中共同用到的实体对象类&#xff1a; //汽车类&#xff1a;宝马X3/X5/X7&#xff1b;发动机类&#xff1a;B48TU、B48//宝马汽车接口 public interface BMWCar {void s…

CSS-基础-MDN文档学习笔记

CSS构建基础 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever MDN中文官网 CSS选择器 选择器是什么 CSS 选择器是 CSS 规则的第一部分&#xff0c;它用来选择HTML元素&#xff0c;选择器所选择的元素&#xff0c;叫做选择器的对象 选择器列表 如果有多…

盘点3款实用的音频文件转文字工具!

在信息爆炸的时代&#xff0c;我们每天都面临着海量的信息输入和输出。其中&#xff0c;音频信息作为一种重要的信息传播方式&#xff0c;如何高效地将其转化为文字&#xff0c;成为许多人和企业迫切的需求。本文将为您盘点几款实用的音频转文字工具&#xff0c;让声音瞬间转化…

通过闭包表解决无限极代理分销

闭包表设计 闭包表是解决分层存储一个简单而又优雅的解决方案&#xff0c;它记录了表中所有的节点关系&#xff0c;并不仅仅是直接的父子关系。   在闭包表的设计中&#xff0c;额外创建了一张节点关系表(空间换取时间)&#xff0c;它包含两列&#xff0c;每一列都是一个指向…

facebook群控如何做?使用静态住宅ip代理有什么好处?

在进行Facebook群控时&#xff0c;ip地址的管理是非常重要的&#xff0c;因为Facebook通常会检测ip地址的使用情况&#xff0c;如果发现有异常的使用行为&#xff0c;比如从同一个ip地址频繁进行登录、发布内容或者在短时间内进行大量的活动等等&#xff0c;就会视为垃圾邮件或…

我的NPI项目之Android USB 系列(一) - 遥望和USB的相识

和USB应该是老朋友了&#xff0c;从2011年接触Android开发开始&#xff0c;就天天和USB打交道了。那时候还有不 对称扁头的usb/方口的usb&#xff0c;直到如今使用广泛的防反插USB3.0 type-C。 但是&#xff0c;一直有一个不是很清楚的问题萦绕在心头&#xff0c;那就是。先有…

Vue3 学习笔记(Day1)

「写在前面」 本文为尚硅谷禹神 Vue3 教程的学习笔记。本着自己学习、分享他人的态度&#xff0c;分享学习笔记&#xff0c;希望能对大家有所帮助。 目录 0 课程介绍 1 Vue3 简介 2 创建 Vue3 工程 2.1 基于 vue-cli 创建 2.2 基于 vite 创建&#xff08;推荐&#xff09; 2.3 …

[word] word正反面打印应该怎么设置呢? #知识分享#学习方法#职场发展

word正反面打印应该怎么设置呢&#xff1f; word文档打印时&#xff0c;如果页数比较多&#xff0c;出于格式要求或为了节省纸张&#xff0c;通常需要正反面打印&#xff0c;那怎么操作正反双面打印呢&#xff1f;通常有两种方法打印。 1、选择“打印”对话框底部的“打印”下…

linux 安装、删除 JTAG驱动

安装 安装驱动需要sudo访问权限&#xff0c;所以得手动安装。 在petalinux安装目录下&#xff1a; 文件的路径。 cd tools/xsct/data/xicom/cable_drivers/lin64/install_script/install_drivers 然后执行文件 install_drivers。 sudo ./install_drivers安装成功。 删除 …

FFmpeg进阶-给视频添加马赛克效果

很多时候为了隐藏视频中的敏感信息如人脸、身份证号、车牌号等,我们会采用马赛克算法对视频帧中的一部分内容进行处理。这里介绍一下如何采用FFmpeg实现马赛克效果。 马赛克效果算法的原理如下: 1.分块处理:首先将图像划分为多个小块或区域 2.像素替换:对于每个小块,算法会将…

sentinel的资源数据指标是如何采集

资源数据采集 之前的NodeSelectorSlot和ClusterBuilderSlot已经完成了对资源调用树的构建, 现在则是要对资源进行收集, 核心点就是这些资源数据是如何统计 LogSlot 作用: 记录异常请求日志, 用于故障排查 public class LogSlot extends AbstractLinkedProcessorSlot<Def…

鸿蒙 状态管理-组件装饰器

前提&#xff1a;基于官网3.1/4.0文档。参考官网文档 基于Android开发体系来进行比较和思考。&#xff08;或有偏颇&#xff0c;自行斟酌&#xff09; 1.概念 Android中使用过Jetpack MVVM框架知道状态管理&#xff0c;包括React前端所使用的状态管理框架&#xff0c;都有所设…

爬虫知识--01

爬虫介绍 # 爬虫的概念&#xff1a; 通过编程技术(python:request,selenium)&#xff0c;获取互联网中的数据(app&#xff0c;小程序&#xff0c;网站)&#xff0c;数据清洗(xpaht&#xff0c;lxml)后存到库中(mysql&#xff0c;redis&#xff0c;文件&#xff0c;excel&#x…