自制激光虚拟投影键盘 激光投影键盘多少钱

先上一个小视频,是我自制的键盘demo。


再上一张实物图,够山寨把:
虚拟激光投射键盘在1992年就由IBM发明了。我第一次看到这玩意儿就觉得特别新奇,后来看到淘宝上棒子的产品,要900多米,实在是宰人啊。于是就一直有想法做一个。不久前在淘宝看到了投射键盘图案的激光模组,果断买了一个,开始筹划制作一个。
taobao上买的650nm虚拟键盘激光组件:
而且现在有了强大的opencv图像处理库,实现这样的虚拟激光投射键盘变得易如反掌。
先说说投影键盘的基本原理。键盘由三个主要部件组成:摄像头、键盘图案投射器、一字线性感应激光头。见下图:
图上从上到下分别是键盘图案投射器、摄像头、一字线性感应激光头。当然,摄像头放在键盘图案投射器上面也是可以的,比如我就是这么做的。1.键盘图案投射器在平坦的桌面投出清晰键盘图案2.最底下的一字线性激光(一般采用红外线的,这样眼睛不可见)发出一字型激光,平行于桌面射出,这样如果手指有按键活动,会在手指上形成激光光斑3. 摄像头捕获激光光斑,对应于键盘图案映射的位置,就可以知道哪些键被按下OK,原理很简单,是不是。有了这些模块,剩下的关键就是摄像头的图像处理算法了,而且现在有了opencv,实现也不是难事。这里说一下我的实现方法。

由于人眼对激光的反应不一样,780nm-808nm的激光人眼不敏感,可看到微弱的一丝红光。850nm至1064nm波长人眼不可见,通过红外感光仪器等专业设备可以看到,其中808-850nm通过摄像头可以看到。980-1064nm通过倍频片可以看到。

所以我在网上买了一个808nm-810nm红外一字线激光器。这样配上滤光片,可以滤去绝大多数其他波长的杂光,只剩下红外激光的光斑。这样做的好处是减少干扰,增加键盘的可靠性,而且使算法处理更加简单有效。加上前面的650nm虚拟键盘激光组件,总共也就花了100块钱左右。
25mw 808nm-810nm 红外一字线激光器 激光头

直径18mm可见光截止400-750nm滤光片,800-1000nm高透
在摄像头上看到的红外激光光斑投射到手 指的图像如下图:
对于光斑的跟踪我找了个现成的opencv扩展库cvblob,具体可以参考它的文档和例子,googlecode上有这个项目的托管。待会儿会奉上代码。cvblob可以跟踪多个光斑,所以很容易就可以实现ctrl+alt+delete之类的组合键。
再来两张键盘图:




顺便说一句,本文中的摄像头放的位置只能捕捉到部分键盘图像,所以demo只是演示了部分键盘的按键。不过丝毫不影响原理介绍。如果要获得全部键盘图像,或者去买一个广角的摄像头,或者把这个摄像头位置提高,不是什么难事。时间有限,不想折腾了。


代码:
C++语言: 高亮代码由发芽网提供#include<iostream>
#include<iomanip>

#include"opencv/cv.h"
#include"opencv/highgui.h"

#include"cvblob.h"
usingnamespacecvb;

typedefstructkey
{
charc;
int x0;
int y0;
int x1;
int y1;
};

key g_keymap[] =
{
{'4',525,350,588,419},
{'5',442,345,504,414},
{'6',360,339,422,408},
{'7',277,332,342,404},
{'8',198,327,259,399},
{'9',121,320,174,389},
{'0',41, 318,94, 383},
{'E',528,274,590,337},
{'R',443,267,507,332},
{'T',359,263,428,327},
{'Y',280,259,344,321},
{'U',199,251,261,315},
{'I',119,246,179,307},
{'O',41, 240,96, 301},
{'D',504,203,567,259},
{'F',424,199,489,257},
{'G',348,194,410,251},
{'H',266,187,329,245},
{'J',192,183,251,241},
{'K',117,178,171,236},
{'L',42 ,174,92, 229},
{'X',543,144,605,197},
{'C',467,139,530,191},
自制激光虚拟投影键盘 激光投影键盘多少钱
{'V',392,135,457,190},
{'B',316,128,377,181},
{'N',242,124,299,176},
{'M',171,118,225,172},
{'<',98, 114,149,166},
{'>',26, 108,73, 159},
{'_',182,62, 531,127},
};

intg_key_num = sizeof(g_keymap)/sizeof(key);

intmain()
{
CvTracks tracks;

cvNamedWindow("red_object_tracking", CV_WINDOW_AUTOSIZE);

CvCapture *capture = cvCaptureFromCAM(0);
cvGrabFrame(capture);
IplImage *img = cvRetrieveFrame(capture);

CvSizeimgSize = cvGetSize(img);

IplImage *frame = cvCreateImage(imgSize, img->depth, img->nChannels);

IplConvKernel* morphKernel = cvCreateStructuringElementEx(5,5, 1, 1, CV_SHAPE_RECT, NULL);

//unsigned intframeNumber = 0;
unsignedintblobNumber = 0;

boolquit = false;
while(!quit&&cvGrabFrame(capture))
{
IplImage *img = cvRetrieveFrame(capture);

cvConvertScale(img, frame, 1, 0);

IplImage *segmentated = cvCreateImage(imgSize, 8, 1);

// Detecting redpixels:
// (This is very slow,use direct access better...)
for(unsignedintj=0; j<imgSize.height; j++)
for(unsignedinti=0; i<imgSize.width; i++)
{
CvScalar c = cvGet2D(frame, j, i);

double b= ((double)c.val[0])/255.;
doubleg = ((double)c.val[1])/255.;
doubler = ((double)c.val[2])/255.;
// unsigned char f =255*((r>0.2+g)&&(r>0.2+b));
//cvSet2D(segmentated, j, i, CV_RGB(f, f, f));
if(b>0.4 || g>0.4 || r>0.4)
cvSet2D(segmentated, j, i, CV_RGB(255, 255, 255));
else
cvSet2D(segmentated, j, i, CV_RGB(0, 0, 0));
}

cvMorphologyEx(segmentated, segmentated, NULL, morphKernel, CV_MOP_OPEN, 1);

cvShowImage("segmentated", segmentated);

IplImage *labelImg = cvCreateImage(cvGetSize(frame), IPL_DEPTH_LABEL, 1);

CvBlobs blobs;
unsignedintresult = cvLabel(segmentated, labelImg, blobs);
cvFilterByArea(blobs, 500, 1000000);
cvRenderBlobs(labelImg, blobs, frame, frame, CV_BLOB_RENDER_BOUNDING_BOX);
cvUpdateTracks(blobs, tracks, 200., 5);
cvRenderTracks(tracks, frame, frame, CV_TRACK_RENDER_ID|CV_TRACK_RENDER_BOUNDING_BOX);

cvShowImage("red_object_tracking", frame);

// printkey
for(CvTracks::const_iterator it=tracks.begin(); it!=tracks.end(); ++it)
{
intxx = (int)it->second->centroid.x;
intyy = (int)it->second->centroid.y;
//std::cout<< xx<< ','<< yy<< std::endl;

for(inti=0; i<g_key_num; i++)
{
if(xx > g_keymap[i].x0 &&
xx<g_keymap[i].x1 &&
yy>g_keymap[i].y0 &&
yy<g_keymap[i].y1)
{
std::cout <<g_keymap[i].c <<std::endl;
break;
}
}
}

cvReleaseImage(&labelImg);
cvReleaseImage(&segmentated);

chark = cvWaitKey(10)&0xff;
switch(k)
{
case27:
case'q':
case'Q':
quit= true;
break;
case's':
case'S':
for(CvBlobs::const_iterator it=blobs.begin(); it!=blobs.end(); ++it)
{
std::stringstream filename;
filename <<"redobject_blob_"<<std::setw(5) <<std::setfill('0') <<blobNumber <<".png";
cvSaveImageBlob(filename.str().c_str(), img, it->second);
blobNumber++;

std::cout <<filename.str() <<" saved!" <<std::endl;
}
break;
}

cvReleaseBlobs(blobs);

//frameNumber++;
}

cvReleaseStructuringElement(&morphKernel);
cvReleaseImage(&frame);

cvDestroyWindow("red_object_tracking");

return0;
}

  

爱华网本文地址 » http://www.413yy.cn/a/25101016/312388.html

更多阅读

激光脱毛有副作用吗 激光脱毛一般多少钱

激光脱毛有副作用吗?近几年来,选择激光脱毛的人士越来越多,但一些女性表示对激光脱毛存在一大疑虑,她们担心激光脱毛后会出现副作用,针对这个实在性的问题,请有关专家为大家做出详细介绍。疑虑之一、激光脱毛影响排汗吗? 有的网友

近视眼激光手术价格 眼睛激光要多少钱

近视眼激光手术价格——简介 虽然近视眼,但还是不想戴眼镜,隐形眼镜又太干,怎么办?看来唯一的方法就是去做近视眼激光手术了。听说眼睛近视手术费用是笔大收费,近视眼激光手术价格要多少钱?近视眼激光手术价格——工具/原料

背投互动投影系统方案 虚拟投影互动系统

系统功能说明北京怡和佳宁Hiwodtouch背投式互动系统又称为橱窗互动、玻璃幕互动、立面互动展示系统。实现用手指或其它自然物品在投影屏幕上的触摸选择,打开界面、转换画面、信息查询等控制功能。用户不仅可以观看到高画质投影的图

笔记本键盘维修全过程 笔记本键盘维修多少钱

实例图解:联想笔记本键盘维修全过程文/罗建勇  今天客户送来一台联想昭阳E255笔记本电脑,说是喇叭位置进了些水开机就一直报警不断的响。进入系统后报警声音就消失。首先让我们先来看看联想的这款机子联想昭阳E255联想昭阳E255全身

声明:《自制激光虚拟投影键盘 激光投影键盘多少钱》为网友眼淚磨成細沙分享!如侵犯到您的合法权益请联系我们删除