在这篇文章中,将构建一个简单的激光手势识别应用程序,并使用它来控制Windows Media Player。这比使用遥控器更方便,因为不需要在黑暗中寻找正确的按钮。只需要在摄像头的视野范围内用激光笔做一些简单的手势,就可以了!这个程序可以识别在墙上用激光笔做的简单手势,比如左、右、上、下,以及两个向下和两个向上的对角线。这个程序可以修改以识别更多的手势;然而,由于没有采用神经网络方法进行图像识别,它不能识别复杂的手势。
第一步是将视频流引入应用程序。可以使用DirectX的组件DirectShow来实现这一点。直接使用了Andrew Kirillov的运动检测代码(经许可)进行图像采集。修改了MotionDetector1.cs中的代码以执行激光手势识别。
程序在其视野范围内搜索最亮的像素(在例子中是激光点),其亮度高于某个阈值。像素的亮度可以使用其RGB值通过一个简单的公式计算得出:
Luminance = (299 * red + 587 * green + 114 * blue) / 1000
找到像素后,它分析该点沿x轴和y轴移动了多少。基于这些参数,程序尝试识别移动。例如,如果激光点沿x轴的移动远大于沿y轴的移动,程序将确定它是或多或少的水平移动。然后,根据激光点的初始和最终位置,它将确定移动是向左还是向右。它使用类似的技术来检测向上、向下和对角线移动。
对于控制Windows Media Player,程序简单地模拟Media Player使用的某些键盘快捷键。这段代码可以跳到下一个/上一个音轨,或者根据程序识别的手势播放、暂停、停止音轨:
C#
//
Get a handle to an application window.
[DllImport(
"
USER32.DLL"
)]
private
static
extern
IntPtr
FindWindow(
string
lpClassName,
string
lpWindowName);
//
Activate an application window.
[DllImport(
"
USER32.DLL"
)]
private
static
extern
bool
SetForegroundWindow(
IntPtr
hWnd);
private
void
ControlMediaPlayer(
string
gesture)
{
IntPtr
mediaPlayerHandle =
FindWindow(
"
WMPlayerApp"
,
"
Windows Media Player"
);
//
Verify that WMP is a running process.
if
(mediaPlayerHandle ==
IntPtr
.Zero)
{
System.Windows.Forms.MessageBox.Show(
"
WMP is not running."
);
return
;
}
switch
(gesture)
{
case
"
LEFT"
:
SetForegroundWindow(mediaPlayerHandle);
SendKeys.SendWait(
"
^b"
);
break
;
case
"
RIGHT"
:
SetForegroundWindow(mediaPlayerHandle);
SendKeys.SendWait(
"
^f"
);
break
;
case
"
UP"
:
SetForegroundWindow(mediaPlayerHandle);
SendKeys.SendWait(
"
^s"
);
break
;
case
"
DOWN"
:
SetForegroundWindow(mediaPlayerHandle);
SendKeys.SendWait(
"
^p"
);
break
;
}
}
由于程序在摄像头的视野范围内搜索最亮的像素,所以房间的照明条件会影响其性能。因此,请调整亮度阈值和照明条件,以确保除了激光之外没有东西超过亮度阈值。
在本文提供的示例程序中,用于控制Windows Media Player的手势如下:
也可以很容易地修改代码,使用对角线手势来控制音量。