在制作3D激光扫描仪的过程中,我偶然在网络上发现有人销售可以投影出键盘画面的激光器组件,并且价格低廉。仔细想来其实激光投影键盘的原理和3D扫描仪一致,于是便产生了DIY一个低成本激光键盘的想法。最终,本作品在我完成3D扫描仪的3天内完成了,可见硬件部分的制作不复杂。虽然完成的时间短,但其中也涉及不少的设计细节需要考虑,于是便写了此文向大家分享我的制作过程。
简介
激光投射键盘相信大家之前也有所听说,他通过光学手段,将计算机键盘的画面通过激光投影到任意的平面上(如桌面)上,并且允许操作者像使用真实键盘那样进行输入操作。
图:Celluon公司出品的Magic Cube激光投影键盘
目前市面上能买到的激光键盘产品是由韩国公司Celluon生产销售的。这类产品目前也可以在国内买到,不过因为价格高昂,目前仍旧在千元水平。我之前并没有购买过,具体使用效果也不得而知。有人评价说因为缺少物理反馈,这样的键盘使用上手感可能不好。
但无论如何,激光虚拟键盘还是非常能吸引眼球的,在投射出的键盘影像上输入非常有科技感并且足够科幻。如果能自己以较低成本DIY一台出来,那岂不是更好?
本文提出的DIY激光投影键盘方案可以保证使用较低的成本(百元左右),并提供较强的性能:30hz的输入频率、支持多键输入,并且还有额外的功能:把他当作多点输入设备来使用,比如可以作为绘图板,并能感应手指的压力大小。
在完成本制作后我拍摄了一段演示视频展现它的性能,可以访问如下地址观看:
原理分析
在具体介绍实现过程前,我们首先需要分析这类激光投影键盘的工作原理以及给出解决问题的思路,这样也可方便大家举一反三。首先需要解决的核心问题有这么两个:
产生键盘画面
对于产生键盘画面,可能很多人认为这种画面是通过激光+高速光学振镜来得到的。这种方式虽然在技术上是完全可行的,但由于需要采用精密的机械部件,成本非常高,并且也难以做成轻便的产品。
图:通过光学振镜扫描产生的激光投影画面。图片来自[1]
实际上在激光投影键盘产品中,这类画面往往是通过全息投影技术得到的。激光器通过照射先前保存有键盘画面的全息镜片的方式在目标平面上产生相应的画面。这种方式的成本非常低廉,市面销售的激光笔常配备的投影图案的镜头也是用这种原理产生的。
图:可以投射出图案的激光笔镜头
不过这类全息投影方式对于DIY来说仍旧不现实,幸好得益于目前网络的便利——通过网购可以直接买到用于产生激光键盘画面的全息投影设备了,且成本在¥50以内。
图:可以购买到的投影键盘画面的激光器模组
识别键盘输入事件
在解决了产生键盘画面的问题后,这里分析另一个看似简单的问题:如何判断键盘输入事件?
由于键盘画面可以投射在任意的表面上,因此传统的靠物理按钮的手段自然是不可能的(否则也称不上虚拟键盘)。需要非接触的手段来检测。这里给出了几种途径,他们在技术上都是可行的:
1) 通过计算机视觉的方式,通过图像来识别
通过摄像头捕捉键盘区域的画面并进行分析,判断出键盘输入事件。
2) 通过检测按键发出的声音来判断
这里假设使用者在按键时会碰触桌面,产生一定的敲击声。通过检测该声音传播时间,可以进行定位。该方案在国外的一些研究机构已经实现。
3) 通过超声波雷达手段来判断
通过发射超声波并检测反射波的传播时间查来检测目标物体(手指)的位置。
这3种方案国内外均有文献表明可以实现,不过相对来说计算机视觉的硬件较为简单,仅仅需要一个摄像头,因此这里我们采用这种方式。
下图给出了本制作早期阶段,摄像头所拍摄的使用过程的画面,基于这类画面进行计算机视觉的运算,可以得到我们需要的键盘事件:
图:通过计算机视觉的方式识别并判断键盘输入事件
其实这里涉及到了2个子问题:
- 判断手指按下的是哪个键?
- 如何判断手指已经“按到”了对应的“按钮”?
由于我们人类就是通过视觉来理解外部世界的,因此很直观的可以想到,只要能够识别并定位画面中手指的位置,第一个问题就可以解决了。这里先不讨论定位本身该如何实现,假设我们的算法已经可以和人脑一样轻松在一副画面中找到手指的位置并用相对于图像的坐标来表示(x,y)。
接下来就要考虑第二个问题,如何判断手指已经“按下按钮”?这里一个办法是通过捕捉声音:即像前文提到的通过捕捉手指碰触桌面产生的敲击声来判断。但这样会带来额外的问题:
- 需要额外的硬件和电路,增加了复杂性
- 如何将敲击声与画面中真正敲击的手指对应?就像上图中的5个手指都可能是在敲击状态,此时难以进行匹配
- 其他的噪音也会被当作键盘敲击
因此这里还是依靠视觉的手段来进行判断。在分析可行方案前,需要明确“按下按钮”的具体指标。我们可以定义当手指碰触桌面,或者距离桌面足够接近为“按下”。那么其实问题的实质就是我们需要检测出手指距离桌面的距离z。在求出该数值后,我们只需简单的判断它小于某一个值,就认为手指已经“按下按键”。
综合起来看,我们需要设计一种视觉处理算法:它可以在一副画面中找出每个手指相对画面的位置(x,y),并且手指距离桌面的高度z。事实上我们就是在检测手指的三维空间坐标了(x,y,z)了。
图:需要设计的视觉检测算法和期望的检测结果
如果之前有阅读我的3D激光扫描仪制作的话,相信大家就能猜到具体的实现方式了,其实算法本身就是做三维的激光测距。不过这里我们先按照前文的思路继续分析下去:
做三维测量有很多种方式,比如现在可以购买微软的KINECT深度传感器。如果不考虑成本,这的确是一种非常有效的方法,可以非常好的解决本文提出的这些问题。另一种类似的办法是使用双摄像头来做双目视觉处理,提取目标画面物体的深度信息。不过目前这类处理比较消耗处理资源,且校正过程比较复杂,并不适合这里的应用。
图:RoboPeak团队曾进行的双目视觉进行深度提取的实验
这里我们采用基于三角测距原理的激光测距仪[2]一致的办法,通过主动投射激光来做目标物体的三维坐标检测。在[2]中我使用一束线型激光照射目标物体,在目标物体的反射光被摄像头捕捉到,利用三角测距原理,可以求出目标物体中被线激光照亮部分的坐标信息。
在[2]中提到的利用线激光和单摄像头的3D测距原理
这里我们将线激光所产生的光线平面与桌面平行并紧贴在桌面之上,将摄像头放置于激光发射器上方并俯视桌面,如下图所示:
图:利用激光三角测距原理用于手指空间坐标检测
此时若手指接近桌面,则会阻挡住激光的通路,产生反射,反射的光点画面会被图中摄像头拍摄到。这是一个标准的三角测距的结构设置。细心的读者可能已经发现在前文给出的本制作摄像头拍摄到的画面中手指尖部的白色光斑,这正是安装了线激光器后被手指遮挡产生的反射效果。
图:本制作采用的线激光测距方案
对于这种基于线激光的测距的方式[2],我们可以通过三角关系求出被激光照亮部分相对于激光发射口为原点、位于线激光组成平面内的坐标P(x,y)。而又因为线激光组成的平面与桌面平行,且在设计上这两个平面是紧贴着的,所以可以近似的认为坐标点P(x,y)是位于桌面平面的。
这样的设置具有几个优点:
方便检测指尖
当手指遮挡激光平面后产生了反射,因此会在摄像头画面中出现较为明亮的光斑,可以通过简单的视觉算法来提取指尖部分
方便检测按键事件
由于只有当手指靠近或者碰触到桌面才会遮挡住激光产生反光,而在距离桌面较高的位置则不会被检测算法察觉。因此这里检测按键事件可以做出简化,不需要通过检测手指距离桌面高度来判断。而只要当检测算法检测到手指反光,则可认为出现了按键事件,且可直接用当前检测到的坐标来进行后续的处理。
值得一提的是,事实上这样的方式对从事多点触摸领域朋友来说应该不陌生,有一种称为LLP(Laser Light Plane)的技术[4]和我们的方式很类似。
图:LLP方式的多点触摸技术,图片来源自[5]
如上图所示,LLP技术也通过发射一束线型激光构造出一个光平面,并捕捉手指反光来做多点触摸定位。而摄像头的安装位置也并非一定位于上边示意图的底下,同样也可以安装在本制作一样的位置。事实上这里采用的激光测距方案的前期处理是和LLP一致的:提取手指指尖的兴趣点,并转换成相对于摄像头画面的坐标。不过对于多点触摸而言,不需要得到手指在桌面上的精确距离,就好比我们用的鼠标只需要知道一个相对位移的程度,而不需得到具体鼠标移动了多少毫米。但由于我们需要将手指的坐标转换成具体按键的信息,因此还有必要进行更进一步的处理。
不过相信有人会说这样的方法岂不是和之前通过求出指尖的三维坐标的方式的思路不同吗?的确目前的方式无法直接求得手指距离桌面的高度z。并且接触主动发射线激光的特性,通过求取z来判断是否存在按键事件也显得不必要了。但这并不表示我们无法求解手指距离桌面的高度,并且在后文我将指出,求出手指距离桌面的高度仍旧是有意义的。
判断并产生对应的按键事件
前面我们已经解决了如何检测手指当碰触到桌面时指尖在桌面平面上的坐标P(x,y)。但这与我们最终要产生对应的按键事件还有一定距离。我们需要建立一个映射机制,通过桌面坐标P(x,y)找到对应按键键值,并最终通知操作系统触发一个对应键值的按键事件。
这里的做法与GUI系统进行UI元素碰撞判断的过程类似。在图形系统中,所有UI元素均保存有他们相对于屏幕的坐标值。GUI系统不停地判断当前鼠标指针位置是否落入了某一个按钮或者选择框的坐标范围内。
图:GUI系统通过对比鼠标坐标和按钮UI元素的坐标来判断鼠标是否存在于按钮元素上方
与GUI系统类似,我们首先需要建立投射键盘图案中每个按键的坐标信息。然后将指尖相对于桌面平面上的坐标P(x,y)映射到键盘图案的坐标系内进行按键的判断。
图:将基于桌面平面以激光器为原点的指尖坐标P(x,y)映射到键盘坐标平面并进行按键判断
上述过程涉及到两个步骤:
1) 将以激光发射器为原点的指尖坐标P(x,y)映射到以键盘图案左上角为原点坐标的平面内,得到映射点P’(x,y)
该过程用数学表达记作:
P' (x,y)=fprojection (P(x,y))
2) 将映射点P’(x,y)与事先记录的每个按键的坐标值比对,求得当前对应按下的按键值。
该过程记作:
Key[n]=fmapping (P' (x,y))
可能有人会问为何不直接按照以激光发射器原点的坐标来表示每个按键的坐标?这样第一步的映射f_projection就可以省略了。这的确也可以达到同样的效果。但是由于在组装上会存在误差,不能保证每次制作出来的成品激光发射器与键盘图案投射的位置都完全一致,并且单个成品在使用过程中也会因为热胀冷缩等原因,键盘图案会发生偏移。一旦键盘图案发生了移动,则先前以这种方式记录的所有按键坐标都需要重新测量。但如果一开始就以键盘左上角为原点的方式记录坐标,则每次组装完成品或者发生图案偏移后,则只需进行简单的矫正,求出一个新的f_projection函数即可。
对于步骤2)中的函数f_mapping,一种简单的实现是依次按照前文例图中的判断代码对每个按键轮流计算,判断是否被“按下”。这种方式实现简单直观,但是性能较差。对于这类问题,可以使用Kd-Tree的数据结构[3]进行快速的查找。
系统框图
前面我们解决了制作激光投影键盘的两个关键问题,这里将我们最终采用方案的大致原理做出总结,方便大家理解。在实现过程部分,将具体就其中的实现细节做出介绍。
框图中还包含了本制作的另一个功能:多点触摸绘图板。该部分也将在具体制作过程中介绍。
实现过程
器件选择
有前面的原理分析可知,本激光键盘至少需要摄像头、投射键盘画面的激光器以及一字线激光。如下是我选用的器件和参数
元件
|
核心参数
|
摄像头
|
广角镜头,视角>120度
|
投射键盘画面的激光器
|
无特殊要求
|
一字线激光
|
红外激光器,>50mW
|
红外带通滤光片
|
800nm左右光谱带通
|
对于摄像头,这里一个比较关键的特性是需要采用广角镜头。目前的USB摄像头一般视角在90度左右,这样的摄像头需要在很高处俯视才能拍摄到完整的激光键盘图案,如果想把本投影键盘制作的小巧,则需要采用广角镜头,视角最好在120度以上。
图:窄视角的摄像头需要安装在较高的位置
除了镜头外,摄像头本身没有特殊要求,一般市面VGA画质的普通USB摄像头即可满足要求。下图为我采用的镜头和摄像头照片:
图:两种不同视角的摄像头镜头,左边为窄视角镜头,右边为广角镜头
图:USB摄像头模组
对投射键盘图案的激光发射器模组前文已经提到,且没有特殊要求。
图:选用的激光键盘图案投射模组
对用于测距的激光发射器,只需要使用红外波段的一字线激光器,功率在50mW左右即可。为了安全考虑,不要使用过大功率的激光器。采用红外波段主要为了过滤可见光干扰,简化视觉处理中的兴趣点提取,同时也不会因为手指反射对投射的键盘图案产生干扰。
图:选用的红外线型激光器
摄像头改装
在我之前的3D测距仪文章[2]中提到过使用红外激光器配合红外滤光片进行测距可有效避免可见光干扰的技巧,在这里也仍旧适用。对此我们需要对摄像头镜头做一些改造,首先拆除镜头上的红外光截至滤光片,并在镜头头部安装红外带通滤光片:
图:拆除镜头内的红外截止滤光片
图:在镜头表面安装红外带通滤光片
电子系统
本制作的电子系统比较简单,仅仅涉及给两个激光发射器供电以及通过USB电缆连接摄像头至主机。并没有采用任何单片机,这样也意味着之前原理部分介绍的算法将完全在PC上实现。这样的优点是大幅降低了制作成本以及制作的难度。如果使用的是免驱动USB摄像头,在PC上使用本激光投影键盘只需要额外运行处理程序即可。不过缺点就是这样的设计无法给手机等不支持USB的设备使用。
由于摄像头已经使用了一条USB电缆,因此这里我们直接通过usb的5V供电来驱动另外2个激光器。电路很简单,如下图所示:
可以看到电路的核心就是一个3.3V的LDO芯片而已,可以裁剪一个洞洞板制作:
图:使用小块洞洞板制作简易的驱动电路
总体安装
由前面的分析可以得到如下的安装结构:
其中线型激光器需要安装在设备的最底下并紧靠底部,这样可以保证产生的激光平面能够尽可能的靠近桌面平面。在激光器上方安装投射键盘图案的激光模组,他的高度以能够投射出与常规键盘尺寸大小类似的图案来决定。在最顶端安装摄像头,其高度取决于摄像头能够完整拍摄整个键盘图案画面为宜。
我使用一块轻质木材作为安装这3个部件的整体支架:
图:将激光器安装在木板最底部,使用热熔胶固定
图:安装图案投射模块和摄像头并点亮
图:在木板背面安装稳压电路板和所有供电连线
图:将木板装入一个牢固的纸盒
图:完成并通电
图:顶部加装一个“保护罩”
最终本制作的实体部分组装完毕,接下来将介绍本制作的重点:视觉算法部分。