-
2020-07-10 09:35:53
恩智浦智能车摄像头循迹部分
对于恩智浦智能车竞赛已经举行了14届,从以往的电磁车已经逐渐转变成了用摄像头进行循迹。与电磁循迹对比,摄像头拥有着诸多优势,但摄像头对于很多新手入门来说却是比较困难的。下面将给新手介绍我们对摄像头循迹部分的处理。大家都知道,单片机从摄像头采集到数据后,必须对图像进行相应的二值化(即0,1)后才方便对图像进行处理。在得到二值化图像后如何进行处理并且进行巡线呢? 一获取中线
for(j=MT9V032_H-5;j>20;j--) { for(i = 0 ;i <=MT9V032_W/2;i++) { if(i==MT9V032_W/2-2) { left=MT9V032_W/2; break; } if(img[j][MT9V032_W/2-i] <= 10 && img[j][MT9V032_W/2-i-1] <= 10) { left = i;break;} } for(i = 0 ;i < MT9V032_W/2;i++) { if(i==MT9V032_W/2-2) { right=MT9V032_W/2; break; } if(img[j][MT9V032_W/2+i] <= 10 && img[j][MT9V032_W/2+1+i] <= 10) { right = i;break;} } if(j<30) midder[j]=MT9V032_W/2-(left-right)*1.5; else midder[j]=MT9V032_W/2-(left-right); minder=minder+(MT9V032_W/2-midder[j]); }
获取中线的原理在于图像的中线下方往两边进行找黑线,找到黑线后进行记录。并且两边的黑线到中点的距离进行作差,即可得到对应该横的中点值,依次往上进行寻找中线,最后把所有中点与中线的误差积累在minder变量中即可得到车子里中线的偏差。 但这样获得中线的方式存在一个问题:当车模快在过弯时摄像头拍摄的位置将不会是赛道的方向,拍摄的位置可能为赛道的外侧,那么计算中线的位置将会出现问题。因此我们需要引入一个结束点,在查找中线时检测到巡线位置已经到达边缘时暂停结束巡线详细代码如图
if(midder[j]<10||midder[j]>MT9V032_W-10||j<21) { if(j>60) minder=minder*j*3.4; else minder=minder*j*0.03; if(minder>2000)minder=2000; if(minder<-2000)minder=-2000; break; }
具体的比例系数需要大家对自己的车模进行一一的调整。
更多相关内容 -
摄像头循迹小车
2016-01-03 20:34:50智能循迹小车的设计与制作 摘要介绍了一种智能循迹小车的制作方法,给出了控制系统的硬件设计和软件设计。控制 系统的硬件电路部分主要包括控制器。 -
基于stm32f103摄像头循迹.zip
2021-04-13 19:54:27摄像头0v7670传入的数据通过二值化把道路检测出来并进行寻迹 -
OV7670摄像头循迹 程序源码
2017-07-25 23:36:16该代码是我博客中的源码,需要者自取。 -
摄像头循迹
2017-11-13 17:16:09摄像头循迹,基于stm32的摄像头循迹,能够寻找黑线并且获得位置 -
OV7670摄像头循迹V1.0
2019-04-09 23:58:18通过OV7670摄像头对黑白线识别检测进行循迹,注意:该程序用的是步进电机。 -
CMOS摄像头循迹例程
2015-08-12 09:49:15本篇说明文档介绍了基于 RL78/G13 单片机的 CMOS 摄像头图像采集处理程序 的编写。 -
PID详解3(摄像头循迹分析)
2021-03-31 16:25:05PID详解3(摄像头循迹分析) 看了那么多成功的案例和大佬们的分享、讲解,终于轮到我们自己来设计PID了。 首先需要分析的是,想要用PID,我们得先知道,我们需要通过传感器拿到哪些参数,我们处理后要得到的是什么参数...PID详解3(摄像头循迹分析)
看了那么多成功的案例和大佬们的分享、讲解,终于轮到我们自己来设计PID了。
首先需要分析的是,想要用PID,我们得先知道,我们需要通过传感器拿到哪些参数,我们处理后要得到的是什么参数,然后才是设计PID控制器。这个很重要,毕竟“方向”才是最重要的。在很多以后的工作中,也一定要先弄明白方向和目的,避免犯迷糊。
分析:
- 我们通过PWM波控制车轮速度,通过两轮差速完成转向,所以我们需要的参数是赋给两轮的车速,但又不是速度本身,而是 T I M S e t C o m p a r e x ( T I M x , a x 1 ) TIM_SetComparex(TIMx,ax1) TIMSetComparex(TIMx,ax1)中的这个ax1的值。它与车速之间的关系并不是很明确。这里我们来计算一下具体的关系,不然就是一个隐患:
ps:今天是见识到CSDN的鱼龙混杂了。。。看到好多个概念错误还写的贼自信,到处查资料,去伪存真,得到我下面的结论,应该是没什么问题了。
PWM在初始化时,需要两个参数自主设定: 1.TIM_Period:=ARR 定时器周期, 也就是当计数器内的值变化到该值时,相关事件标志位。 2.TIM_Prescaler:定时器预分频, 时钟源内部时钟经过这个分频处理才是定时器的时钟 在通用定时器中,内部时钟72MHZ,所以定时器内部时钟 CLK = 72M / (TIM_Prescaler + 1) Hz 也就是计数器每1s该时钟增加CLK次 然后计数器内数字变化成为TIM_Period后,结束。 For example: if TIM_Prescaler = (7200 - 1) => CLK = 72M / 7200 = 10K if TIM_Period = 5000-1 (from 0 to 5000 = 5000-1) ==>> 定时为0.5s(周期)的定时器(5000*(1/10KHz))
周期: T = ( T I M P e r i o d + 1 ) ∗ ( T I M P r e s c a l e r + 1 ) 72 M T = \frac{(TIM_Period + 1)*(TIM_Prescaler+1)}{72M} T=72M(TIMPeriod+1)∗(TIMPrescaler+1)
在此给定的定时器之上,我们再调用 function:TIM_SetComparex(TIMx,CCRx)
来看看波形:
首先了解一下两个参数:
TIM_OCPolarity 和TIM_OCInitTypeDef.TIM_OCMode :2 .1 TIM_OCPolarity = TIM_OCPolarity_High,
高电位为有效电平。
2 .2 TIM_OCPolarity = TIM_OCPolarity_low,
低电位为有效电平。
1 .1 若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM1时:
在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;
在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平1 .2 若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM2时:
在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;
在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平这里我找到一个图:显然这里是
TIM_OCPolarity_High、TIM_OCMode_PWM2;
和
TIM_OCPolarity_low、TIM_OCMode_PWM1初始为低电平,未到设定值时时低电平
这个图很容易让我们知道PWM的形成了,以及占空比的概念也很形象了。
占空比D = (t2 - t1)/t2 ,但这里我们并不能直接得到时间轴上的值,因此我们从比例相同的角度,用计数值来表示这个量。D = 1 − ( C C R / ( A R R + 1 ) D = 1 - (CCR/(ARR+1) D=1−(CCR/(ARR+1)
~~~~若采用High PWM1或Low 2,图有所变化
D = C C R / ( A R R + 1 ) D = CCR/(ARR+1) D=CCR/(ARR+1)
D的作用:
很多人抓到PWM都知道,我靠控制占空比控制车速,但其实很多人都不知道为什么可以控制,都是似懂非懂罢了。
这里其实要从电机角度来,其实占空比最终的目的是改变电机的电枢电压。
V l = V ∗ D V_l= V * D Vl=V∗D
所以到底这个compare值和车速的数学表达式关系到底是什么很难确定,不同的电机、不同的环境都有影响,所以大家还是借助自己手上的电机实体进行测试吧。。。设计PID控制器
磨磨蹭蹭这么久,总算到了设计PID的时候,为了上面这一段PID真的是花了不少时间。。其实一开始就看手册反倒不会这么麻烦,都怪我太相信博文了。。。
分析
我们来分析这个摄像头传感器的PID巡线:
err是什么:巡线为目标,则轨迹下起点与图像中线的距离可以作为err。
P控制器
V = K P ∗ e r r ( t ) V =K_P*err(t) V=KP∗err(t)
D控制器
V V V+= K D ∗ ( e r r [ t ] − e r r [ t − 1 ] ) K_D*(err[t]-err[t-1]) KD∗(err[t]−err[t−1])
I控制器
A L L e r r ALLerr ALLerr+=err(t)$$
V V V+= K I ∗ ( A L L e r r ) K_I*(ALLerr) KI∗(ALLerr)最后的
TIM_sercmparex(TIMx,compare1)
TIM_sercmparey(TIMx,compare2)compare1 = fixed + V
compare2 = fixed - V具体实操
xxx-4.1
完成理论分析4.1-
完成理论分析下一步我们就要开始实际设计编程了。
这里我们采用的是OV7725摄像头作为传感器。
-
摄像头循迹openmv.zip
2021-07-26 23:26:45STM32F1 摄像头寻迹 寻红线 openmv串口通讯 -
pid摄像头循迹(opencv和openmv)
2021-06-12 21:42:45用摄像头进行循迹的方法参考 之前用openmv做了一个循迹小车,效果还不错,实验室里做了汇报,这里也同步分享一下制作的一些细节。 小车灰常简陋,当时硬件水平有限,轻喷>_< csdn视频放不出来,只能放已经...pid摄像头循迹(opencv和openmv)
用摄像头进行循迹的方法参考
去年用openmv做了一个循迹小车,效果还不错,实验室里做了汇报,这里也同步分享一下制作的一些细节。
小车灰常简陋,当时硬件水平有限,轻喷>_<
csdn视频放不出来,只能放已经投稿的视频,这里就不展示了叭。
运行效果其实和openmv官方教程给的视频里小车效果类似,大家可以作为参考。硬件选型方面
- 稳压模块x2
- 9v锂电池x1
- openmv
- 减速电机(6v 280rpm)
- 万向轮
- L298N直流电机驱动模块
(插一下,这里的稳压可以稳压到7V和3.3V,L298N本身可以将电压稳压到5V)
软件思路
如上图所示,分为图像预处理、线性拟合以及PID控制转速。一.图像预处理:
1.按阈值取二值化 (可以加入中值滤波或高斯滤波)
2.腐蚀操作 (去除噪点)
3.膨胀操作(可有可无)
因为openmv的算力有限,若是同时加上了膨胀和腐蚀操作,运行循迹程序时帧率会变得很低(可能低于15fps)。代码部分
图像预处理在openmv和opencv中均有现成的库函数,直接调用即可。
1.openmv:img.dilate(2) #膨胀 img.erode(2)# 腐蚀 img = sensor.snapshot().binary([THRESHOLD]) # 按阈值二值化
2.opencv:
mask=cv2.inRange(img,black_min,black_max) #二值化 kernel=np.ones((3,3),np.uint8) #半径大小 erode=cv2.morphologyEx(mask,cv2.MORPH_ERODE,kernel)# 腐蚀
腐蚀膨胀 示意图如下所示:
二.线性拟合
这里的线性拟合采用的是最小二乘法进行拟合,遍历所有像素点,复杂度为O(n²)
openmv有现成的库函数:line = img.get_regression([(100,100,0,0,0,0)], robust = True)
官网给的解释是快速鲁棒线性回归
可以直接返回得到拟合的直线对象参考文档:https://docs.singtown.com/micropython/zh/latest/openmvcam/library/omv.image.html?highlight=get_regression#image.get_regression
官方文档介绍:
opencv线性拟合:
由于我没有找到相关的线性拟合函数,于是自己写了一个函数:
传入参数img为二值化图像,result为原图。# 线性拟合 def liner(img,result): # print(img) n=[len(img[:,0]),len(img[0,:])] # print(n,'n') (x_point,y_point)=np.nonzero(img) if len(x_point)<2: return 0 f1 = np.polyfit(x_point, y_point,1) p1 = np.poly1d(f1) point1=(int(p1(0)),0) point2=(int(p1(n[0])),n[0]) print(point2,point1) result = cv2.line(result, (int(n[1]/2),0) , (int(n[1]/2),n[0]), (0, 0, 255),2) result=cv2.line(result,point1,point2,(0,255,0),2) cv2.imshow('inside',result) print(f1) return [n[1]/2-p1(n[0]),f1[1]]
返回值为拟合的直线与图像下方中点的距离和函数的k值
运行效果如下:
从左到右分别为:
1.腐蚀后的图像 2.拟合效果图像 3.二值化图像实际在树莓派上运行时,帧率也比较高,拟合效果也比较好。
可以看到有81帧每秒,运行速度较为不错。三.PID控制
pid算法对于熟悉控制算法来说已经是非常常见的算法了,这里就不过多介绍,直接贴代码:
(这里pid的调整输入为角度theta和距离rho)import time from math import pi, isnan # 定义pid class PID: _kp = _ki = _kd = _integrator = _imax = 0 _last_error = _last_derivative = _last_t = 0 _RC = 1/(2 * pi * 20) # 车身参数 def __init__(self, p=0, i=0, d=0, imax=0): self._kp = float(p) # 比例 self._ki = float(i) # 积分 self._kd = float(d) # 微分 self._imax = abs(imax) self._last_derivative = float('nan') def get_pid(self, error, scaler): tnow = time.time()*1000 # 当前时间,单位为ms dt = tnow - self._last_t output = 0 if self._last_t == 0 or dt > 1000: dt = 0 self.reset_I() # 防止积分系数过大 self._last_t = tnow delta_time = float(dt) / float(1000) output += error * self._kp if abs(self._kd) > 0 and dt > 0: if isnan(self._last_derivative): derivative = 0 self._last_derivative = 0 else: derivative = (error - self._last_error) / delta_time derivative = self._last_derivative + \ ((delta_time / (self._RC + delta_time)) * \ (derivative - self._last_derivative)) self._last_error = error self._last_derivative = derivative output += self._kd * derivative output *= scaler if abs(self._ki) > 0 and dt > 0: self._integrator += (error * self._ki) * scaler * delta_time if self._integrator < -self._imax: self._integrator = -self._imax elif self._integrator > self._imax: self._integrator = self._imax output += self._integrator return output def reset_I(self): self._integrator = 0 self._last_derivative = float('nan')
一些问题:
newimg=155*np.ones(shape,dtype = np.uint8)
在转化时注意类型转化
img=cv2.resize(img,(480,640))
cv2.inRange %用于按阈值取二值化的函数:
关于控制直流电机:
openmv中控制电机可以采用定时器输出pwm来控制电机
而在树莓派中可以调用RPi.GPIO库或pigpio库来实现。
以RPi.GPIO库为例:p = GPIO.PWM(channel, frequency) p.start(dc) # dc 代表占空比(范围:0.0 <= dc <= 100.0) p.ChangeFrequency(freq) # freq 为设置的新频率,单位为 Hz p.ChangeDutyCycle(dc) # 范围:0.0 <= dc <= 100.0
-
基于STM32F1系列的OV7725摄像头初步使用(用于摄像头循迹)
2021-01-06 09:17:35由于OV7725对于工作频率的要求较高,因此使用带FIFO的摄像头模块。代码参考自正点原子官方。 OV7725资源 引脚说明 以下时关于十八个引脚的说明(来自正点原子的用户手册) 其中,OV_SCL和OV_SDA组成SCCB,即串行... -
用摄像头循迹的智能车的硬件系统设计
2015-05-01 11:36:47用摄像头循迹的智能车的硬件系统设计,主要涉及硬件设计 -
51黑论坛_摄像头循迹V1.0_摄像头_
2021-09-29 03:19:41摄像头轨迹搜索,寻找摄像头的轨迹方位,找到摄像头的位置。 -
智能车摄像头循迹图像爬梯算法
2022-04-21 13:24:56关于电磁循迹方面的可以加群:789127261咨询 算法主要是先把CMOS灰白摄像头传感器所采集到的图像数据二值化处理。主要使用的是优化大津法(但也没优化多少)。主要大津法之类的遍历的数据有点多,运行速度会有点慢。... -
摄像头判断,简单的进行摄像头循迹(全部通用)
2021-05-24 21:23:21摄像头判断,简单的进行摄像头循迹 -
电赛练习之摄像头循迹单轮驱动小车
2021-07-24 15:43:57因为ministm32板载资源有限,摄像头模块需要占用大量的IO口,同时调试过程中需要用到LCD,因此我们使用了ministm32+c8t6串口通讯共同控制小车。 我们使用的是正点原子官方的ov7725,默认输出是QVGA的RGB图像,但为了...一.要求
成品展示
二.实现思路
因为ministm32板载资源有限,摄像头模块需要占用大量的IO口,同时调试过程中需要用到LCD,因此我们使用了ministm32+c8t6串口通讯共同控制小车。
我们使用的是正点原子官方的ov7725,默认输出是QVGA的RGB图像,但为了加速处理的速度,我们将画面进行了裁剪,变成了160*160,且因为我们只需要道路的二值化图像,因此我们直接配置ov7725寄存器,使其输出灰度图像,修改位置和内容放在下图。
在得到灰度图后,设置合适的阈值,将图像二值化。在寻找阈值的过程中我们看到了很多动态寻找阈值的方法,但根据实际情况分析我们的赛道并不需要动态阈值,通过PS对赛道图片处理我们得到了相对合适的阈值。
得到图片后我们对其进行膨胀处理,因为160160的图片对我们而言仍然大,我们以十个像素为步数将画面分割成1616个方格,并根据方格内黑白像素的占比将其二值化为16*16的二值化图像。
接下来是寻找赛道边界。
我们从画面最左边向右寻找,当找到一个点从白色跳变成黑色,则它就是左边界,再从左边界继续向右寻线,当找到一个从黑色跳变为白色的点,就是右边界。将左右边界相加并除以二得到赛道中心值,计算中心值与画面正中央的值相减,得到偏差值,小于0则应左转,反之右转,根据偏差值的大小映射到舵机上,动态控制偏转角的大小,即偏差大小车转的角度就大,偏差小小车转的角度就小。工程文件
-
摄像头循迹智能平衡小车.doc
2021-10-12 19:44:08摄像头循迹智能平衡小车.doc -
摄像头循迹智能平衡小车.docx
2021-09-28 00:40:25摄像头循迹智能平衡小车.docx -
基于摄像头循迹的电子设计竞赛论文
2018-05-23 09:53:20摘要 本系统以设计题目的要求为目的,采用STM32F103ZET6单片机为控制核心,...通过利用ov7725摄像头探测前方的黑线,将采集到的信息传回STM32单片机,对读出的数据进行二值化处理,加上阈值后可以进行循迹使用,通... -
openMV摄像头循迹小车
2021-10-26 08:32:59主控MSP430F5529,电机驱动模块L298N,openMV摄像头 一、总体思路 使用openMV线性回归,然后使用pid输出,使用串口发送到MSP430,在经过处理输出PWM到车轮,实现循迹 二、openMV代码 THRESHOLD = (0, 20, -128,... -
基于STM32的智能小车摄像头循迹系统方案.doc
2021-09-30 12:45:15基于STM32的智能小车摄像头循迹系统方案.doc -
基于CMOS摄像头循迹的智能车控制系统设计.pdf
2021-09-07 23:58:15基于CMOS摄像头循迹的智能车控制系统设计.pdf -
基于CMOS摄像头循迹的四轮智能车控制系统设计.pdf
2021-09-09 23:14:44基于CMOS摄像头循迹的四轮智能车控制系统设计.pdf -
OV7725摄像头循迹小车
2018-09-13 17:07:49循迹小车,OLED带屏,摄像头为OV7725,MCU为STM32F1, -
OV7725摄像头和STM32循迹小车.zip
2019-08-20 12:31:01利用 STM32单片机和oV7725摄像头实现小车的智能循迹。使用摄像头对路况信息进行收集,利用STM32进行处理数据,然后进行二值化处理,利用算法获得前进路线,可以实现左转和右转并且有指示灯对应亮起,实现循迹。 -
摄像头智能循迹小车设计与实现
2021-01-29 22:10:12智能循迹小车可以根据前端摄像头的输入图像识别出道路状况,通过优化智能车的软硬件设计,能够确保 其在不同环境下行驶的快速性和准确性,本文以Kinetis60 为核心处理器,完成了智能车路径检测、速度检测、数 ... -
车辆循迹行驶算法学习笔记.pdf
2020-05-04 22:06:52以下算法研究内容的阅读笔记来自于《Autonomous_vehicle_control_at_the_limits_of_handling.pdf》 可以自行百度或者gooooogle搜索, - 说明:以下latex格式的公式在网页中显示不出来效果,可以把本.md文件git ... -
CCD摄像头循迹和灰度传感器循迹哪个更好
2021-12-13 00:41:07现在想做一个智能车循迹方面不知道是用普通6路灰度传感器好还是CCD摄像头好,想知道哪个更好一点更丝滑一点。比如寻单个黑箱的时候哪个好?还有双线的时候哪个好用?像英飞凌智能车比赛那种赛道用哪个模块好一点? -
【方法】树莓派小车自动循迹(摄像头)
2018-12-28 10:35:07今天我们来介绍一下树莓派小车的循迹教程 首先看一个效果视频 说明 该小车的硬件是:树莓派+L298N,其实用Arduino也是一样的,下位机只提供一个车轮的控制,视觉识别都是通过树莓派完成的 看到这样一个赛道,赛道是...