旭日x3派目标跟随小车
目标跟随小车(yolov5、安全帽识别)
- 前言
- 最终结果
- 接线
- 实现
前言
上板运行的后处理使用cython封装了,由于每个版本的yolo输出的形状不一样,这里只能用yolov5-6.2这个版本。
①训练自己的模型并部署于旭日x3派参考:
https://blog.csdn.net/m0_71523511/article/details/136546588/部署官方权重文件
https://blog.csdn.net/m0_71523511/article/details/136823320/部署自己训练的安全帽识别权重文件
②通过40pin引脚驱动减速电机参考:
https://blog.csdn.net/m0_71523511/article/details/136722608/视觉循迹小车
最终结果
跟随戴着安全帽的人前进,当距离过近时会停车(没有使用深度相机,无法直接获取距离信息,简单根据检测框与图像的比值来确定是否停车),检测不到安全帽时也会停车。根据目标(在这里是目标框中心的 x 坐标)与设定值(320)之间的偏差计算(PID)得到相应占空比驱动差速车轮。
接线
这里使用物理引脚编号:
旭日x3派连接TB6612驱动电机:
11、13引脚接AIN1、AIN2;15、16引脚接BIN1、BIN2;32引脚接PWMA;33引脚接PWMB引脚。TB6612的VCC接3.3v,VM和STBY接5V,有条件的VM可以接7-12V;AO1、AO2接左电机的正负极;BO1、BO2接右电机的正负极。
如果想把小车弄好的,需要能输出3A电流供电,可以使用18650电池,输出最好在7V-12V,3A。这里参考:
https://developer.horizon.cc/forumDetail/146176819622746404
实现
经过前面的步骤得到bin文件之后,需要将如下文件放入板端(在前言的参考博客中有下载链接)
新建一个视频推理py文件:
import numpy as np
import cv2
import os
from hobot_dnn import pyeasy_dnn as dnn
from bputools.format_convert import imequalresize, bgr2nv12_opencv
import Hobot.GPIO as GPIOimport lib.pyyolotools as yolotoolsclass CTRL():def __init__(self, in1, in2, in3, in4, pa, pb):GPIO.setmode(GPIO.BOARD)GPIO.setwarnings(False)GPIO.setup(in1, GPIO.OUT)GPIO.setup(in2, GPIO.OUT)GPIO.setup(in3, GPIO.OUT)GPIO.setup(in4, GPIO.OUT)self.in1 = in1self.in2 = in2self.in3 = in3self.in4 = in4self.PWMA = GPIO.PWM(pa, 48000)self.PWMB = GPIO.PWM(pb, 48000)def drive(self, FL, FR):if FL >= 0:GPIO.output(self.in3, GPIO.HIGH)GPIO.output(self.in4, GPIO.LOW)elif FL < 0:GPIO.output(self.in4, GPIO.HIGH)GPIO.output(self.in3, GPIO.LOW)if FR >= 0:GPIO.output(self.in1, GPIO.HIGH)GPIO.output(self.in2, GPIO.LOW)elif FR < 0:GPIO.output(self.in2, GPIO.HIGH)GPIO.output(self.in1, GPIO.LOW)self.PWMA.ChangeDutyCycle(abs(FR))self.PWMB.ChangeDutyCycle(abs(FL))self.PWMA.start(abs(FR))self.PWMB.start(abs(FL))def stop(self):GPIO.output(self.in1, GPIO.LOW)GPIO.output(self.in2, GPIO.LOW)GPIO.output(self.in3, GPIO.LOW)GPIO.output(self.in4, GPIO.LOW)self.PWMA.ChangeDutyCycle(0)self.PWMB.ChangeDutyCycle(0)self.PWMA.start(0)self.PWMB.start(0)def clean(self):self.PWMB.stop()self.PWMA.stop()GPIO.cleanup()class PIDController():def __init__(self,KP,KI,KD,setpoint):self.KP = KPself.KI = KIself.KD = KDself.setpoint = setpointself.prev_error = 0self.integral = 0def update(self,current_value):error = self.setpoint - current_valueself.integral += errorderivative = error - self.prev_erroroutput = self.KP * error + self.KI *self.integral + self.KD * derivativeself.prev_error = errorreturn outputdef get_hw(pro):if pro.layout == "NCHW":return pro.shape[2], pro.shape[3]else:return pro.shape[1], pro.shape[2]def format_yolov5(frame):row, col, _ = frame.shape_max = max(col, row)result = np.zeros((_max, _max, 3), np.uint8)result[0:row, 0:col] = framereturn result# 加载模型和设置参数
model_path = 'hat_yolov5_6.2_2.bin'
classes_name_path = 'coco_classes.names'
models = dnn.load(model_path)
model_h, model_w = get_hw(models[0].inputs[0].properties)
print("Model Height:", model_h, "Model Width:", model_w)thre_confidence = 0.4
thre_score = 0.25
thre_nms = 0.45
colors = [(255, 255, 0), (0, 255, 0), (0, 255, 255), (255, 0, 0)]# 打开摄像头
cap = cv2.VideoCapture(8) # 使用第一个摄像头(如果有多个摄像头,可能需要更改参数)
Ctrl = CTRL(11, 13, 16, 15, 32, 33) # 设置管脚
pidController = PIDController(KP=0.12,KI=0.001,KD=0.12,setpoint=320)
Ctrl.drive(25, 25) # 小车的始发运动# 主循环:读取帧,进行目标检测,显示结果
while True:ret, frame = cap.read() # 读取一帧图像if not ret:print("Error: Couldn't capture frame")breakinputImage = format_yolov5(frame)img = imequalresize(inputImage, (model_w, model_h))nv12 = bgr2nv12_opencv(img)t1 = cv2.getTickCount()outputs = models[0].forward(nv12)t2 = cv2.getTickCount()outputs = outputs[0].buffer#print('Inference time: {0} ms'.format((t2 - t1) * 1000 / cv2.getTickFrequency()))image_width, image_height, _ = inputImage.shapefx, fy = image_width / model_w, image_height / model_ht1 = cv2.getTickCount()class_ids, confidences, boxes = yolotools.pypostprocess_yolov5(outputs[0][:, :, 0], fx, fy,thre_confidence, thre_score, thre_nms)t2 = cv2.getTickCount()#print('Post-processing time: {0} ms'.format((t2 - t1) * 1000 / cv2.getTickFrequency()))with open(classes_name_path, "r") as f:class_list = [cname.strip() for cname in f.readlines()]for (classid, confidence, box) in zip(class_ids, confidences, boxes):color = colors[int(classid) % len(colors)]cv2.rectangle(frame, box, color, 2)cv2.rectangle(frame, (box[0], box[1] - 20), (box[0] + box[2], box[1]), color, -1)#cv2.putText(frame, str(classid), (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, .5, (0, 0, 0))cv2.putText(frame, class_list[classid], (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0))cv2.imshow('frame', frame) # 显示帧##########################################################################################################################car_logicalnum_detection = len(boxes)if num_detection == 0:print("no_object_stop")Ctrl.stop()else:if classid == 0:x1,y1 = box[0],box[1]x2,y2 = box[0] + box[2],box[1] + box[3]kuang_area = (x2-x1) * (y2-y1)input_area = 409600bizhi = kuang_area / input_areaif bizhi > 0.1:print("too_close_stop")Ctrl.stop()else:x3 = (x2+x1)/2print("weizhi",x3)#direct_control#if x3 < 300:#print("left")#Ctrl.drive(20,-20)#elif x3 > 280 and x3 < 320:#print("zhixian")#Ctrl.drive(25,25)#else:#print("right")#Ctrl.drive(-20,20)#pid_controlpid_output = pidController.update(x3)if pid_output > 11:pid_output = 11if pid_output < -11:pid_output = -11Ctrl.drive(25+pid_output, 25-pid_output)else:Ctrl.stop()print("hat_stop")#########################################################################################################################if cv2.waitKey(1) & 0xFF == ord('q'): # 按下 'q' 键退出循环Ctrl.stop()break# 释放资源并关闭窗口
cap.release()
cv2.destroyAllWindows()
如果模型输出是 1×25200×7 ,代码直接复制就能用。
查看模型结构图网址:https://netron.app/ ,直接打开onnx文件拉到最后就可以看到模型输出:
相关文章:

旭日x3派目标跟随小车
目标跟随小车(yolov5、安全帽识别) 前言最终结果接线实现 前言 上板运行的后处理使用cython封装了,由于每个版本的yolo输出的形状不一样,这里只能用yolov5-6.2这个版本。 ①训练自己的模型并部署于旭日x3派参考: http…...

金潮实业邀您参观2024长三角快递物流展览会
展会介绍 本届展会致力于全面展示快递物流上下游领域的创新解决方案,涵盖快递物流供应链、智能装备、AGV机器人与无人搬运、自动识别、智慧仓储、智慧物流、无人配送、新能物流车及商用车、绿色包装、冷链物流等各个环节,为促进行业合作共融,…...
【超细完整版】C# WebService 通过URL生成WSDL文件和DLL文件 【生成篇】
先学生成,再看调用哦 【超细完整版】C# 获取WebService所有方法并调用 【调用篇】 目的 支持通过web url (自适应“?wsdl”的有无) 生成.wsdl文件 和 .dll文件 实现 将通过一个类的三部分来实现这些功能 获取url中的ClassName (GetClassNameFromUrl&a…...

申请公派访问学者难不难?
申请公派访问学者,对许多人来说是一项具有挑战性的任务。这需要充分的准备和计划,以确保申请能够顺利进行并最终获得批准。下面将探讨一些关于申请公派访问学者的问题以及应对策略。 首先,申请公派访问学者需要有一个明确的研究计划或合作意向…...

关于汽车中网改装需要报备吗?(第二天)
车联网改造需要申报吗? 今天2022年10月20日,小编就给大家介绍一下车联网改装是否需要申报的相关知识。 让我们来看看。 汽车格栅改装无需申报。 这种年检可以直接通过。 您不必担心,因为汽车格栅对于实车的外观来说并不陌生,因此…...

面试官:对于 Java 中多态的理解是什么?
面试官:对于 Java 中多态的理解是什么? 题目 面试官:对于 Java 中多态的理解是什么? 推荐解析 1.父类的引用指向子类的对象 子类重写父类的方法:子类可以继承父类的方法,并对其进行重写。当通过父类的…...

JUC-1M/75±5°超小型密封温度继电器 体积小、重量轻、控温精度高 JOSEF约瑟
JUC系列温度继电器 JUC-1M型超小型密封温度继电器 JUC-2M型超小型密封温度继电器 继电器JUC-027M/2531H-III-G温度继电器 JUC-1M 10C常开温度继电器 JUC-1M 105C温度继电器 用途 小型温控开关系接触感应式密封温度继电器,具有体积小、重量轻、控温精度高等特点&…...
filebeat 配置
主要就是证书的配置 ca_trusted_fingerprint: 产生方式 openssl x509 -fingerprint -sha256 -in /etc/elasticsearch/certs/http_ca.crt 产生的结果 SHA256 Fingerprint 中的冒号 替换掉就是我们想要的结果 ssl: enabled: true ca_trusted_fingerprint: "…...

Qt教程 — 3.5 深入了解Qt 控件:Display Widgets部件(1)
目录 1 Display Widgets简介 2 如何使用Display Widgets部件 2.1 QLabel组件-显示图像或文本 2.2 QCalendarWidget组件-日历简单的使用 2.3 QLCDNumber组件-控件作时钟的显示 2.4 QProgressBar组件-模拟手机电池充电 2.5 QFrame组件-绘制水平/垂直线 Display Widgets将分…...

网络安全框架和云安全参考架构介绍
目录 一、网络安全框架 1.1 概述 1.2 IATF框架 1.2.1 框架来源 1.2.2 框架结构图 1.2.3 框架内容 1.2.3.1 人(People) 1.2.3.2 技术(Technology) 1.2.3.3 操作(Operation) 1.3 NIST网络安全框架 …...

360企业安全浏览器兼容模式显示异常某个内容不显示 偶发现象 本地无法复现情况js
360企业安全浏览器兼容模式显示异常 ,现象测试环境频发 ,本地连测试无法复现,线上反馈问题。 出现问题的电脑为windows且使用360企业安全浏览器打开兼容模式可复现 复现过程: 不直接点击超链接跳转页面 ,登录后直接通…...
JVM常见启动参数
目录 内存参数设置 垃圾收集 内存溢出 其他杂项 总结 java虚拟机(JVM)的启动参数可以用来调整其行为、性能和资源分配。以下是一些常见的JVM启动参数: 内存参数设置 初始化堆内存以满足应用程序需求是最常见的与性能相关的实践之一。 …...
单元测试、集成测试、系统测试区别
一、测方法不同 1、单元测试属于白盒测试范畴。 2、集成测试属于灰盒测试范畴。 3、系统测试属于黑盒测试范畴。 二、考察范围不同 1、单元测试主要测试单元内部的数据结构、逻辑控制、异常处理等。exception handling 2、集成测试主要测试模块之间的接口和接ロ数据传递关…...

NIVision-相机图像采集
应用场景 上位机与工业相机通讯,控制相机抓取图像。 工业相机的通讯接口大多为USB口或网口。 USB口则直接将通讯线缆插入上位机USB端口,打开MAX中设备与接口一栏可以看到电脑给相机分配的资源名称;网口则需要将网线连接相机和上位机…...

【vue-小知识】var、let 和 const之间的区别
文章目录 结论1、重复定义变量名var:允许重复定义变量名let和const:不可以重复定义变量名 2、修改值var:允许修改值let:允许修改值const:不允许修改值,会报错 3、变量提升var : 支持变量提升let和const&…...
24.3 分布式综合应用
24.3 分布式综合应用 1. 分布式事务1.1 分布式事务1.2 分布式事务方案1. 2pc2. 其他方案1.3 Seata分布式事务框架:基于2pc1. 简介2. 启动seata服务1.4 微服务事务案例分析1. 代码分析2. 基于Seata改造2. 分布式锁2.1 简介1. redis实现...
Android学习进阶
UI组件进阶 使用RecyclerView和Adapter显示列表数据 RecyclerView是Android开发中用于显示列表数据的一个灵活且高效的组件。与其前身ListView相比,RecyclerView引入了更加复杂的布局排列和动画支持,使得创建高度定制化的列表和网格布局变得更加简单。…...

“低代码+平台”:驱动企业数字化转型与创新的新引擎
“低代码平台”作为一种新兴的软件开发范式,正逐渐成为企业快速响应市场变化、优化业务流程、提升数字化水平的重要手段。它的价值在于,将传统软件开发的复杂性大大降低,赋予了非技术人员或轻量级开发者快速构建应用的能力,并能灵…...
python代码截取任意页的pdf
python代码把截取任意页的pdf:比如你有一个pdf文件1.pdf,共有30页,但是,你想把其中的10-20页截取出来保存成新的pdf,名为2.pdf,可以使用下面代码 from PyPDF2 import PdfReader, PdfWriter# 输入和输出文件…...
速盾:cdn加速后真实ip会暴漏吗?
CND(内容分发网络)是一种通过将内容分发到全球各地的服务器来加速网站访问的技术。当用户请求访问一个网站时,CDN会将静态资源(如图片、视频、脚本等)缓存在离用户最近的服务器上,从而提高网站的加载速度。…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...

PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...

C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...
虚幻基础:角色旋转
能帮到你的话,就给个赞吧 😘 文章目录 移动组件使用控制器所需旋转:组件 使用 控制器旋转将旋转朝向运动:组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转:必须移动才能旋转,不移动不旋转控制器…...