从一开始,人类就用手势相互交流,甚至在没有任何正式语言之前。手势是沟通的主要方式,在世界各地发现的古代雕塑中也可以明显看出,手势是以非常有效的方式传递大量数据的成功方式,有时甚至比语言本身更有效
手势是自然的,它们可以作为对特定情况的反射而出现。即使我们不知道,它也会在潜意识中发生。因此,它成为与各种设备通信的理想方式。然而,问题依然存在,如何解决
我们可以肯定,如果我们谈论的是手势,那么我们肯定需要做大量的编程来识别视频中的手势;此外,它还需要大量的处理能力才能实现。因此,这是不可能的。我们可以使用一组接近传感器来构建一些基本的手势识别系统。然而,识别的手势范围将非常有限,并且使用的总体端口将是多重的。
因此,我们需要找到一个易于使用且成本不高于其交付成本的解决方案
本章将涵盖以下主题:
- 电场传感
- 使用轻弹帽
- 基于手势识别的自动化
近场传感是一个非常有趣的传感领域。为一些有趣的事情做好准备。如果你感到有点困,或者你缺乏注意力,那么就喝点咖啡,因为这个系统的工作原理将会有点新
只要有电荷,就有一个相关的电场伴随着它。这些电荷在空间中传播,并在物体周围传播。当这种情况发生时,与之相关的电场具有特定的特性。此特性将保持不变,直到其周围的环境为空
对于我们正在使用的手势识别板,它周围的感应场只有几厘米,因此超出该点的任何东西都可以忽略不计。如果附近没有任何东西,那么我们可以安全地假设被感知的电场模式将保持不变。然而,每当一个物体如我们的手靠近时,这些波就会发生畸变。失真与对象的位置及其位置直接相关。通过这种变形,我们可以感知手指的位置,通过不断的感知,我们可以看到正在执行的运动类型。所讨论的电路板如下所示:
电路板上的中心纵横交错区域是发射机,最末端是四个矩形结构。这些是传感元件。它们感知空间中的波浪模式。在此基础上,他们可以推导出物体的 x、y 和 z 坐标。这是由一个名为 MGC3130 的芯片驱动的。这将完成所有计算,并向用户提供有关坐标的原始读数
Flick 帽子以盾牌的形式出现,您只需将其插入覆盆子 Pi 即可开始使用。但是,一旦您这样做,您将不会留下任何 GPIO 引脚。因此,为了避免这个问题,我们将使用公母线连接它。这将使我们能够访问其他 GPIO 引脚,然后我们可以玩得很开心。
因此,请按如下方式连接它。以下是 Flick board 的引脚图:
然后,按如下方式进行连接:
连接完成后,只需上传此代码,看看会发生什么:
import signal
import flicklib
import time
def message(value):
print value
@flicklib.move()
def move(x, y, z):
global xyztxt
xyztxt = '{:5.3f} {:5.3f} {:5.3f}'.format(x,y,z)
@flicklib.flick()
def flick(start,finish):
global flicktxt
flicktxt = 'FLICK-' + start[0].upper() + finish[0].upper()
message(flicktxt)
def main():
global xyztxt
global flicktxt
xyztxt = ''
flicktxt = ''
flickcount = 0
while True:
xyztxt = ''
if len(flicktxt) > 0 and flickcount < 5:
flickcount += 1
else:
flicktxt = ''
flickcount = 0
main()
现在,一旦您上传了代码,让我们继续了解这段代码实际上在做什么。
我们正在使用一个名为import flicklib
的库,该库由该电路板的制造商提供。本章将全面使用该库的功能与 flick board 进行通信并获取数据
def message(value):
print value
在这里,我们定义了一个名为message(value)
的函数,它只需打印参数中传递给函数的任何值:
@flicklib.move()
这对装饰师有一个特殊的概念。根据定义,decorator 是一个函数,它接受另一个函数并扩展后一个函数的行为而不显式修改它。在前一行代码中,我们声明它是一个 decorator@
。
这有一个特殊的任务:动态定义程序中的任何函数。用简单的英语来说,这意味着使用这种方法定义的函数可以根据用户定义的方式进行不同的工作
函数move()
将进一步得到该函数的补充,该函数将在之后定义。这类函数称为嵌套函数。即函数中的函数:
def move(x, y, z):
global xyztxt
xyztxt = '{:5.3f} {:5.3f} {:5.3f}'.format(x,y,z)
在这里,我们定义一个名为move()
的函数,其参数为x
、y
和z
。在函数内部,我们定义了一个名为xyztxt
的全局变量;现在,xyztxt
的值将是五位数的形式,三位后有一个小数点。我们怎么知道的?如您所见,我们正在使用一个名为format()
的函数。此函数的作用是根据用户请求的方式格式化给定变量的值。我们在这里声明的值为{:5.3f}
。:5
表示五位数,3f
表示小数点在三位数之后。因此,格式为xxx.xx
:
def flick(start,finish):
global flicktxt
flicktxt = 'FLICK-' + start[0].upper() + finish[0].upper()
message(flicktxt)
在这里,我们定义了一个名为flick(start, finish)
的函数。它有两个参数:start
和finish
。使用行flicktxt = 'FLICK-' + start[0].upper() + finish[0].upper()
,这是对手势板识别的字符进行切片。如果检测到南-北滑动,则开始将变为南,结束将变为北。现在我们只使用单词的前几个字符:
global xyztxt
global flicktxt
我们再次在全局范围内定义名为xyztxt
和flicktxt
的变量。前面,我们所做的是在函数中定义了它。因此,在主程序中对其进行定义非常重要:
if len(flicktxt) > 0 and flickcount < 5:
flickcount += 1
else:
flicktxt = ''
flickcount = 0
当检测到手势时,flicktxt
变量将获得与手势对应的值。如果没有手势,则flicktxt
将留空。一个名为flickcount
的变量将计算其被刷过的次数。如果值超出指定范围,则使用行flicktxt = ''
将flicktxt
清除为空字符串,并将flickcount
设为 0。
最终的输出将是一个文本,提供给用户手的挥击方向
现在,我们已经按照下图连接了连接:
让我们继续并上传以下代码:
import signal
import flicklib
import time
import RPi.GPIO as GPIO
GIPO.setmode(GPIO.BCM)
GPIO.setup(light, GPIO.OUT)
GPIO.setup(fan,GPIO.OUT)
pwm = GPIO.PWM(fan,100)
def message(value):
print value
@flicklib.move()
def move(x, y, z):
global xyztxt
xyztxt = '{:5.3f} {:5.3f} {:5.3f}'.format(x,y,z)
@flicklib.flick()
def flick(start,finish):
global flicktxt
flicktxt = 'FLICK-' + start[0].upper() + finish[0].upper()
message(flicktxt)
def main():
global xyztxt
global flicktxt
xyztxt = ''
flicktxt = ''
flickcount = 0
dc_inc = 0
dc_dec = 0
while True:
pwm.start(0)
xyztxt = ' '
if len(flicktxt) > 0 and flickcount < 5:
flickcount += 1
else:
flicktxt = ''
flickcount = 0
if flicktxt ==”FLICK-WE”:
GPIO.output(light,GPIO.LOW)
if flicktxt ==”FLICK-EW”:
GPIO.output(light,GPIO.HIGH)
if flicktxt ==”FLICK-SN”:
if dc_inc < 100:
dc_inc = dc_inc + 10
pwm.changeDutyCycle(dc_inc)
else:
Dc_inc = 10
if flicktxt ==”FLICK-NS”:
if dc_inc >0:
dc_dec = dc_dec - 10
pwm.changeDutyCycle(dc_dec)
main()
该程序是我们之前所做程序的补充,一如既往,我们有一些附加功能,可以使用 flick 手势板接收的数据,并使用它打开或关闭灯光
像上一个程序一样,我们以滑动方向的形式在黑板上做手势,并使用一个简单的条件关闭或打开灯。那么,让我们看看有哪些补充:
if flicktxt ==”FLICK-WE”:
GPIO.output(light,GPIO.LOW)
第一个条件很简单。我们将flicktxt
的值与给定变量进行比较,在本例中,该变量为FLICK-WE
,其中WE
表示西到东。因此,当我们从西向东轻弹时,或者换句话说,当我们从左向右轻弹时,灯光将关闭:
if flicktxt ==”FLICK-EW”:
GPIO.output(light,GPIO.HIGH)
和前面一样,我们再次引入了一个名为FLICK-EW
的变量,它表示从东到西的 flick。它的作用是,每当我们从东到西或从右到左挥动手时,灯就会打开:
if flicktxt ==”FLICK-SN”:
if dc_inc <= 100:
dc_inc = dc_inc + 20
pwm.changeDutyCycle(dc_inc)
现在我们已经把一个调光器和一个风扇放在一起,以控制风扇的速度;因此,我们必须给它一个与我们想要驱动它的速度相对应的 PWM。现在,每当用户从南到北或从下到上挥动手时。条件if dc_inc <100
将检查dc_inc
的值是否小于或等于100
。如果是,则将dc_inc
的值增加20
值。使用ChangeDutyCycle()
功能,我们为调光器提供不同的占空比;因此,需要改变风扇的整体速度。每次刷高风扇的值时,它将增加 20%:
else:
Dc_inc = 10
if flicktxt ==”FLICK-NS”:
if dc_inc >0:
dc_dec = dc_dec - 10
pwm.changeDutyCycle(dc_dec)
在本章中,我们能够理解手势识别如何通过电场检测工作的概念。我们还了解使用手势控制板和使用手势控制家庭是多么容易。我们将在下一章介绍机器学习部分。