[项目概述]
本项目将树莓派作为数据处理和机构控制核心,通过接入USB摄像头作为图像采集设备,摄像头安装在一个由两个MG945舵机组成的旋转云台上,下部舵机用来使摄像头左右旋转,上部舵机用来使摄像头上下旋转。由于此舵机的旋转范围为0~180度,故整个云台的旋转范围受舵机的限制。舵机需要稳定的供电,采用开关电源的5V输出单独供电。
物体追踪采用颜色追踪方案,将RGB颜色空间转换到HSV颜色空间,颜色识别更准确。测试物体用的是一个红色的饮料瓶盖。物体追踪的控制原理是通过舵机云台不断调节摄像头的角度,使被检测物体始终位于图像的中心区域,如果物体此时没有处于图像中心,说明摄像头没有正对着物体,则向相反方向调整舵机角度,实现物体跟踪的功能。
系统整体效果如下面两幅图所示。
先是整体的系统结构:
再来看一下识别效果:
[材料清单]
- 树莓派3B+
- USB摄像头
- 红色饮料瓶盖(测试物体)
- 两个MG945舵机及固定支架
- 自制GPIO口转接板
- 充电宝(给树莓派供电)
- 开关电源(给舵机供电)
[硬件设计]
舵机是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。舵机的选择可以根据实际的需要进行选择,如果USB摄像头本身比较轻,可以选用小型塑料的9g舵机搭建平台。我选用MG945是因为手边正好有这种舵机就拿来用了。
对于我这种舵机,一般需要配合专用的舵机支架来搭建云台机构。如果是用的小型的9g舵机,可以借助扎带、胶枪等工具来手工制作云台框架,这个就要看自己的手工水平了。
USB摄像头我选用的是一个快要废弃的摄像头,我把它壳子拆了,背后粘了一块板子用来和云台固定。另外云台的底座可以固定在某个平面上以保持稳定,我固定在了一块废旧的电路板上。
双舵机云台摄像头最终效果:
树莓派3B+留有40个GPIO口(两排,每排20个),包括一些5V、3.3V电源和GND端口。舵机的接口是3P型的,分别是信号线(橙色)、电源线(红色)和地线(棕色)。为了接线方便以及单独供电方便,自制了一个转接板。由于转接板下部需要连接树莓派,转接板上部需要连接舵机等,即转接板两面都需要焊接原件(排母和排针),而手头的洞洞板都是单面有焊盘,想了想可以把排针的固定塑料移动一下,使所有元器件都焊在同一面。焊接的正反面效果如下,反面看着还可以,但是正面满眼的都是焊盘和焊点,而且焊点明晃晃的看着有点眼花。
自制转接板的反面效果:
自制转接板的正面效果:
当然,弥补措施就是再在上面加上一层纸,顺便将GPIO口的序号标上,方便接线。最终效果如下图,右边两排共40个是将树莓派的原本的40个GPIO口引上来,左边三排是专用于接舵机的,标黑线的一排是GND,该GND与树莓派的GND相连,用于保持信号处于同一水平。标红线的一排是舵机的独立电源,注意不要和树莓派的5V相连,单独供电更安全。
自制转接板的最终效果:
[软件调试]
舵机的控制信号为频率50Hz,即周期是20ms的脉宽调制(PWM)信号,其中脉冲宽度从0.5ms-2.5ms,相对应舵盘的位置为0-180度,呈线性变化。也就是说,给它提供一定的脉宽,它的输出轴就会保持在一个相对应的角度上,无论外界转矩怎样改变,直到给它提供一个另外宽度的脉冲信号,它才会改变输出角度到新的对应的位置上。舵机内部有一个基准电路,产生周期20ms,宽度1.5ms的基准信号,同时还有一个比较器,将外加信号与基准信号相比较,判断出方向和大小,从而产生电机的转动信号。
不同的角度对应的占空比如下:
初始位置(0°):脉冲宽度 0.5ms ->占空比= 0.5ms / 20ms ==> 2.5%
中间位置(90°):脉冲宽度 1.5 ms->占空比= 1.5ms / 20ms ==> 7.5%
最终位置(180°):脉冲宽度2.5 ms->占空比= 2.5ms / 20ms ==> 12.5%
即占空比应该在2.5%到12.5%的范围内变化,总体变化范围为10,对应0~180度。程序中的控制的工作时间计算公式为: T=angle/18+2.5
例如angle=0时,T=0/18+2.5=2.5,angle=180时,T=180/18+2.5=12.5。
下面这个小程序可以控制单个舵机(29号引脚)转动到指定角度(45度):
- from time import sleep
- import RPi.GPIO as GPIO
-
- GPIO.setmode(GPIO.BOARD)
- servo = 29
- GPIO.setup(servo, GPIO.OUT)
-
- def setServoAngle(servo, angle):
- pwm = GPIO.PWM(servo, 50) #channel,frequence=50Hz
- pwm.start(7.5) #start pwm
- dutyCycle = angle / 18. + 2.5 #PWM 2.5%~12.5%
- pwm.ChangeDutyCycle(dutyCycle) #change pwm
- sleep(0.1)
- pwm.stop()
-
- if __name__ == '__main__':
- setServoAngle(servo,45) #set angle
- GPIO.cleanup()
颜色的常用表达形式为RGB色彩模式,但RGB并不能很好地反映出物体具体的颜色信息 。而另一种HSV颜色空间则能够非常直观的表达色彩的明暗,色调,以及鲜艳程度,方便进行颜色之间的对比。HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。这个模型中颜色的参数分别是:色调(H),饱和度(S),亮度(V)。
色调H表示色彩信息,即所处的光谱颜色的位置。该参数用一角度量来表示,红、绿、蓝分别
饱和度S为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率。S=0时,只有灰度。相隔120度。互补色分别相差180度。
亮度V表示色彩的明亮程度,范围从0到1,注意它和光强度之间并没有直接的联系。
OpenCV中,H、S、V的取值范围为:
H: 0— 180
S: 0— 255
V: 0— 255
利用HSV色彩模式识别颜色,需要根据要识别的物体设置其HSV的范围,识别出颜色区域后对该区域进行轮廓提取,圆拟合等操作,即可确定物体的位置。编程思路如下:
- boundaries = [ ( [170, 43, 46 ], #红色范围下阈值
- [180, 255, 255] ) ] #红色范围上阈值
- cap = cv2.VideoCapture(0)
-
- while True:
- ret, frame = cap.read()
- hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV) #RGB转HSV
- for (lower, upper) in boundaries:
- lower = np.array(lower, dtype = "uint8")
- upper = np.array(upper, dtype = "uint8")
- mask = cv2.inRange(hsv, lower, upper)
- cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
- cnts = cnts[0] if imutils.is_cv2() else cnts[1]
- center = None
- if len(cnts) > 4:
- c = max(cnts, key=cv2.contourArea)
- ((x,y), radius) = cv2.minEnclosingCircle(c) #得到物体中心点和物体半径大小
将颜色识别和舵机控制结合起来,根据识别的物体在图像中的位置通过反馈控制的思想来调整舵机,思路如下:
摄像头获取的图像大小为640*480,中心点为(320,240),则定义中心区域为:x从220到420,y从140到340,中心区域如下图:
若物体处于中心区域,则不需要调整舵机(continue),若在中心区域外,如物体中心点x坐标小于等于220,则控制左右旋转的舵机角度调整正的5度,为防止角度超出180度,当调整超出时,限定最大角度为180度。根据物体的位置进行舵机调整的编程思路如下:
- if radius > 35: #检测到的物体的半径大于35像素
- if (x > 220) and (x < 420):
- continue
- elif (x <= 220):
- anglex = anglex + 5
- if (anglex > 180): anglex = 180
- elif (x >= 420):
- anglex = anglex - 5
- if (anglex < 0): anglex = 0
- setServoAngle(servo1,anglex)
-
- if (y > 140) and (y < 340):
- continue
- elif (y <=140):
- angley = angley - 5
- if (angley < 0):angley = 0
- elif (y >= 340):
- angley = angley + 5
- if (angley > 180): angley = 180
- setServoAngle(servo2,angley)
- else:
- continue
[视频效果演示]
演示视频:
基于树莓派的云台摄像头物体追踪系统
[结果分析]
实际的测试效果跟踪不是很准确,原因在于图像处理和舵机运行是交替进行的,导致舵机调整时不能得到信息反馈。
解决方案可以采用多线程编程的方式,使图像处理和舵机运动同时进行,或是采用Arduion等微控制器单独进行舵机的控制,树莓派只作为图像处理中心,识别的位置结果可通过串口通信的方式传送给Arduino,同样也可以达到图像处理与舵机运动同步进行的效果。
[帖子汇总]
最后汇总一下我之前的测评帖子
1.
【树莓派3B+测评】开箱与硬件测评
2.
【树莓派3B+测评】系统安装
3.
【树莓派3B+测评】远程登录
4.
【树莓派3B+测评】点亮LED
5.
【树莓派3B+测评】使用USB摄像头
6.
【树莓派3B+测评】树莓派数硬币
7.
【树莓派3B+测评】树莓派扫描条形码
8.
【树莓派3B+测评】OCR字符识别
9.
【树莓派3B+测评】TensorFlow物体识别
10.
【树莓派3B+测评】搭建Flask视频流媒体Web服务器
本帖最后由 DDZZ669 于 2018-10-11 20:14 编辑