-
基于
Aforge
的手势识别之二
~~~
单点手势识别<
/p>
分类:
计算机视觉
2010-05-04 13:46
9058
人阅读
评论
(12)
收藏
举
报
ima
geprocessing
图形
objectc
本文来自
/hellogv/
,引用必须注明出处!
本文把
Aforge
的运动识别
与
前面介绍的手写识别
融合在一起,
实现单个手指的手势识别。
下图演示了本文代码运行的结果,
图片有
点大,请稍候。。。
我预先让程序学习了
B
和
C
这两个字母,然后通过手指的手势
识别向程序绘画图形,
所以点击
rec
orgize
时,
就自动把图形的特征
对应的字母给识别出来了。
这个例子关键部分在于如何灵活运用
Aforge
的运动识
别,
如何
判断是要画图,
还是普通的移
来移去呢?在这里,
我判断移动对象的
大小,当突然面积增大<
/p>
(
即两个指套合并
)
则开始绘图
(
手势识别的开
始
p>
)
,
当拆开再合并则为解除绘图
(
手势识别的结束
)
,<
/p>
说白了就是用一
个当前状态
=!
当前状态去做。
本文的代码可以到这里下载:
/source/2313846
下面贴出运动判断的核心代码:
[c-sharp]
view
plaincopyprint?
1.
private
void
videoSourcePlayer1_NewFrame(
object
sender,
ref
Bitmap image )
2.
{
3.
nowImg = (Bitmap)();
4.
5.
Bitmap
objectImage = ( image
);
6.
7.
// lock image for further
processing
8.
BitmapData
objectData = ts(
new
Rectangle( 0, 0, ,
)
,
9.
ly,
ormat
);
10.
11.
// grayscaling
12.
UnmanagedImage grayImage =
(
new
UnmanagedImage( objectData ) );
13.
14.
// unlock
image
15.
Bits( objectData );
16.
17.
// locate blobs
18.
sImage( grayImage );
19.
List
new
List
);
20.
ge(ectsRectan
gles());
21.
22.
if
( >0 )
23.
{
24.
#region
去掉内部和黏在一起的对象
25.
for
(
int
i = 0; i < - 1;
i++
)
26.
{
27.
//tru
e
表示
X
轴上不能相交,
false
表示相
交
28.
Boolean isNoTouchX =
(rects[
i + 1].Right , rects[i].Right) -
(rects[i
+ 1].Left ,rects[i].Left) >
(rects[i].Width + re
cts[i + 1].Width);
29.
//true
表示
Y
轴上不能相交,
false
p>
表示相
交
30.
Boolean isNoTouchY = (rects[
i +
1].Bottom, rects[i].Bottom) - (rects[
i
+ 1].Top, rects[i].Top) > (rects[i].Height +
re
cts[i + 1].Height);
31.
if
(isNoTouchX ==
false
&&
isNoTouch
Y ==
false
)
//
如果两个对象相交
32.
{
33.
Rectangle rect =
new
Rectangle(M
(rects[i].Left, rects[i +
1].Left),
34.
(rects[i].Top, rects
[i + 1].Top),
35.
(rects[i].Right,
rec
ts[i + 1].Right) - (rects[i].Left,
rects[
i + 1].Left),
36.
(rects[i].Bottom, re
cts[i + 1].Bottom)
- (rects[i].Top, rects
[i + 1].Top));
37.
At(i + 1);
38.
At(i);
39.
40.
(rect);
41.
i = 0;
42.
}
43.
}
44.
#endregion
45.
46.
#region
画出表示点
47.
Rectangle objectRect = rects[0];
48.
49.
int
oldSize=+
;
50.
int
nowSize=rects[0].Width+rects[0].Heig
ht;
51.
52.
if
(nowSize > (oldSize * 1.2
))
//
如果突然
变大,即两个指套合
并
53.
{
54.
isCapture
=!isCapture;
55.
();
56.
}
57.
58.
Graphics g = age(image);
59.
60.
if
(isCapture)
//<
/p>
如果捕捉到对象
61.
{
62.
Pen pen =
new
Pen(gb(255
,
0, 0), 3);
63.
ctangle(pen,
objectRect);
64.
int
x = ( +
objectRec
/ 2) * /
videoSourcePlayer1.
Width;
65.
int
y = ( +
objectRect
.Height / 2) * /
videoSourcePlayer1
.Height;
66.
(x,y );
67.
}
68.
else
//
如果没有捕捉到对象
p>
69.
{
70.
Pen pen =
new
Pen(gb(160
, 255, 160), 3);
71.
ctangle(pen, objectRect);
72.
}
73.
74.
e();
75.
76.
#endregion
77.
78.
oldRect = rects[0];
79.
80.
}
81.
82.
UpdateObjectPicture(objectImage );
83.
84.
}
基于
Af
orge
的手势识别之三
~~~
多点手
势识别
分类:
计算机视觉
2010-05-07 12:54
8158
人阅读
评论
(11)
收藏
举
报
ima
geprocessingobject
图形
c
本文来自
/hellogv/
,引用必须注明出处!
上次介绍了
单点手势识别
,这次就继续
介绍一下如何实现多点
手势识别,
先来看看本文实现的效果图,
图片有点大,
请稍候。
。
。
:
我预先让程序学习了
B
和
C
这两个字母,第一个对象通过点击
鼠标左键去选择颜色
(
对象为绿色
p>
)
,第二个对象通过点击鼠标右键去
选择颜
色
(
对象为红色
)
,然后通过两支手指的手势识别分别向程序绘
画图形,
所以
点击
recorgize
时,
就自动把
图形的特征对应的字母给
识别出来了。
本文上一篇文章的延伸,如图中所示,这里通过
一个对象的消
失
/
重现来识别是否开始
绘图,
当突然消失
/
重现则开始绘图,
再次消
失
/
重
现则停止绘图。本文的代码可以到这里下载:
/source/2323958
接下来贴出本文的核心代码:
[c-sharp]
view
plaincopyprint?
1.
private
void
videoSourcePlayer1_NewFrame(
object
sender,
ref
Bitmap image )
2.
{
3.
//
保存捕获到的对象
4.
List
new
List
[2];
5.
6.
Bitmap[]
objectImage =
new
Bitmap[2];
7.
for
(
int
i = 0; i < ObjectSum; i
++)
//
捕获对
象
< br>
8.
{
9.
nowImg[i] = (Bitmap)();
10.
11.
objectImage[i] =
colorFilter[i].Apply(no
wImg[i]);
12.
13.
// lock
image for further processing
14.
BitmapData objectData = objectIm
age[i].L
ockBits(
new
Rectangle(0, 0, ,
ight),
15.
ly,
ormat);
16.
17.
//
grayscaling
18.
UnmanagedImage grayImage =
new
Grayscale
BT70
9().Apply(
new
UnmanagedImage(objectData));
19.
20.
// unlock
image
21.
objectImage[i].UnlockBits(objectData);
22.
23.
//
从颜色中筛选有效的对象
24.
blobCounter[i].ProcessImage(grayImage);
25.
rects[i] =
new
List
26.
rects[i].AddRange(blobCounter[i]
.GetObje
ctsRectangles());
27.
28.
//
如果当前对象
p>
i
不存在,并且原有的对象
i
又是
存在的,则表示是对象
i
隐藏起来了
29.
if
(rects[i].Count == 0 &&
oldRect[i].Is
Empty ==
false
)
30.
{
31.
isCapture[i] = !
isCapture[i];
//
改变为
反模式
32.
clsHandWrite[i].Clear();
33.
}
34.
else
if
(rects[i].Count > 0)
//
如果当前对
象
i
p>
存在
35.
{
36.
#region
去掉内部和黏在一起的对象
37.
for
(
int
ii = 0; ii <
rects[i].Count
- 1; ii++)
38.
{
39.
/
/true
表示
X
轴上不能相交,
p>
false
表
示相交
40.
Boolean
isNoTouchX = (re
cts[i][ii + 1].Right,
rects[i][ii].Right) -
Math.
Min(rects[i][ii + 1].Left,
rects[i][ii].Left) >
(
rects[i][ii].Width + rects[i][ii +
1].Width);
41.
/
/true
表示
Y
轴上不能相交,
p>
false
表
示相交
42.
Boolean
isNoTouchY = (re
cts[i][ii + 1].Bottom,
rects[i][ii].Bottom) - Mat
(rects[i][ii
+ 1].Top, rects[i][ii].Top) >
(
rects[i][ii].Height + rects[i][ii +
1].Height);
43.
if
(isNoTouchX ==
false
&&
isNoT
ouchY ==
false
)
//
如果两个对象相交
44.
{
45.
Rectangle rect =
new
Rectang
le((rects[i][ii].Left,
rects[i][ii + 1].L
eft),
46.
(rects[i][ii].To
p, rects[i][ii +
1].Top),
47.
(rects[i][ii].Ri
ght, rects[i][ii +
1].Right) - (rects[i][
ii].Left,
rects[i][ii + 1].Left),
48.
(rects[i][ii].Bo
ttom, rects[i][ii +
1].Bottom) - (rects[i
][ii].Top,
rects[i][ii + 1].Top));
49.
rects[i].RemoveAt(ii + 1);
50.
rects[i].RemoveAt(ii);
51.
52.
rects[i].Add(rect);
53.
ii = 0;
54.
}
55.
}
56.
#endregion
57.
58.
#region
画出表示点
59.
Rectangle objectRect = rects[i][0];
/
/
只取得该对象第一个矩阵
60.
Graphics g =
age(imag
e);
61.
62.
if
(is
Capture[i])
//
如果捕捉到对象
< br>
63.
{
64.
Pen pen =
new
Pen(gb
(255, 255, 255), 3);
65.
ctangle(pen, objectRect)
;
66.
int
x = ( + objec
/ 2) * / videoSourcePla
;
67.
int
y = ( +
object
/ 2) * /
videoSourcePl
;
68.
clsHandWrite[i].Draw(x, y);
69.
}
70.
else<
/p>
//
如果没有捕捉到对象
71.
{
72.
Pen pen =
new
Pen(gb
(160, 255, 160), 3);
73.
ctangle(pen, objectRect)
;
74.
}
75.
76.
e();
77.
78.
oldRect[i] =
new
Rectangle()
;
//
初始
化
79.
oldRect[i] = rects[i][0];
80.
#endregion
81.
}
82.
}
83.
Cls_ObjectPicture(
ref
pictureBo
x1, objectImage[0]);
//
显示过滤颜色的对象
1
84.
Cls_ObjectPicture(
ref
pictureBo
x2, objectImage[1]);
//
显示过滤颜色的对象
2
85.
}
86.
87.
/
//
88.
/
//
选择绿色的物体为识别的对象
89.
/
//
90.
p
rivate
void
videoSourcePlayer1_Mous
eUp(
object
s
ender, MouseEventArgs e)
91.
{
92.
if
( == )
//
点击左键,
识别绿色对象
93.
Cls_een(nowImg[0],
ref
colo
rFilter[0], e.X, e.Y);
94.
else
if
( ==
)
//
点击右键,识别红色对象
95.
Cls_d(nowImg[1],
ref
colorF
ilter[1], e.X, e.Y);
96.
}
手手势识别
通过
安德鲁
Kirillov
一些想法关于手手势识别在静止图像和视频。
示例应用程序
(
源
)- 149 k
示例应用程
序
(
二进制
)- 130
k
样例视频
# 1 - 7290
k
样例视频
# 2 - 11084
k
发布
:
2008
年
10
月
12
日
更新
:
2010
年
2
月
16
日
< br>
编程语言
:
C#
AForge
。
NET
框架
:
2.1.1
介绍
自从我写了第一篇关于运动检测
的文章
,
我有很多
< br>电子邮件来自世界各地不同的人
,
发现这篇文
章相当
有用
,
发现许多应用程序的代码在许多不同的领域。
那些
地区包括从简单的视频监控工<
/p>
具相当印象应用程序
,
像激光手势识别
,
检测与望远镜彗星
,
检测只蜂鸟
并使镜头的控制高压水
< br>炮和许多其他应用程序。
在本文中
,
我想讨论一个应用程序
,
它使用
运动
检测的第一步
,
然后做一些有趣的检测例程
对象
——
手手势识别。
让我们假定我
们有一个相机
,
显示器
一些区域。
当有人进入该地区
,
使一些
手手势在前面
的相机
,
应用程序应该检测类型的
姿态
,
提高事件
,
为例。
当检测到双手手势识别
时
,
应用程序可能
执行不同的操作取决于类型的姿态。
例如
,
手势
识别应用程序可以控制一些
设备或另一个应用程序发送
不同的命令根据公认的姿态。
什么样的手
手势我们谈论吗
?
这个
特定的应用程序
,
这是在讨论
篇文章
,
可能认识
15
手势
,
这是
4
个不同位置的组合
2<
/p>
手的手不提
高
,
斜斜向下
,
或提高
直。
本文中描述的算法都是基于
p>
框架
,
它提供了
不同的图像处理应用程序使用的例
程。
的
应用程序也使用一些运动检测例程
,
受到启发
另一篇文章的框架和专用的
运动检测
。
在我们进入深入讨论什么应用程序
,
以
及它是如何
实现
,
让
?
年代看看很快演示
……
运动对象检测和提取
我们可以开始双
手手势识别之前
,
首先我们需要提取
人类吗
?
年代的身体
,
这表明一些手势
,
找
到一个好的时刻
,
当
实际应该做手势识别。
我们要对这两个任务
重用一些运动检
测的想法中描
述致力于运动检测
篇文章。
为对象提取任务我们要使用
的方法
,
基于背景
建模。
让吗
?
年代假设视频的第一帧不包含任何
移动
对象
,
但仅仅包含一个背景场景。
p>
当然这样的假设不能调用情况下有效。
但是
,
首先
,
它可能是有效的
对于大多数的情况下
,
所以
很适用
,
和第二个
?
我们的算法
自适应
< br>,
所以它可以处理情况下
,
不仅
当第一帧包含背景。
但是
,
我们呢
?
年代连续
……
所以
< br>,
我们的拳头框架可以作为背景的近似
框架。
/
/
检查背景帧
如果
(backgroundFrame = = null)
{
/
/
保存图片尺寸
宽度
=
身高
=
frameSize
=
宽
*
高
;
/
/
创建初始背景图像
bitmapData = ts(
新矩形
< br>(0,0,
宽度、高度
),
ImageLockMode
。
PixelFormat
只读的。
Format24bppRgb);
/
/
应用灰度滤波器获得非托管的形象
backgroundFrame =
grayscaleFilter
。
应用
(
新
UnmanagedImag
e(bitmapData));
/
/
打开源图像
的形象。
UnlockBits(bitmapData);
…
}
现在来吗
?
年代后假设当我们收到一
个新的框架
,
其中包含一些对象
,
p>
和我们
任务是提取它。
当我们有两个图像<
/p>
,
图像的背景和对象
,
< br>我们可以使用
区别
过滤得到一个不同的形象
:
/ /
锁定源图像
bitmapData = ts(
新矩形
< br>(0,0,
宽度、高度
),
ImageLockMode
。
PixelFormat
只读的。
Format24bppRgb);
/
/
应用灰度过滤器
grayscaleFilter
。
应用
(
新
Un
managedImage(bitmapData)currentFrame);
/ /
打开源图像
的形象。
UnlockBits(bitmapData);
/
/
设置背景帧作为不同的覆盖过滤器
differenceFilter
。
UnmanagedOverlayImage = backgroundFrame;
/
/
应用不同过滤器
differenceFilter
。
应用
(currentFrame
motionObjectsImage);
差分图像可以看到绝对区别两个图片吗
?
更白
区域显示更高的地区差异和黑色
区域显示领域
的没有区别。
的
下一个两个步骤
:
1.
阈值图像使用的区别
阈值
过滤器
,
所以对每个
像素进行分类
重大变化
(
最有可能造成移
动对象
)
或无显著变化。
2.
去除噪声的图像使用阈值差异
开放
过滤器。
在这一步
独立的像
素
,
这可能是造成嘈杂
的相机和其他的
情况下
,
将被删除
,
所以我们吗
?
会有一个图像
,
这只描述了或多或少的
改变
< br>(
运动区域
)
的重要领域。
p>
/
/
应用阈值过滤
thresholdFilter
。
ApplyInPlace(motionObjectsImage);
/ /
打开过滤器适用于去除噪声
openingFilter
。
ApplyInPlace(motionObjectsImage);
看起来我们
有不错的手动作形象
,
下一步我们准备好了吗
< br>?
识别
……
还没有。
的对象吗
?
年代
图像我们很识别作为一个例子代表了人类
?
的身体
,
展示了我们一些手的姿势。
但是
p>
,
之前我们
会得到这样的形象在我们的视频
中
,
我们呢
?
我收到一个
许多其他的框架
,
我们可能会有很多其
他不同的对象
,
这远非人类的身体。
这样的对象可能是别的越过现场
,
或甚至可能相当大的噪声
p>
比
我们过滤掉。
摆脱一些错误的对象
,
让
?
通过图像中的所有对象
并检查它们的大小。
为实
现这一目标我们将使用
BlobCounter
类
:
/
/
处理
blob
blobCounter
。
ProcessImage(motionObjectsImage);
Blob[]=
blobCounter
废品。
GetObjectInformation();
int
最大尺寸
= 0;
Blob maxObject =
新
Blob(0,
新矩形
(0,0,0,0));
/
/
找到最大的
blob
如果
(
斑点
!
= NULL)
{
foreach(Blob Blob
Blob)
{
int blobSize =
gle
。
宽度
*
如果
(blobSize
>
最大尺寸
)
{
最大尺寸
= blobSize;
maxObject =
斑点
;
}
}
}
我们将如何使用信息最大的对象吗
?
年代的尺寸吗
?
首先我们要
实现自适应的背景
,
我们呢
?
前面提到的。
假设时间可能会有
小场景的变化
p>
,
如轻微改变光的条件下
,
甚至是一些运动的小对
象
小对象出现在现场。
考虑到这些变化
,
我们要
自适应背景
?
我们要改变我们的背景
框架
(
这
是最初的初始化
第一视频帧
)
的方向变化
致力于
过滤器。
的
致力于
过滤器的变化略一个图像的
方向与第二提供图像产生较小的影响。
例如
,
如果我们有一个背景图像
,
其中包含场景
,
一个物体
的图像
,
其中包含的
同一
场景加上一个对象
,
然后按顺序应用
致
力于
过滤背景图像
,
将对象图像
经过一段时间的一样吗
?
我们应用
致力于
过滤器的背景
形象
,
更加突出成为对象的存在
(
p>
背景图
像变得
“
更
”
对象形象吗
?
< br>变得更小
)
的区别。
所以
,
我们正在检查当前帧中的最大对象的大小
,
如果不是那么大
,
< br>我们考虑
对象不重要
,
我们只
是更新我们的背景框架
,
适应变化
:
/ /
如果我
们只有小物体
,
我们采用场景的变化
如果
(gle
。
宽度
< 20)|
|(gle
。
高度
>
20))
{
/
/
移动对当前帧的背景
moveTo
wardsFilter
。
UnmanagedOverlayImage = currentFrame;
m
oveTowardsFilter
。
ApplyInPlace(backgroundFrame);
}
第二个最大的使用对象
?
年代大小是
找到一个
,
这是很重要的
,
哪些可能
是一个人吗
?
年代的身
体。
为了节省
CPU
时间我们的手手势识别算法不会分析任何对象
,
在当前帧是最大的
,
但只有
对象满足一些要求
:
如果
(gle
。
宽度
> = minBodyWidth)& &
(gle
。
高度
> = minBodyHeight)& &
(! firstFrame))
{
/ /
做进一步处理的框架
}
好
,
现在
我们有一个形象
,
其中包含移动对象
,
对象的大小是很合理
,
所以它可能是一
个
人类吗
?
身体可能。
我们准备通过手手势识别模块的图像进一步处理
?
再一次
,
没有
……
是的
,
我们呢
p>
?
已经检测到一个相当大的对象
,
这可能是一个人吗
?
年代的身体展示一些姿态。
但是
p>
,
如果对象
还在动吗
?
如果对象没有停止
,
它还没有准备好证明我们真正的姿态将
想展示
吗
?
我们真的想通过所有这些框架手手势识别模块
,
对象是什么
p>
还在运动
,
加载
我们的
CPU
计
算
?
更多的
,
因为对象运动仍在<
/p>
,
我们甚至可以检测到
的姿态
,
不是想展示的对象。
那么
,
我们
呢
?
没有匆忙与手势识别。
后我们发现的
,
这是一个候选人进行进一步的处
理
,
我们想给它一个机会停下来
p>
一段时间
,
证明
我
们一些吗
?
一个手势。
如果对象是不断移动
,
我们不想证明什么
,
所以我们可以跳过其处理。
捕捉的时刻对象已经停止
,
我们将使用另一个运动检
测器
,
基于帧间差异。
运动探测器检查两个
后续视频帧之间的数量变化
(
当前和前一个
),
< br>根据这个做出决定是否有或没有运动检测。
但是
,
在这个特定的
我
们不感兴趣的运动检测
,
但检测的运动。
/ /
检查帧之间的运动水平
differenceFilter
。
UnmanagedOverlayImage = previousFrame;
/ /
应用不同过滤器
differenceFilter
。
应用
(currentFrame
betweenFramesMotion);
/
/
应用阈值过滤
thresholdFilter
。
ApplyInPlace(betweenFramesMotion);
/ /
打开过滤器适用于去除噪声
openingFilter
。
ApplyInPlace(betweenFramesMotion);
/ /
计算像素数量的改变
VerticalIntensityStatistics vis =
新
VerticalIntensityStatistics(betwe
enFramesMotion);
int[]
直方图
=
-
-
-
-
-
-
-
-
-
上一篇:21世纪大学英语视听说答案
下一篇:(完整版)苏教版英语一年级知识要点