Kinect 开发 —— 面部识别
EmguCV库也能用来进行面部识别(face identify)。实际的面部识别,就是将一张图像上的人物的脸部识别出来,这是个很复杂的过程,具体过程我们这里不讨论。对一幅影像进行处理来找到包含脸部的那一部分是我们进行面部识别的第一个步骤。
大多数面部识别软件或多或少都是基于类哈尔特征(Haar-like feature)来进行识别的,他是哈尔小波(Haar wavelets)的一个应用,通过一些列的数学方法来定义一个矩形形状。2001年,Paul Viola和Michael Jones发表了Viola-Jones物体识别方法的框架,该框架基于识别Haar-like特征进行的。该方法和其他面部识别算法相比,所需要的运算量较小。所以这部分方法整合进了OpenCV库。
OpenCV和EmguCV中的面部识别是建立在一系列定义好了的识别规则基础之上的,规则以XML文件的形式存储,最初格式是由Rainer Lienhart定义的。在Emgu示例代码中该文件名为haarcascade_frontalface_default.xml。当然还有一系列的可以识别人物眼睛的规则在这些示例文件中,本例子中没有用到。
要使用Kinect SDK来构造一个简单的面部识别程序,首先创建一个名为KinectFaceFinder的WPF应用程序,然后引用Microsoft.Kinect, System.Drawing, Emgu.CV, Emgu.CV.UI, 和Emgu.Util. 并将所有以opencv_*开头的dll拷贝到程序编译的目录下面。最后将之前写好的两个扩展方法类库ImageExtension.cs和EmguImageExtensions.cs拷贝到项目中。项目的前端代码和之前的一样。只是在root根节点下面添加了一个名为rgbImage的Image控件。
<Window x:Class="FaceFinder.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" >
<Grid >
<Image HorizontalAlignment="Stretch" Name="rgbImage" VerticalAlignment="Stretch" />
</Grid>
</Window>
后台代码中,首先在MainWindow的构造函数中实例化KinectSensor对象然后配置彩色影像数据。因为我们使用EmguCV库来进行影像处理,所以我们可以直接使用RGB影像而不是深度影像。如下代码所示,代码中使用了BackgroundWork对象来从彩色影像数据流中拉取数据。每一次处理完了之后,拉取下一幅,然后继续处理。
KinectSensor _kinectSensor;
public MainWindow()
{
InitializeComponent(); this.Unloaded += delegate
{
_kinectSensor.ColorStream.Disable();
}; this.Loaded += delegate
{
_kinectSensor = KinectSensor.KinectSensors[];
_kinectSensor.ColorStream.Enable();
_kinectSensor.Start(); BackgroundWorker bw = new BackgroundWorker();
bw.RunWorkerCompleted += (a, b) => bw.RunWorkerAsync();
bw.DoWork += delegate { Pulse(); };
bw.RunWorkerAsync();
};
}
上面代码中,Pluse方法处理BackgroundWork的DoWork事件,这个方法是这个例子的主要方法。下面的代码简单的对Emgu提供的示例代码进行了一点修改。我们基于提供的脸部识别规则文件实例化了一个新的HaarCascade类。然后我们从彩色影像数据流获取了一幅影像,然后将他转换为了Emgu能够处理的格式。然后对图像进行灰度拉伸然后提高对比度来使得脸部识别更加容易。Haar识别准则应用到图像上去来产生一些列的结构来指示哪个地方是识别出来的脸部。处理完的影像然后转换为BitmapSource类型,最后后复制给Image控件。因为WPF线程的工作方式,我们使用Dispatcher对象来在正确的线程中给Image控件赋值。
String faceFileName = "haarcascade_frontalface_default.xml";
public void Pulse()
{
using (HaarCascade face = new HaarCascade(faceFileName))
{
var frame = _kinectSensor.ColorStream.OpenNextFrame();
var image = frame.ToOpenCVImage<Rgb, Byte>();
using (Image<Gray, Byte> gray = image.Convert<Gray, Byte>()) //Convert it to Grayscale
{
//normalizes brightness and increases contrast of the image
gray._EqualizeHist(); //Detect the faces from the gray scale image and store the locations as rectangle
//The first dimensional is the channel
//The second dimension is the index of the rectangle in the specific channel
MCvAvgComp[] facesDetected = face.Detect(
gray,
1.1,
,
Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
new System.Drawing.Size(, )); Image<Rgb, Byte> laughingMan = new Image<Rgb, byte>("laughing_man.jpg");
foreach (MCvAvgComp f in facesDetected)
{
image.Draw(f.rect, new Rgb(System.Drawing.Color.Blue), );
}
Dispatcher.BeginInvoke(new Action(() => { rgbImage.Source = image.ToBitmapSource(); }));
}
}
}
既然facesDetected包含了识别出来的脸部的位置信息,我们能够使用脸部识别算法来建立一个现实增强应用。我们可以将一个图片放到脸部位置,而不是用矩形框来显示。下面的代码显示了我们如何使用一个图片替代蓝色的矩形框
Image<Rgb, Byte> laughingMan = new Image<Rgb, byte>("laughing_man.jpg");
foreach (MCvAvgComp f in facesDetected)
{ //image.Draw(f.rect, new Rgb(System.Drawing.Color.Blue), 2);
var rect = new System.Drawing.Rectangle(f.rect.X - f.rect.Width /
, f.rect.Y - f.rect.Height /
, f.rect.Width *
, f.rect.Height * ); var newImage = laughingMan.Resize(rect.Width, rect.Height, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR); for (int i = ; i < (rect.Height); i++)
{
for (int j = ; j < (rect.Width); j++)
{
if (newImage[i, j].Blue != && newImage[i, j].Red != && newImage[i, j].Green != )
image[i + rect.Y, j + rect.X] = newImage[i, j];
} }
}
Kinect 开发 —— 面部识别的更多相关文章
- Kinect开发笔记之二Kinect for Windows 2.0新功能
这是本博客翻译文档的第一篇文章.笔者已经苦逼的竭尽全力的在翻译了.但无奈英语水平也是非常有限.不正确或者不妥当不准确的地方必定会有,还恳请大家留言或者邮件我以批评指正.我会虚心接受. 谢谢大家. ...
- Kinect 开发 —— 杂一
Kinect 提供了非托管(C++)和托管(.NET)两种开发方式的SDK,如果您用C++开发的话,需要安装Speech Runtime(V11),Kinect for Windows Runtime ...
- Kinect开发文章目录
整理了一下去年为止到现在写的和翻译的Kinect的相关文章,方便大家查看.另外,最近京东上微软在搞活动, 微软 Kinect for Windows 京东十周年专供礼包 ,如果您想从事Kinect开发 ...
- Kinect开发资源汇总
Kinect开发资源汇总 转自: http://www.sigvc.org/bbs/forum.php?mod=viewthread&tid=254&highlight=kinec ...
- Kinect开发学习笔记之(一)Kinect介绍和应用
Kinect开发学习笔记之(一)Kinect介绍和应用 zouxy09@qq.com http://blog.csdn.net/zouxy09 一.Kinect简单介绍 Kinectfor Xbox ...
- Kinect 开发 —— 控制PPT播放
实现Kinect控制幻灯片播放很简单,主要思路是:使用Kinect捕捉人体动作,然后根据识别出来的动作向系统发出点击向前,向后按键的事件,从而使得幻灯片能够切换. 这里的核心功能在于手势的识别,我们在 ...
- Kinect 开发 —— 全息图
Kinect的另一个有趣的应用是伪全息图(pseudo-hologram).3D图像可以根据人物在Kinect前面的各种位置进行倾斜和移动.如果方法够好,可以营造出3D控件中3D图像的效果,这样可以用 ...
- Kinect 开发 —— 进阶指引(上)
本文将会介绍一些第三方类库如何来帮助处理Kinect传感器提供的数据.使用不同的技术进行Kinect开发,可以发掘出Kinect应用的强大功能.另一方面如果不使用这些为了特定处理目的而开发的一些类库, ...
- Kinect开发 —— 基础知识
转自:http://www.cnblogs.com/yangecnu/archive/2012/04/02/KinectSDK_Application_Fundamentals_Part2.html ...
随机推荐
- codeforces 401 B Sereja and Contests【贪心】
题意:给出最后的时间n,div 1必须和div2一起举行,并且div2的时间总是比div1大1 给出Sereja(只能参加div2)参加过的k场比赛的时间,问他最少错过了多少场div2,最多错过了多少 ...
- ES6学习笔记(十三)Iterator遍历器和for...of循环
1.概念 遍历器(Iterator)就是这样一种机制.它是一种接口,为各种不同的数据结构提供统一的访问机制.任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有 ...
- dmesg---检查和控制内核的环形缓冲区
dmesg命令被用于检查和控制内核的环形缓冲区.kernel会将开机信息存储在ring buffer中.您若是开机时来不及查看信息,可利用dmesg来查看.开机信息保存在/var/log/dmesg文 ...
- golang实现php里的serialize()和unserialize()序列和反序列方法
Golang 实现 PHP里的 serialize() . unserialize() 安装 go get -u github.com/techleeone/gophp/serialize 用法 pa ...
- 洛谷 P1156 垃圾陷阱 (01背包拓展)(好题!!)
这真是一道好题目 学到了很多 一开始感觉吃或者不吃会有后效性 然后看到洛谷的题解,直接把这个有后效性的部分当作dp的维度和值 因为这个垃圾可以堆或者不堆,所以这个很像01背包, 但是加了非常多的限制条 ...
- HDU 4960 Another OCD Patient 简单DP
思路: 因为是对称的,所以如果两段是对称的,那么一段的前缀和一定等于另一段的后缀和.根据这个性质,我们可以预处理出这个数列的对称点对.然后最后一个对称段是从哪里开始的,做n^2的DP就可以了. 代码: ...
- ECNUOJ 2856 仰望星空
仰望星空 Time Limit:1000MS Memory Limit:65536KBTotal Submit:373 Accepted:145 Description 我仰望星空, 它是那样辽阔而 ...
- 【转】 java RSA加密解密实现
[转] java RSA加密解密实现 该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar 下载地址:http://download.csdn.net/detai ...
- poj 3261 后缀数组 找反复出现k次的子串(子串能够重叠)
题目:http://poj.org/problem?id=3261 仍然是后缀数组的典型应用----后缀数组+lcp+二分 做的蛮顺的,1A 可是大部分时间是在调试代码.由于模板的全局变量用混了,而自 ...
- 动态限制EdiText仅仅能输入特定字符
怎样设置EditText,使得仅仅能输入数字或者某些字母呢? 一.设置EditText,仅仅输入数字: 方法1:直接生成DigitsKeyListener对象就能够了. et_1.setKeyList ...