0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何控制Pan/Tilt Servo设备来安置一个PiCam

新机器视觉 来源:机器学习研究组订阅号 作者:机器学习研究组订 2020-11-03 09:45 次阅读

01. 导语在之前的某个教程里,我们探讨了如何控制Pan/Tilt Servo设备来安置一个PiCam(树莓派的相机)。这次,我们将使用你的设备来帮助相机自动地跟踪某种颜色的物体,像下边的动图里那样:

尽管这是我第一次使用OpenCV,但我必须承认,我已经爱上了这个“开源计算机视觉库”。

OpenCV对学术用途和商业用途都免费。它有C++、C、PythonJava接口,并且支持Windows、Linux、MacOS、iOSAndroid系统。在我的OpenCV教程系列中,我们将专注于使用树莓派(当然,操作系统就是Raspbian了)和Python。OpenCV为高效计算而生,极大地专注于实时应用。因此,它对于物理计算(即使用可以感知和响应模拟世界的软件和硬件来构建交互式物理系统)项目来说,简直再适合不过了!

02. 安装 OpenCV 3 库我使用的是安装着目前最新的Raspbian版本(Stretch)的树莓派V3。安装OpenCV最好的办法就是按照Adrian Rosebrock的这篇极棒的教程:Raspbian Stretch: Install OpenCV 3 + Python on your Raspberry Pi。

我在我的树莓派上试了好几种不同的OpenCV安装教程,其中Adrian的是最棒的一篇。我建议各位读者一步一步按照这篇教程的步骤做。

当你完成了Adrian的教程后,你的树莓派应该已经安装好了OpenCV的虚拟环境,并且可以进行我们的实验了。

让我们再次检查一下虚拟环境并确认OpenCV 3已经正确安装了。

Adrian建议每次打开新的终端都执行一次“source”命令,从而确保你的系统变量已经正确设置:

source ~/.profile

接下来,进入我们的虚拟环境:

workon cv

如果你看到你的命令提示符之前多了个(cv),那说明你已经进入虚拟环境“cv”了。

(cv) pi@raspberry:~$

Adrian强调,Python虚拟环境“cv”是和Raspbian Stretch系统自带的Python版本完全独立的。也就是说,系统Python的site-packages目录中的那些库在虚拟环境“cv”中并不能使用——同样,这个虚拟环境中的包在系统全局的Python版本中也是无法使用的。

现在,Python翻译器,启动!

python

同时,请确认你是用的是Python 3.5版本或者更高版本。

在翻译器中(应该会有“>>>”提示符),导入OpenCV库:

import cv2

如果没有出现任何错误信息,说明OpenCV在你的虚拟环境中已经正确安装~

03. 测试你的相机

既然你的树莓派已经安装好OpenCV了,那就先测试一下你的相机是否正常工作吧~(假设你已经在你的树莓派上安装PiCam了)

在你的IDE中输入以下代码:

import numpy as npimport cv2cap = cv2.VideoCapture(0) while(True): ret, frame = cap.read() frame = cv2.flip(frame, -1) # Flip camera vertically gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow( frame , frame) cv2.imshow( gray , gray) if cv2.waitKey(1) & 0xFF == ord( q ): breakcap.release()cv2.destroyAllWindows()

上述代码将捕获你的PiCam的视频流并使用BGR三色模式和灰度模式显示。

请注意,我的相机在组装过程中是上下颠倒的,所以我把得到的图片垂直翻转了。如果你并没有我的情况,请删掉frame = cv2.flip(frame, -1)那一行。

或者,你可以直接从我的GitHub下载该代码:simpleCamTest.py

要执行我的代码,运行:

python simpleCamTest.py

要结束程序,请按键盘上的[q]键或[Ctrl]+[C]键。

下图是我的结果:

要学习OpenCV的更多知识,可以参考以下教程:loading -video-python-opencv-tutorial

04. 使用 Python 与 OpenCV 进行颜色检测我们想做的一件事情就是检测并跟踪某种颜色的物体。为此,我们必须理解一点OpenCV是如何翻译颜色的。

关于颜色检测,Henri Dang写了一篇很棒的教程:Color Detection in Python with OpenCV。

通常,我们的相机是使用RGB颜色模式工作的。RGB颜色模式可以这样认为:我们看到的所有可能的颜色都可以被三种颜色的光(红,绿,蓝)组成。然而,这里我们使用的OpenCV默认是BGR颜色模式,也就是将RGB的顺序进行了调整。

正如以上所述,使用BGR颜色模式,每一个像素可以由三个参数——蓝、绿、红组成。每个参数通常是一个0~255之间的值(或者十六进制下0x00到0xFF)。比如,电脑屏幕上的纯蓝色的BGR值分别为:蓝255,绿0,红0。

OpenCV还使用一种RGB模型的替代——HSV(Hue色相,Saturation色度,Value色值)颜色模型,它是70年代的计算机图形学研究者为了更好地与人类视觉对颜色属性的感知方式相匹配而提出的。

好。如果你想要使用OpenCV跟踪某一种确定的颜色,你必须使用HSV模型定义它。

示例比如说,我想要跟踪下图中的黄色塑料盒。首先要做的就是找出它的BGR值。你可以用很多办法采样(这里我用的是PowerPoint)。

我这里找到的是:

蓝色:71

绿色:234

红色:213

下面,我们需要将BGR模型(71, 234, 213)转换为HSV模型,这将被定义为上下界取值范围的形式。让我们执行以下代码:

import sysimport numpy as npimport cv2 blue = sys.argv[1]green = sys.argv[2]red = sys.argv[3] color = np.uint8([[[blue, green, red]]])hsv_color = cv2.cvtColor(color, cv2.COLOR_BGR2HSV)hue = hsv_color[0][0][0] print("Lower bound is :"),print("[" + str(hue-10) + ", 100, 100]")print("Upper bound is :"),print("[" + str(hue + 10) + ", 255, 255]")

你也可以到GitHub下载我的这段代码:bgr_hsv_converter.py

要执行我的脚本,运行以下命令并把BGR值作为参数:

python bgr_hsv_converter.py 71 234 213

这个程序将会计算我们目标物体HSV值的上下界。给定以上参数会得到:

lower bound: [24, 100, 100]

以及

upper bound: [44, 255, 255]

以上结果将显示在终端中。

最后让我们看看OpenCV如何根据给出的颜色来选择出我们的物体。

import cv2import numpy as np # Read the picure - The 1 means we want the image in BGRimg = cv2.imread( yellow_object.JPG , 1) # resize imag to 20% in each axisimg = cv2.resize(img, (0,0), fx=0.2, fy=0.2) # convert BGR image to a HSV imagehsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # NumPy to create arrays to hold lower and upper range# The “dtype = np.uint8” means that data type is an 8 bit integerlower_range = np.array([24, 100, 100], dtype=np.uint8)upper_range = np.array([44, 255, 255], dtype=np.uint8) # create a mask for imagemask = cv2.inRange(hsv, lower_range, upper_range) # display both the mask and the image side-by-sidecv2.imshow( mask ,mask)cv2.imshow( image , img) # wait to user to press [ ESC ]while(1): k = cv2.waitKey(0) if(k == 27): breakcv2.destroyAllWindows()

你也可以到GitHub下载我的这段代码:colorDetection.py

要执行我的脚本,运行以下命令并把图片名作为参数(我这里的图片为yellow_object.JPG):

python colorDetection.py

这个脚本将显示原图(“image”窗口)和OpenCV使用颜色范围过滤后的掩膜(“mask”窗口)。

05. 移动物体跟踪既然我们已经知道了如何用掩膜来选择出我们的物体,那就让我们用相机来实时跟踪他的移动吧。为此,我基于Adrian Rosebrock的OpenCV小球目标跟踪教程写了我的代码。

我强烈建议你详细阅读Adrian的教程。

首先,请确认你已经安装了imutils库。它是Adrian基于OpenCV自制的图像处理基本任务(如修改尺寸、翻转等)的易用函数集合。如果你还没有安装,请在你的Python虚拟环境中运行下面的命令安装:

pip install imutils

下面,从我的GitHub下载ball_tracking.py代码并用下面的命令执行:

python ball_traking.py

你将会看到类似于下面的gif的结果:

总体而言,我与Adrian的代码除了“视频垂直翻转”之外没有什么不同:

frame = imutils.rotate(frame, angle=180)

请注意,这里使用的颜色掩膜的边界值是我们在上一步得到的。

06. 测试通用 IO现在我们已经搞定OpenCV的基础了,是时候给树莓派装个LED来试一下通用IO了。

请按照上图的电路做:LED的负极接到GPIO 21口,正极接一个220Ω的电阻再连接GND。

现在使用我们的Python虚拟环境测试一下这个LED吧!

请注意,有可能你的Python虚拟环境还没有安装树莓派的RPi.GPIO。如果还没有的话,运行下面的命令即可使用pip安装(请先确定自己在虚拟环境“cv”中):

pip install RPi.GPIO

现在用一个Python脚本来做个简单的测试:

import sysimport timeimport RPi.GPIO as GPIO # initialize GPIO and variablesredLed = int(sys.argv[1])freq = int(sys.argv[2])GPIO.setmode(GPIO.BCM)GPIO.setup(redLed, GPIO.OUT)GPIO.setwarnings(False) print(" [INFO] Blinking LED (5 times) connected at GPIO {0} at every {1} second(s)".format(redLed, freq))for i in range(5): GPIO.output(redLed, GPIO.LOW) time.sleep(freq) GPIO.output(redLed, GPIO.HIGH) time.sleep(freq) # do a bit of cleanupprint(" [INFO] Exiting Program and cleanup stuff ")GPIO.cleanup()

上边的代码需要一个GPIO端口号和一个LED闪烁频率作为参数。LED闪烁5次后程序结束。结束之前记得释放GPIO。

也就是说,运行脚本时要给出两个参数:“LED GPIO”和frequency。举个例子:

python LED_simple_test.py 21 1

上边的指令意味着使用“GPIO 21”上连接的LED灯,并且每1秒闪烁一次,总共闪烁五次。

同样,上边这段代码也可以在GitHub下载:GPIO_LED_test.py

上边的图片显示了我的程序结果。至于LED灯亮不亮,就要各位自己去检验啦。

好,下面让我们把OpenCV和基本GPIO操作一起耍起来~

07. 识别颜色和GPIO(General-purpose input/output:通用型输入输出)交互让我们开始集成 OpenCV 代码和 GPIO 进行交互。我们会从 最后的OpenCV 代码开始,并且我们将会把 GPIO_RPI 库集成到代码中,其目的是在摄像头检测到我们的着色物体时,能使红色LED常亮。这一步骤使用的代码是基于 Adrian 写得非常不错的教程OpenCV, RPi.GPIO, and GPIO Zero on the Raspberry Pi

第一件需要做的事情是:”创建“我们的LED对象,目的是为了连接上指定的GPIO。

import RPi.GPIO as GPIOredLed = 21GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)GPIO.setup(redLed, GPIO.OUT)

第二,我们必须初始化LED(关灯状态):

GPIO.output(redLed, GPIO.LOW)ledOn = False

现在,在代码循环体中,当物体被检测到,”圆“被创建时,我们会把LED灯打开

GPIO.output(redLed, GPIO.HIGH)ledOn = True

你可以在我的GitHub库中下载到完整的代码:object_detection_LED.py

运行代码使用到的命令行:

python object_detection_LED.py

下面的图片就是实现的效果。提示:当物体被检测到时,在图片左下方的LED灯就会亮着。

试试不同颜色,不同形式的物体,你会发现一旦颜色和掩码范围内匹配的话,LED灯就会亮起来。

下面的视频显示了一些经验。要注意的是,只有在色值一定范围内的黄色物体才会被检测到,LED等会亮起来。而其他不同颜色的物体则会被略过。

正如最后一步解释的那样,我们只是用到了LED灯。但是在视频中,摄像头却集成了云台(Pan Tilt:指摄像头可全方位左右/上下移动),所以不妨先忽略它。我们会下一步骤中实现云台机制。

08. 云台机制

现在我们已经用上了基本的 OpenCV 和 GPIO,那么接下来我们升级一下云台机制。

获取更多细节,请查看我的教程:Pan-Tilt-Multi-Servo-Control

伺服(servo:一种微型电子机械产品的合体转置)需要连接额外的 5V 电力供应模块,并且这些伺服使用它们的数据插口(在我这边,它们是黄色的布线)连接草莓派的 GPIO,连接方式如下:

GPIO 17 ==> 倾斜伺服

GPIO 27 ==> 水平伺服

不要忘记了将 GND(GND:ground,接地端)引脚 也连到一起 ==> 草莓派——伺服——额外电力供应模块

你有个可选项:在草莓派 GPIO 和 服务端的数据输入引脚之间串联一个 1K 欧姆的电阻。这个举措可以在伺服发生问题时保护你的草莓派。

让我们一起用这个机会在 虚拟 Python 环境中测试一下我们的伺服。
我们执行 Python 脚本来测试一下驱动器

from time import sleepimport RPi.GPIO as GPIO) GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)def setServoAngle(servo, angle): pwm = GPIO.PWM(servo, 50) pwm.start(8) dutyCycle = angle / 18. + 3. pwm.ChangeDutyCycle(dutyCycle) sleep(0.3) pwm.stop() if __name__ == __main__ :import sys servo = int(sys.argv[1]) GPIO.setup(servo, GPIO.OUT) setServoAngle(servo, int(sys.argv[2])) GPIO.cleanup()

上面代码的核心是 setServoAngle(servo, angle)方法。这个方法会接收的参数有:一个 GPIO 数字,一个伺服被定位的角度值。一旦把角度值输入到这个方法中,我们必须将其转换到等效的工作周期中(duty cycle:指伺服进入角度变化的时间段)。

执行脚本时,你要输入两个参数值:GPIO 伺服对应的端口以及角度值。

例如:

python angleServoCtrl.py 17 45

上面的命令行会将在 连接在GPIO 17端口的伺服(倾斜伺服)定位到45度的”海拔“上。

angleServoCtrl.py 文件可以在我的GitHub上下载到。

09. 实时获取物体位置将物体定位到屏幕中央的想法会使用到云台机制。实现这个想法坏消息是 我们必须实时地定位到物体的位置,但好消息是 如果我们已经知道了物体中心坐标点,这将会很容易。

首先,我们使用之前用过的”object_detect_LED“代码,以及修改该代码,以打印出检测物体的 x,y坐标点。

代码可以从我的GitHub中下载到:objectDetectCoord.py

代码核心逻辑是:在检测到的物体区域画出一个圆,并且在圆的中心画一个红点。

# only proceed if the radius meets a minimum sizeif radius > 10: # draw the circle and centroid on the frame, # then update the list of tracked points cv2.circle(frame, (int(x), int(y)), int(radius), (0, 255, 255), 2) cv2.circle(frame, center, 5, (0, 0, 255), -1) # print center of circle coordinates mapObjectPosition(int(x), int(y)) # if the led is not already on, turn the LED on if not ledOn: GPIO.output(redLed, GPIO.HIGH) ledOn = True

我们输出中心点坐标到 mapObjectPosition(int(x), int(y))方法中,目的是打印这些坐标点。方法如下:

def mapObjectPosition (x, y): print ("[INFO] Object Center coordinates at X0 = {0} and Y0 = {1}".format(x, y))

在跑这个程序时,我们会看到在命令行终端上输出的 (x,y)坐标点,如下图所示:

太好了!我们可以使用这些坐标点作为云台追踪系统的开始点。

10. 物体位置追踪系统我们想要目标始终在屏幕的中央,我们来定义一下,例如:假如满足下方条件,我们就认为物体在中央:

220 < x < 280

160 < y < 210

而在这个界限之外的话,我们就需要通过移动云台装置来修正偏差。基于这个逻辑,我们可以构建如下方法mapServoPosition(x, y)。需要注意的是,该方法中使用到的”x“和”y“是和我们之前打印出来的中心位置一样的。

# position servos to present object at center of the framedef mapServoPosition (x, y): global panAngle global tiltAngle if (x < 220): panAngle += 10 if panAngle > 140: panAngle = 140 positionServo (panServo, panAngle) if (x > 280): panAngle -= 10 if panAngle < 40: panAngle = 40 positionServo (panServo, panAngle) if (y < 160): tiltAngle += 10 if tiltAngle > 140: tiltAngle = 140 positionServo (tiltServo, tiltAngle) if (y > 210): tiltAngle -= 10 if tiltAngle < 40: tiltAngle = 40 positionServo (tiltServo, tiltAngle)

基于这些(x,y)坐标点,并使用方法positionServo(servo, angle),伺服位置命令已经产生了。举个例子:假如”y“的位置是”50“,这就意味着我们的物体几乎在屏幕的顶部,也就是说 摄像头的视野是往下的(比如说倾斜装置处于120°上),所以要调低倾斜装置的角度(比如说调到100°),如此一来,摄像头的视野将会抬高,进而使得物体在屏幕上就会往下方移动(比如 y坐标提高到190的位置)。

上面的图例在几何上解释了举的例子。

思考一下水平装置上的摄像头如何移动的。要注意的是 屏幕并不是镜像映射的,也就是说,当你面对着摄像头时,如果你将物体移动到”你的左边“,但在屏幕上看,物体却会在”你的右边“移动。

positionServo(servo, angle)方法可以写成这样:

def positionServo (servo, angle): os.system("python angleServoCtrl.py " + str(servo) + " " + str(angle)) print("[INFO] Positioning servo at GPIO {0} to {1} degrees".format(servo, angle))

上面的代码中,我们将会调用之前展示的伺服移动脚本。

注意:angleServoCtrl.py一定要和 objectDetectTrac.py 在同一个目录下。

完整的代码可以从我的GitHub上下载:objectDetectTrack.py

下面的gif 展示了我们的项目运行的效果:

11. 结论

我一如既往地希望这个项目能帮助其他人找到进入激动人心的电子世界的入口。

想要获取项目细节以及最终的代码,可以浏览我的GitHub仓库:OpenCV-Object-Face-Tracking 。

而想了解更多的项目,请浏览我博客:MJRoBot.org

下面是我下一篇教程的预告,我们将会探索”人脸追踪和检测“。

向你们发出来自世界南半球的问候!

责任编辑:lq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 自动化
    +关注

    关注

    29

    文章

    5570

    浏览量

    79268
  • 计算机视觉
    +关注

    关注

    8

    文章

    1698

    浏览量

    45993
  • OpenCV
    +关注

    关注

    31

    文章

    635

    浏览量

    41345

原文标题:实践干货 | 自动化视觉跟踪

文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    贸泽电子开售适合工业和智能家居应用的 Panasonic Industrial Devices PAN9019和PAN9019A Wi-Fi 6双频无线模块

    Devices全新的PAN9019和PAN9019A系列Wi-Fi® 6双频2.4GHz/5GHz/蓝牙5.4模块。PAN9019系列是先进的Wi-Fi/蓝牙模块,具有出色的连接能力,可满足工业物联网
    发表于 12-13 15:19 73次阅读

    双开关控制灯怎么接线

    双开关控制灯的接线方法主要有以下几种,每种方法都有其特定的应用场景和接线方式: 、串联接线法 接线步骤 : 将电源线的火线(L)与
    的头像 发表于 10-09 15:57 5462次阅读

    如何控制普通电机的转动角度

    (Stepper Motor)和伺服电机(Servo Motor)。每种电机都有其特定的控制方式和应用场景。 直流电机 :通过改变电源电压或电流来控制转速和方向。 步进电机 :通过发送脉冲信号来
    的头像 发表于 09-03 10:42 737次阅读

    制作简单手机充电器的步骤教程

    你有没有想过手机充电器是如何工作的,或者小型设备如何将220 – 230伏的交流电源转换为5伏或所需的电压?在这个项目中,我们将解释用于通过将 220 伏交流电源转换为手机电源额定值来安
    的头像 发表于 08-12 18:11 1491次阅读
    制作<b class='flag-5'>一</b><b class='flag-5'>个</b>简单手机充电器的步骤教程

    经典蓝牙协议PAN详解

    蓝牙 Profile定义了蓝牙设备之间如何进行通信以及实现特定的功能和应用场景。正是由于各种Profile的存在拓展出了蓝牙丰富的应用场景,例如A2DP、HFP、HID等。PAN Profile便提供了蓝牙设备接入以太网络的能力
    的头像 发表于 07-17 09:25 3039次阅读
    经典蓝牙协议<b class='flag-5'>PAN</b>详解

    esp8266中断不准的原因?

    我使用esp8266 及 http服务来控制servo servo需要约每10ms更新次pwm值 (从i2c写值给pwm ic控制)
    发表于 07-11 07:36

    使用wear_level api来安装fat文件系统,如何格式化FAT文件系统?

    我使用wear_level api来安装fat文件系统。 在使用过程中发现,在向该地址中写入文件的时候断电,将导致这份文件之后无法操作,还会占用文件位置。当这样的情况出现多次,占用的文件位置过多
    发表于 06-26 06:51

    伺服控制器与PLC的区别

    在现代工业自动化领域中,伺服控制器(Servo Controller)和可编程序控制器(Programmable Logic Controller,简称PLC)是两至关重要的
    的头像 发表于 06-13 17:26 3085次阅读

    工业自动化控制设备包括什么设备

    工业自动化控制设备是现代工业生产中不可或缺的部分,它们通过自动化技术实现生产过程的高效、稳定和精确控制。本文将详细介绍工业自动化控制
    的头像 发表于 06-11 11:04 1855次阅读

    工业控制设备有哪些类型

    工业控制设备是现代工业生产中不可或缺的部分,它们通过自动化、智能化的方式,提高了生产效率,降低了生产成本,保证了产品质量。本文将详细介绍工业控制
    的头像 发表于 06-11 10:49 1588次阅读

    DIY推荐!基于 ESP32 做的三舵机机械蚂蚁

    。 但在这个项目中只用到三舵机、夹爪和点机械设备,就实现了只极简主义的蚂蚁机器人,除开
    发表于 03-28 09:40

    轻量级的LED控制模块

    比如LED周期控制函数为100ms,理论上设置500ms间隔闪烁,则需要占用10bit,但是增加bit时间颗粒度变量,只需要占用两b
    发表于 02-29 11:43 569次阅读

    PAN24001产品警报通知

    电子发烧友网站提供《PAN24001产品警报通知.pdf》资料免费下载
    发表于 02-21 11:08 0次下载
    <b class='flag-5'>PAN</b>24001产品警报通知

    电位器两地控制变频器,如何接线?

    电位器两地控制变频器,如何接线? 接线方式如下: 1. 首先,明确需要使用的电器设备。在这个场景中,我们需要两
    的头像 发表于 02-05 10:13 5265次阅读

    双控开关控制灯怎么接线

    双控开关是指可以通过在两不同位置的开关来控制灯的开关。在使用双控开关控制灯的时候,我们需要正确地接线,以确保开关能够正常工作。下面是关
    的头像 发表于 01-17 11:19 2671次阅读