分享

「干货」用Opencv打造一台自动视觉目标跟踪系统

 taotao_2016 2019-08-26

平移/倾斜伺服装置,帮助摄像机使用视觉自动跟踪颜色对象。

「干货」用Opencv打造一台自动视觉目标跟踪系统

  1. 简介

现在我们将使用我们的设备帮助相机自动跟踪颜色对象,如下所示:

「干货」用Opencv打造一台自动视觉目标跟踪系统

OpenCV可免费用于学术和商业用途。它具有C ++,C,Python和Java接口,并支持Windows,Linux,Mac OS,iOS和Android。在我的一系列OpenCV教程中,我们将专注于Raspberry Pi(因此,Raspbian as OS)和Python。OpenCV专为提高计算效率而设计,专注于实时应用。因此,它非常适合物理计算项目!

2.安装OpenCV 3软件包

我正在使用Raspberry Pi V3更新到最新版本的Raspbian(Stretch),因此安装OpenCV的最佳方法是遵循Adrian Rosebrock开发的优秀教程:Raspbian Stretch:在Raspberry Pi上安装OpenCV 3 + Python 。

我尝试了几个不同的指南在我的Pi上安装OpenCV。阿德里安的教程是最好的。我建议你按照他的指导方针一步一步地做同样的事情。

完成Adrian的教程后,您应该准备好在您的Pi上运行我们的实验的OpenCV虚拟环境。

让我们转到我们的虚拟环境并确认OpenCV 3已正确安装。

Adrian建议每次打开新终端时运行命令“source”以确保系统变量已正确设置。


source ~/.profile

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


workon cv

如果您在提示符前面看到文本(cv),那么您就在cv virtualenvironment中:


(cv) pi@raspberry:~$

Adrian提请注意,cv Python虚拟环境完全独立,并与Raspbian Stretch下载中包含的默认Python版本隔离。因此,全局site-packages目录中的任何Python包都不可用于cv虚拟环境。同样,安装在cv的site-packages中的任何Python包都不可用于全局安装的Python。

现在,输入你的Python解释器:


python

并确认您运行的是3.5(或更高版本)版本

在解释器内部(将出现“>>>”),导入OpenCV库:


import cv2

如果没有出现错误消息,则在您的PYTHON VIRTUAL ENVIRONMENT上正确安装OpenCV。

您还可以检查安装的OpenCV版本:


cv2.__version__

应该出现3.3.0(或者可以在将来发布的高级版本)。上述终端PrintScreen显示前面的步骤。

3. Testing Your Camera

「干货」用Opencv打造一台自动视觉目标跟踪系统

一旦你在RPi中安装了OpenCV,让我们测试你的相机是否正常工作。

我假设您的Raspberry Pi上已经安装了PiCam。

在IDE上输入以下Python代码:


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颜色和灰色模式显示它们。

请注意,由于组装方式,我将相机垂直旋转。如果不是您的情况,请评论或删除“翻转”命令行。

您也可以从我的GitHub:https://github.com/Mjrovai/OpenCV-Object-Face-Tracking/blob/master/simpleCamTest.py下载代码

要执行,请输入命令:


python simpleCamTest.py

要完成程序,您必须按键盘上的[q] [Ctrl] + [C]键

图为结果。

「干货」用Opencv打造一台自动视觉目标跟踪系统

4.使用OpenCV在Python中进行颜色检测

我们将尝试完成的一件事是检测和跟踪某个颜色对象。为此,我们必须更多地了解OpenCV如何解释颜色。

Henri Dang用OpenCV编写了一篇关于Python中的颜色检测的精彩教程。

通常,我们的相机将使用RGB颜色模式,可以通过将其视为可以由红色,绿色和蓝色的三种彩色灯制成的所有可能颜色来理解。我们将在这里使用BGR(蓝色,绿色,红色)。

如上所述,对于BGR,像素由3个参数表示,蓝色,绿色和红色。每个参数的值通常为0-255(或以十六进制表示的O到FF)。例如,计算机屏幕上的纯蓝色像素的B值为255,G值为0,R值为0。

「干货」用Opencv打造一台自动视觉目标跟踪系统

OpenCV与HSV(色调,饱和度,值)颜色模型一起使用,它是RGB颜色模型的替代表示,由计算机图形学研究人员在20世纪70年代设计,以更加贴近人类视觉感知颜色制作属性的方式:

「干货」用Opencv打造一台自动视觉目标跟踪系统

因此,如果要使用OpenCV跟踪某种颜色,则必须使用HSV模型对其进行定义。

假设我必须跟踪黄色物体,如上图所示的塑料盒。易用部分是找到它的BGR元素。您可以使用任何设计程序来查找它(我使用PowerPoint)。

「干货」用Opencv打造一台自动视觉目标跟踪系统

在我的情况下,我发现:

蓝色:71

绿色:234

红色:213

接下来,我们必须将BGR(71,234,213)模型转换为HSV模型,该模型将使用上限和下限范围进行定义。为此,让我们运行以下代码:


import sysimport numpy as npimport cv2blue = 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]\n')print('Upper bound is :'),print('[' + str(hue + 10) + ', 255, 255]')

您也可以从我的GitHub下载代码:https://github.com/Mjrovai/OpenCV-Object-Face-Tracking/blob/master/bgr_hsv_converter.py

要执行,请输入以下命令,其中包含之前找到的BGR值作为参数:


python bgr_hsv_converter.py 71 234 213

程序将打印对象颜色的上下边界。

在这种情况下:


lower bound: [24, 100, 100]

upper bound: [44, 255, 255]

终端打印屏幕显示结果。

「干货」用Opencv打造一台自动视觉目标跟踪系统

最后,但并非最不重要的,让我们看看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:https://github.com/Mjrovai/OpenCV-Object-Face-Tracking/blob/master/colorDetection.py下载代码

要执行,请在目录中输入以下命令,其中包含目标对象的照片(在我的情况下:yellow_object.JPG):


python colorDetection.py

「干货」用Opencv打造一台自动视觉目标跟踪系统

上面的图片将显示原始图像(“图像”)以及在应用蒙版之后对象将如何显示(“蒙版”)。

5.物体移动跟踪

现在我们知道如何使用蒙版“选择”我们的对象,让我们使用相机实时跟踪它的移动。为此,我将我的代码基于Adrian Rosebrock的Ball Tracking with OpenCV教程。

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

首先,确认您是否安装了imutils库。这是Adrian的OpenCV便利功能集合,可以更轻松地完成一些基本任务(如调整大小或翻转屏幕)。如果没有,请输入以下命令在虚拟Python环境中安装库:


pip install imutils

接下来,从我的GitHub下载代码https://github.com/Mjrovai/OpenCV-Object-Face-Tracking/blob/master/ball_tracking.py,并使用以下命令执行它:


python ball_traking.py

因此,您将看到类似于以下gif的内容:

「干货」用Opencv打造一台自动视觉目标跟踪系统

基本上,除了“视频垂直翻转”之外,它与Adrian的代码相同,我用这条线:


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

另请注意,使用的掩码边界是我们在上一步中获得的掩码边界。

6.测试GPIO

现在我们已经使用了OpenCV的基础知识,让我们为我们的RPi安装一个LED并开始与我们的GPIO进行交互。

「干货」用Opencv打造一台自动视觉目标跟踪系统

按照上面的电气图:LED的阴极将通过一个220欧姆的电阻连接到GPIO 21,其阳极连接到GND。

让我们在虚拟Python环境中测试我们的LED。

请记住,在Python虚拟环境中可能没有安装RPi.GPIO!要解决此问题,一旦您在那里(记得确认(cv)在您的终端中),您需要使用pip将其安装到您的虚拟环境中:


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('\n [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('\n [INFO] Exiting Program and cleanup stuff \n')GPIO.cleanup()

此代码将接收GPIO编号作为参数,以及LED应闪烁的频率(以秒为单位)。LED将闪烁5次,程序将终止。请注意,在终止之前,我们将释放GPIO。

因此,要执行脚本,必须输入参数,LED GPIO和频率。

例如:


python LED_simple_test.py 21 1

上述命令将每隔“1”秒闪烁5次连接到“GPIO 21”的红色LED。

可以从我的GitHub下载文件https://github.com/Mjrovai/OpenCV-Object-Face-Tracking/blob/master/GPIO_LED_test.py

「干货」用Opencv打造一台自动视觉目标跟踪系统

上面的终端打印屏幕显示结果(当然您应该确认LED闪烁。

现在,让我们使用OpenCV和一些基本的GPIO。

7.识别颜色和GPIO交互

让我们开始将我们的OpenCV代码与GPIO交互集成。我们将从最后的OpenCV代码开始,我们将在其上集成GPIO-RPI库,因此我们将在相机找到彩色物体的任何时候打开红色LED。此步骤中使用的代码基于Adrian的优秀教程OpenCV,RPi.GPIO和Raspberry Pi上的GPIO Zero:

首先要做的是“创建”我们的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下载完整的代码:

https://github.com/Mjrovai/OpenCV-Object-Face-Tracking/blob/master/object_detection_LED.py

使用以下命令运行代码:


python object_detection_LED.py

结果如下。请注意,每次检测到物体时,LED(左下角)都会亮起:

尝试使用不同的对象(颜色和格式)。您将看到,一旦掩模边界内的颜色匹配,LED就会亮起。

以下视频显示了一些经验。请注意,只会检测到位于颜色范围内的黄色物体,从而打开LED。忽略具有不同颜色的对象。

我们只在这里使用LED,如上一步所述。当我拍摄视频时,我的Pan Tilt已经组装完毕,所以请忽略它。我们将在下一步处理PAN / TILT机制。

8.泛倾斜机制

「干货」用Opencv打造一台自动视觉目标跟踪系统

现在我们已经使用了OpenCV和GPIO的基础知识,让我们安装我们的Pan / tilt机制。

「干货」用Opencv打造一台自动视觉目标跟踪系统

伺服电机应连接到外部5V电源,其数据引脚(在我的情况下,它们的黄色接线)连接到Raspberry Pi GPIO,如下所示:

GPIO 17 ==>倾斜伺服

GPIO 27 ==> Pan Servo

不要忘记将GND连接在一起==> Raspberry Pi - Servos - 外部电源)

您可以选择在Raspberry Pi GPIO和服务器数据输入引脚之间串联一个1K欧姆的电阻。这可以在发生伺服问题时保护您的RPi。

让我们也利用这个机会,在我们的虚拟Python环境中测试我们的伺服器。

让我们使用Python脚本用我们的驱动程序执行一些测试:


from time import sleepimport RPi.GPIO as GPIOGPIO.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(伺服,角度)。该功能接收伺服GPIO编号作为参数,以及伺服必须定位的角度值。一旦此函数的输入为“角度”,我们必须将其转换为等效的占空比。

要执行脚本,必须输入参数,伺服GPIO和角度。

例如:


python angleServoCtrl.py 17 45

上述命令将连接在GPIO 17上的伺服(“倾斜”)与“仰角”成45度。

「干货」用Opencv打造一台自动视觉目标跟踪系统

文件

https://github.com/Mjrovai/OpenCV-Object-Face-Tracking/blob/master/angleServoCtrl.py

可以从我的GitHub下载

9.查找对象实时位置

这里的想法是使用平移/倾斜机制将对象定位在屏幕中间。坏消息是,为了开始我们必须实时知道对象的位置。但好消息是,一旦我们已经拥有了对象中心的坐标,这很容易。

首先,让我们使用之前使用的“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)位置坐标,如上所示。移动对象并观察坐标。我们将意识到x从0到500(从左到右),y从o到350(从上到下)。见上图。

「干货」用Opencv打造一台自动视觉目标跟踪系统

现在我们必须使用这些坐标作为我们的Pan / Tilt跟踪系统的起点

「干货」用Opencv打造一台自动视觉目标跟踪系统

10.物体位置跟踪系统

我们希望我们的对象始终以屏幕为中心。所以,让我们定义一个例子,如果符合以下情况我们会认为我们的对象是“居中的”:

220 <x <280

160 <y <210

在这些边界之外,我们必须移动我们的Pan / Tilt机制以补偿偏差。基于此,我们可以构建函数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(伺服,角度)生成伺服位置命令。例如,假设y位置是“50”,这意味着我们的对象几乎位于屏幕的顶部,可以转换为“相机视线”为“低”(假设倾角为120度) 所以我们必须“减少”倾斜角度(让我们说100度),所以相机视线将“向上”并且物体将在屏幕上“向下”(y将增加,比方说,190)。

「干货」用Opencv打造一台自动视觉目标跟踪系统

上图显示了几何方面的示例。

想想泛相机将如何操作。请注意,屏幕没有镜像,这意味着如果您将对象移动到“左侧”,一旦您与相机相反,它将在屏幕上移动“右侧”。

函数positionServo(伺服,角度)可写为:


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

我们将调用之前显示的脚本进行伺服定位。

请注意,angleServoCtrl.py必须与objectDetectTrac.py位于同一目录中

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

下面的gif显示了我们项目工作的一个例子:

「干货」用Opencv打造一台自动视觉目标跟踪系统

11.结论

一如既往,我希望这个项目可以帮助其他人进入激动人心的电子世界!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多