视觉循迹小车(旭日x3派、opencv)

2024-04-08 07:36

本文主要是介绍视觉循迹小车(旭日x3派、opencv),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于旭日x3派的视觉循迹小车,未完全实现,参考:https://developer.horizon.cc/forumDetail/146176819622746404

    • 效果
    • 硬件
    • 视觉循迹原理
    • python代码

效果

硬件

1、旭日x3派(烧录好系统镜像)
2、USB摄像头
3、TB6612
4、小车底盘(直流电机或直流减速电机)

视觉循迹原理

x3派读取摄像头图像,转换成灰度图像,从灰度图像中选择第 120 行(图像的一个水平线),遍历第120行的全部320列,根据像素值小于或大于阈值,将相应的值(0 或 1)添加到 date 列表中。最后根据小于阈值的像素个数和它们的总和来判断黑色赛道的位置,以此调节左右电机的转速实现循迹。

python代码

import Hobot.GPIO as GPIO
import time
import cv2class EYE():def __init__(self):self.video = cv2.VideoCapture(8)  #打开索引为8的摄像头ret = self.video.isOpened()  #判断摄像头是否打开成功if ret:print("The video is opened.")else:print("No video.")codec = cv2.VideoWriter_fourcc( 'M', 'J', 'P', 'G' )   #设置参数self.video.set(cv2.CAP_PROP_FOURCC, codec)self.video.set(cv2.CAP_PROP_FPS, 30)self.video.set(cv2.CAP_PROP_FRAME_WIDTH, 672)self.video.set(cv2.CAP_PROP_FRAME_HEIGHT, 672)# 创建全屏窗口#cv2.namedWindow("Camera Feed", cv2.WND_PROP_FULLSCREEN)#cv2.setWindowProperty("Camera Feed", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)def outmiss(self):_, img = self.video.read()  #从摄像头读取一帧图像img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  #将图像转为灰度img = img[120]   #选择图像的第120行,一共240行。date = []for i in range(320):    #遍历每一列,一共320列if img[i] <= 64:   #如果当前列的像素值小于等于 64,将 1 添加到 date 列表,表示该像素是感兴趣的。date.append(1)elif img[i] > 64:  #如果当前列的像素值大于 64,将 0 添加到 date 列表,表示该像素不感兴趣。date.append(0)n = 0   #用于计算感兴趣的像素数量。  sum = 0   #用于计算感兴趣像素的列索引总和。for i in range(320):if date[i] == 1:sum += i   #如果该列的像素是感兴趣的(即 date[i] 为 1),则更新 sum 和 n。n += 1if n >= 18:return sum / n - 159.5else:return Nonedef off(self):self.video.release()class 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 PID():def __init__(self,KP,KI,KD):self.KP = KPself.KI = KIself.KD = KDself.p1 , self.p2 = 0 , 0#保留一个帧的误差self.i = 0#积累误差初值def naosu(self,miss):if miss != None:self.p1 , self.p2 = self.p2 , miss #替换缓存的误差self.i += missif self.i > 1000:self.i -= 800if self.i < -1000:self.i += 800#积累误差的限制naosu = self.KP * miss + self.KI * self.i + self.KD * (self.p2 - self.p1)#按照公式输出return naosuelif miss == None:#摄像头读空时,根据上一帧的缓存误差正负,来判断现在应该原地左转还是右转if self.p2 >= 0:self.p1 , self.p2 = self.p2 , 1return "r"elif self.p2 < 0:self.p1 , self.p2 = self.p2 , -1return "l"if __name__ == '__main__':try:Ctrl = CTRL(11, 13, 16, 15, 32, 33)  # 设置管脚Eye = EYE()  # 调用视觉模块Pid = PID(0.095,0.001,0.52)#调用PID,传入参数Ctrl.drive(25, 25)  # 小车的始发运动time.sleep(0.5)while True:ms = Eye.outmiss()  # 获取误差ns = Pid.naosu(ms)#获取修正值if ns == "r":#原地转弯的情况Ctrl.drive(20,-20)elif ns == "l":Ctrl.drive(-20,20)else:#限制修正值,保证不超过PWM上下限if ns > 18:ns = 18if ns < -18:ns = -18Ctrl.drive(25+ns, 25-ns)  # 小车的始发运动# 添加代码来显示摄像头捕获的图像_, frame = Eye.video.read()cv2.imshow("Camera Feed", frame)time.sleep(0.2)if cv2.waitKey(1) & 0xFF == ord('q'):breakfinally:Ctrl.stop()Ctrl.clean()Eye.off()cv2.destroyAllWindows()

这篇关于视觉循迹小车(旭日x3派、opencv)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/884954

相关文章

opencv实现像素统计的示例代码

《opencv实现像素统计的示例代码》本文介绍了OpenCV中统计图像像素信息的常用方法和函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 统计像素值的基本信息2. 统计像素值的直方图3. 统计像素值的总和4. 统计非零像素的数量

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模

前言 本系列教程旨在使用UE5配置一个具备激光雷达+深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2和UE5仿真的通讯,达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博客Nav2代价地图实现和原理–Nav2源码解读之CostMap2D(上)-CSDN博客往期教程: 第一期:基于UE5和ROS2的激光雷达+深度RG

opencv 滚动条

参数介绍:createTrackbar( trackbarname , "hello" , &alpha_slider ,alpha_max ,  on_trackbar )  ;在标签中显示的文字(提示滑动条的用途) TrackbarName创建的滑动条要放置窗体的名字 “hello”滑动条的取值范围从 0 到 alpha_max (最小值只能为 zero).滑动后的值存放在

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

计算机视觉工程师所需的基本技能

一、编程技能 熟练掌握编程语言 Python:在计算机视觉领域广泛应用,有丰富的库如 OpenCV、TensorFlow、PyTorch 等,方便进行算法实现和模型开发。 C++:运行效率高,适用于对性能要求严格的计算机视觉应用。 数据结构与算法 掌握常见的数据结构(如数组、链表、栈、队列、树、图等)和算法(如排序、搜索、动态规划等),能够优化代码性能,提高算法效率。 二、数学基础

树莓派5_opencv笔记27:Opencv录制视频(无声音)

今日继续学习树莓派5 8G:(Raspberry Pi,简称RPi或RasPi)  本人所用树莓派5 装载的系统与版本如下:  版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下: 今天就水一篇文章,用树莓派摄像头,Opencv录制一段视频保存在指定目录... 文章提供测试代码讲解,整体代码贴出、测试效果图 目录 阶段一:录制一段

Verybot之OpenCV应用三:色标跟踪

下面的这个应用主要完成的是Verybot跟踪色标的功能,识别部分还是居于OpenCV编写,色标跟踪一般需要将图像的颜色模式进行转换,将RGB转换为HSV,因为对HSV格式下的图像进行识别时受光线的影响比较小,但是也有采用RGB模式来进行识别的情况,这种情况一般光线条件比较固定,背景跟识别物在颜色上很容易区分出来。         下面这个程序的流程大致是这样的:

Verybot之OpenCV应用二:霍夫变换查找圆

其实我是想通过这个程序来测试一下,OpenCV在Verybot上跑得怎么样,霍夫变换的原理就不多说了,下面是程序: #include "cv.h"#include "highgui.h"#include "stdio.h"int main(int argc, char** argv){cvNamedWindow("vedio",0);CvCapture* capture;i