Emgu CV 简介

        众所周知,Emgu CV是.NET平台下对OpenCV图像处理库的封装,也就是.NET版的OpenCV。开发者可以很方便的通过C#,VB等语言调用OpenCV函数来实现相应的图像处理功能。

其下载地址为:http://www.emgu.com/wiki/index.php/Main_Page。安装过程极其简单,网上教程很多,这里也就不详述了。

手势识别

在计算机科学中,手势识别是通过数学算法来识别人类手势的一个议题。手势识别可以来自人的身体各部位的运动,但一般是指脸部和手的运动。

腾讯有一个小工具,叫“QQ手势达人forPPT”,可以通过手势运动来控制PPT的放映,本文章亦是通过Emgu CV实现类似效果。

PPT控制类

控制的两个核心,一个是手势的检测,另一个就是如何使用C#控制PPT的播放、停止、上一页、下一页等操作。下面这个类即实现通过C#来控制PPT的加载,播放控制等。

   1:  // ***********************************************************************
   2:  // Assembly         : HandTrackerTestWindow
   3:  // Author           : pengdian
   4:  // Created          : 08-29-2014
   5:  //
   6:  // Last Modified By : pengdian
   7:  // Last Modified On : 08-29-2014
   8:  // ***********************************************************************
   9:  // <copyright file="PowerPointOperate.cs" company="nikoyo">
  10:  //     Copyright (c) . All rights reserved.
  11:  // </copyright>
  12:  // <summary>PPT操作</summary>
  13:  // ***********************************************************************
  14:  using System;
  15:  using System.IO;
  16:   
  17:  /// <summary>
  18:  /// The HandTrackerTestWindow namespace.
  19:  /// </summary>
  20:  namespace HandTrackerTestWindow
  21:  {
  22:      /// <summary>
  23:      /// PPT操作类.
  24:      /// </summary>
  25:      public class PowerPointOperate
  26:      {
  27:          /// <summary>
  28:          /// The object application
  29:          /// </summary>
  30:          private static Microsoft.Office.Interop.PowerPoint.Application objApp = null;
  31:   
  32:          /// <summary>
  33:          /// The object pres
  34:          /// </summary>
  35:          private static Microsoft.Office.Interop.PowerPoint.Presentation objPres = null;
  36:   
  37:          /////// <summary>
  38:          /////// The object ss ws
  39:          /////// </summary>
  40:          ////private Microsoft.Office.Interop.PowerPoint.SlideShowWindows objSSWs;
  41:   
  42:          /////// <summary>
  43:          /////// The object SST
  44:          /////// </summary>
  45:          ////private Microsoft.Office.Interop.PowerPoint.SlideShowTransition objSST;
  46:   
  47:          /// <summary>
  48:          /// The object SSS
  49:          /// </summary>
  50:          private static Microsoft.Office.Interop.PowerPoint.SlideShowSettings objSSS;
  51:   
  52:          /////// <summary>
  53:          /////// The object SLD RNG
  54:          /////// </summary>
  55:          ////private Microsoft.Office.Interop.PowerPoint.SlideRange objSldRng;
  56:   
  57:          public bool IsStart
  58:          {
  59:              get
  60:              {
  61:                  if (objPres == null || objPres.SlideShowWindow == null || objPres.SlideShowWindow.View == null)
  62:                  {
  63:                      return false;
  64:                  }
  65:                  return objPres.SlideShowWindow.View.State == Microsoft.Office.Interop.PowerPoint.PpSlideShowState.ppSlideShowRunning ? true : false;
  66:              }
  67:          }
  68:   
  69:          /// <summary>
  70:          /// Prevents a default instance of the <see cref="PowerPointOperate"/> class from being created.
  71:          /// </summary>
  72:          private PowerPointOperate()
  73:          {
  74:          }
  75:   
  76:          /// <summary>
  77:          /// 单例模式,获取ppt操作类实例.
  78:          /// </summary>
  79:          /// <returns>PowerPointOperate.</returns>
  80:          public static PowerPointOperate GetInstance()
  81:          {
  82:              return new PowerPointOperate();
  83:          }
  84:   
  85:          /// <summary>
  86:          /// 加载PPT文件.
  87:          /// </summary>
  88:          /// <param name="pptFile">The PPT file.</param>
  89:          /// <exception cref="System.Exception">指定文件不存在</exception>
  90:          public void LoadFile(string pptFile)
  91:          {
  92:              if (string.IsNullOrWhiteSpace(pptFile) || !File.Exists(pptFile))
  93:              {
  94:                  throw new Exception("指定文件不存在");
  95:              }
  96:   
  97:              ////防止连续打开多个PPT程序.
  98:              if (objApp == null)
  99:              {
 100:                  objApp = new Microsoft.Office.Interop.PowerPoint.Application() { Visible = Microsoft.Office.Core.MsoTriState.msoTrue };
 101:              }
 102:   
 103:              try
 104:              {
 105:                  ////以只读方式打开,方便操作结束后保存.
 106:                  objPres = objApp.Presentations.Open(pptFile, Microsoft.Office.Core.MsoTriState.msoTrue, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoTrue);
 107:                  //////Prevent Office Assistant from displaying alert messages:
 108:                  ////this.bAssistantOn = objApp.Assistant.On;
 109:                  ////objApp.Assistant.On = false;
 110:              }
 111:              catch
 112:              {
 113:                  objApp.Quit();
 114:                  GC.Collect();
 115:              }
 116:              finally
 117:              {
 118:                  objSSS = null;
 119:              }
 120:          }
 121:   
 122:          /// <summary>
 123:          /// 开始播放PPT
 124:          /// </summary>
 125:          public void PPTStart()
 126:          {
 127:              try
 128:              {
 129:                  if (objApp != null && objPres != null)
 130:                  {
 131:                      objSSS = objPres.SlideShowSettings;
 132:                      objSSS.Run();
 133:                  }
 134:              }
 135:              catch
 136:              {
 137:                  objApp.Quit();
 138:                  GC.Collect();
 139:              }
 140:          }
 141:   
 142:          /// <summary>
 143:          /// 停止播放PPT
 144:          /// </summary>
 145:          public void PPTStop()
 146:          {
 147:              try
 148:              {
 149:                  if (objApp != null && IsStart)
 150:                  {
 151:                      objPres.SlideShowWindow.View.Exit();
 152:                  }
 153:              }
 154:              catch
 155:              {
 156:                  objApp.Quit();
 157:                  GC.Collect();
 158:              }
 159:              finally
 160:              {
 161:                  objSSS = null;
 162:              }
 163:          }
 164:   
 165:          /// <summary>
 166:          /// 关闭PPT文档。
 167:          /// </summary>
 168:          public void PPTClose()
 169:          {
 170:              if (objApp != null)
 171:              {
 172:                  objApp.Quit();
 173:                  objApp = null;
 174:              } 
 175:   
 176:              GC.Collect();
 177:          }
 178:   
 179:          /// <summary>
 180:          /// PPT下一页。
 181:          /// </summary>
 182:          public void NextSlide()
 183:          {
 184:              if (objApp != null && IsStart)
 185:              {
 186:                  objPres.SlideShowWindow.View.Next();
 187:              }   
 188:          }
 189:   
 190:          /// <summary>
 191:          /// PPT上一页。
 192:          /// </summary>
 193:          public void PreviousSlide()
 194:          {
 195:              if (objApp != null && IsStart)
 196:              {
 197:                  objPres.SlideShowWindow.View.Previous();
 198:              }   
 199:          }
 200:      }
 201:  }

手势识别与运动检测

这里唯一的难点就是手势模型的创建,所幸,这种麻烦东西我们可以从“QQ手势达人forPPT”中提取出来,剩下的就是识别和检测手势了。代码如下:

   1:  using Emgu.CV;
   2:  using Emgu.CV.Structure;
   3:  using Emgu.CV.Util;
   4:  using System;
   5:  using System.Collections.Generic;
   6:  using System.Drawing;
   7:  using System.IO;
   8:  using System.Linq;
   9:  using System.Text;
  10:   
  11:  namespace HandTrackerTestWindow
  12:  {
  13:      public class HandTracker : IDisposable
  14:      {
  15:          CascadeClassifier palmHaar = new CascadeClassifier(@"data\palm.dat");
  16:          CascadeClassifier fistHaar = new CascadeClassifier(@"data\fist.dat");
  17:   
  18:          public void Dispose()
  19:          {
  20:              if (palmHaar != null)
  21:              {
  22:                  palmHaar.Dispose();
  23:                  palmHaar = null;
  24:              }
  25:              if (fistHaar != null)
  26:              {
  27:                  fistHaar.Dispose();
  28:                  fistHaar = null;
  29:              }
  30:          }
  31:   
  32:          public Rectangle DetectPalm(string imagePath)
  33:          {
  34:              if (!File.Exists(imagePath))
  35:              {
  36:                  return new Rectangle(0, 0, 0, 0);
  37:              }
  38:              Image<Bgr, Byte> img = new Image<Bgr, byte>(imagePath);
  39:              Image<Gray, Byte> grayImage = img.Copy().Convert<Gray, byte>();
  40:              Rectangle[] palmDetected = palmHaar.DetectMultiScale(grayImage, 1.4, 10, new Size(20, 20), Size.Empty);
  41:              //faces.AddRange(facesDetected);
  42:              if (palmDetected == null || palmDetected.Length == 0)
  43:              {
  44:                  return new Rectangle(0, 0, 0, 0);
  45:              }
  46:   
  47:              return palmDetected[0];
  48:          }
  49:          public Rectangle DetectPalm(Bitmap bitmap)
  50:          {
  51:              if (bitmap == null)
  52:              {
  53:                  return new Rectangle(0, 0, 0, 0);
  54:              }
  55:              Image<Bgr, Byte> img = new Image<Bgr, byte>(bitmap);
  56:              Image<Gray, Byte> grayImage = img.Copy().Convert<Gray, byte>();
  57:              Rectangle[] palmDetected = palmHaar.DetectMultiScale(grayImage, 1.4, 10, new Size(20, 20), Size.Empty);
  58:              //faces.AddRange(facesDetected);
  59:              if (palmDetected == null || palmDetected.Length == 0)
  60:              {
  61:                  return new Rectangle(0, 0, 0, 0);
  62:              }
  63:   
  64:              return palmDetected[0];
  65:          }
  66:          public Rectangle DetectFist(string imagePath)
  67:          {
  68:              if (!File.Exists(imagePath))
  69:              {
  70:                  return new Rectangle(0, 0, 0, 0);
  71:              }
  72:              Image<Bgr, Byte> img = new Image<Bgr, byte>(imagePath);
  73:              Image<Gray, Byte> grayImage = img.Copy().Convert<Gray, byte>();
  74:              Rectangle[] fistDetected = fistHaar.DetectMultiScale(grayImage, 1.4, 10, new Size(20, 20), Size.Empty);
  75:              if (fistDetected == null || fistDetected.Length == 0)
  76:              {
  77:                  return new Rectangle(0, 0, 0, 0);
  78:              }
  79:   
  80:              return fistDetected[0];
  81:          }
  82:   
  83:          public Rectangle DetectFist(Bitmap bitmap)
  84:          {
  85:              if (bitmap == null)
  86:              {
  87:                  return new Rectangle(0, 0, 0, 0);
  88:              }
  89:              Image<Bgr, Byte> img = new Image<Bgr, byte>(bitmap);
  90:              Image<Gray, Byte> grayImage = img.Copy().Convert<Gray, byte>();
  91:              Rectangle[] fistDetected = fistHaar.DetectMultiScale(grayImage, 1.4, 10, new Size(20, 20), Size.Empty);
  92:              if (fistDetected == null || fistDetected.Length == 0)
  93:              {
  94:                  return new Rectangle(0, 0, 0, 0);
  95:              }
  96:   
  97:              return fistDetected[0];
  98:          }
  99:      }
 100:  }

解决了手势检测控制类和PPT放映控制类,剩下的就是创建一个界面来进行控制了。

   1:  private void test()
   2:          {
   3:              bool isPalm = false;
   4:              bool isFist = false;
   5:              int count = 0;
   6:              while (true)
   7:              {
   8:                  if (count > 10)
   9:                  {
  10:                      isPalm = false;
  11:                      isFist = false;
  12:                      count = 0;
  13:                      this.Invoke(showControllerDelegate, false);
  14:                  }
  15:                  if (!isPalm)
  16:                  {
  17:                      isFist = false;
  18:                      Bitmap bitmap = videoPlayer.GetCurrentVideoFrame();
  19:                      if (handTracker.DetectPalm(bitmap).Width > 0)
  20:                      {
  21:                          isPalm = true;
  22:                          count = 0;
  23:                          this.Invoke(showControllerDelegate, true);
  24:                      }
  25:                      Thread.Sleep(50);
  26:                  }
  27:                  else
  28:                  {
  29:                      if (!isFist)
  30:                      {
  31:                          Bitmap bitmap = videoPlayer.GetCurrentVideoFrame();
  32:                          Rectangle rect = handTracker.DetectFist(bitmap);
  33:                          if (rect.Width > 0)
  34:                          {
  35:                              firstRect = rect;
  36:                              isFist = true;
  37:                              count = 0;
  38:                              this.Invoke(showButtonDelegate, true);
  39:                          }
  40:                          else
  41:                          {
  42:                              isFist = false;
  43:                              if (handTracker.DetectPalm(bitmap).Width > 0)
  44:                              {
  45:                                  isPalm = true;
  46:                                  count = 0;
  47:                                  this.Invoke(showButtonDelegate, false);
  48:                              }
  49:                              else
  50:                              {
  51:                                  count++;
  52:                              }
  53:   
  54:                          }
  55:                          Thread.Sleep(50);
  56:                      }
  57:                      else
  58:                      {
  59:                          Bitmap bitmap = videoPlayer.GetCurrentVideoFrame();
  60:                          Rectangle rect = handTracker.DetectFist(bitmap);
  61:                          if (rect.Width > 0)
  62:                          {
  63:                              if (firstRect.Left - rect.Left > 30)
  64:                              {
  65:                                  this.Invoke(nextPPTDelegate);
  66:                                  PowerPointOperate.GetInstance().NextSlide();
  67:                                  isPalm = false;
  68:                                  isFist = false;
  69:                                  count = 0;
  70:                                  Thread.Sleep(500);
  71:                                  this.Invoke(showControllerDelegate, false);
  72:                              }
  73:                              else if (firstRect.Left - rect.Left < -30)
  74:                              {
  75:                                  this.Invoke(prePPTDelegate);
  76:                                  PowerPointOperate.GetInstance().PreviousSlide();
  77:                                  isPalm = false;
  78:                                  isFist = false;
  79:                                  count = 0;
  80:                                  Thread.Sleep(500);
  81:                                  this.Invoke(showControllerDelegate, false);
  82:                              }
  83:                              else
  84:                              {
  85:                                  isPalm = true;
  86:                                  isFist = true;
  87:                                  count = 0;
  88:                              }
  89:                              //this.Invoke(showButtonDelegate);
  90:                          }
  91:                          else
  92:                          {
  93:                              if (handTracker.DetectPalm(bitmap).Width > 0)
  94:                              {
  95:                                  isPalm = true;
  96:                                  isFist = false;
  97:                                  count = 0;
  98:                                  this.Invoke(showButtonDelegate, false);
  99:                              }
 100:                              else
 101:                              {
 102:                                  count++;
 103:                              }
 104:                          }
 105:                          Thread.Sleep(50);
 106:                      }
 107:   
 108:                  }
 109:   
 110:   
 111:                  //PowerPointOperate.GetInstance().PPTStop();
 112:              }
 113:          }

最后实现的效果图如下:

检测手掌:

检测拳头:

移动拳头控制PPT

由于只是写一个用于演示的Demo,因此代码没做优化,有兴趣的可以自行修改,目前只做了上一页和下一页,开始播放和停止播放,有兴趣的可以自行补上。

最后,附上源代码地址(百度网盘):http://pan.baidu.com/s/1o6nyYFK

文章已迁移到:http://www.izonso.com/forum.php

基于Emgu CV 的手势识别实现PPT的控制放映的更多相关文章

  1. 基于Emgu CV+百度人脸识别,实现视频动态 人脸抓取与识别

    背景 目前AI 处于风口浪尖,作为 公司的CTO,也作为自己的技术专研,开始了AI之旅,在朋友圈中也咨询 一些大牛对于AI 机器学习框架的看法,目前自己的研究方向主要开源的 AI 库,如:Emgu C ...

  2. 基于Emgu CV的人脸检测代码

    这个提供的代码例子是Emgu CV提供的源码里面自带的例子,很好用,基本不需要改,代码做的是人脸检测不是人脸识别,这个要分清楚.再就是新版本的Emgu CV可能会遇到系统32位和64位处理方式有区别的 ...

  3. 基于Emgu cv的图像拼接(转)

    分类: 编程 C# Emgu cv Stitching 2012-10-27 11:04 753人阅读 评论(1) 收藏 举报 在新版本的Emgu cv中添加了Emgu.CV.Stitching,这极 ...

  4. 可学习的多人人脸识别程序(基于Emgu CV)

    源代码下载(需要安装Emgu CV,安装方法请百度) 很多朋友使用Emgu CV遇到CvInvoke()的报错,我找到一种解决方法. 把EmguCV目录下bin里面的所有dll复制到C:\WINDOW ...

  5. [Winform]基于Emgu.CV人脸识别

    摘要 “OpenCV是一个开源的计算机视觉库.OpenCV采用C/C++语言编写,可以运行在Linux/Windows/Mac等操作系统上.OpenCV还提供了Python.Ruby.MATLAB以及 ...

  6. [转载+原创]Emgu CV on C# (六) —— Emgu CV on Canny边缘检测

    Canny边缘检测也是一种边缘检测方法,本文介绍了Canny边缘检测的函数及其使用方法,并利用emgucv方法将轮廓检测解算的结果与原文进行比较. 图像的边缘检测的原理是检测出图像中所有灰度值变化较大 ...

  7. [转载+原创]Emgu CV on C# (四) —— Emgu CV on 全局固定阈值二值化

    重点介绍了全局二值化原理及数学实现,并利用emgucv方法编程实现. 一.理论概述(转载,如果懂图像处理,可以略过,仅用作科普,或者写文章凑字数)  1.概述 图像二值化是图像处理中的一项基本技术,也 ...

  8. .NET开源工程推荐(Accord,AForge,Emgu CV)

         本人用C#开发了一些项目,下面的开源工程给了我很大的帮助——详细的源代码介绍加丰富的实例运用,是非常不错的学习资源,分享给大家,同时附上我的相关开发项目.    Accord.NET The ...

  9. Emgu.CV(一)

    由于这块的知识不少,会分好几期写完 什么是OpenCV? OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows和Mac OS操作系统上.它轻量级而且高效--由一 ...

随机推荐

  1. qt helper

    qt帮助文档(中文版) http://www.kuqin.com/qtdocument/index.html qt基础 http://www.devbean.net/2012/08/qt-study- ...

  2. springMVC项目在jboss7中配置应用自己的log4j--转载

    原文地址:http://www.xuebuyuan.com/1954635.html Jboss7默认采用容器自己的log4j module,应用自己配置的log4j不起作用,需要应用做一些设置: 以 ...

  3. Regular Expressions --正则表达式官方教程

    http://docs.oracle.com/javase/tutorial/essential/regex/index.html This lesson explains how to use th ...

  4. MySQL(6):数据操作

    1.创建数据(插入数据) (1)insert into  tab_name(字段列表)  values(值列表) (2)如果需要在插入时,为所有的字段设置值,那么可以省略字段列表.要求是值的顺序,应该 ...

  5. Android之HTTP网络通信--GET传递(二)

    根据上一篇写的是实现了通过url接口将接口中的数据显示出来,这次根据上一篇的基础,进一步说明一下AsynTask的使用. AsynTask类有几个函数是大家必须知道的. doInBackGround( ...

  6. stitching detail输出的dot图含义

    如果利用opencv里面提供的stitching detail的话. 输入参数: stitching_detail --save_graph a.dot 1.png 2.png 其中a.dot 文件中 ...

  7. 为Debain &&Centos安装dig

    Debain&Ubuntu sudo apt-get install dnsutils Fdeoar&Centos yum install bind-utils

  8. Div+Css的初步运用

    采用DIV+CSS模式的网站具有以下优势:1.表现和内容相分离 2.代码简洁,提高页面浏览速度 3.易于维护和改版 4.提高搜索引擎对网页的索引效率. 然后呢html文件中放置CSS有三种类型:内联. ...

  9. asp下实现多条件模糊查询SQL语句

    常写一个简单的模糊查询的SQL语句格式可以如下例: sql="select * from 表名 where 字段名 like ’%" & request.form(&quo ...

  10. SQL SERVER中的逻辑读,预读和物理读

    sqlserver:数据存储方式:最小单位是页,每一页8k,sqlserver 对页的读取是具有原子性,也就是说,要么读取完整一页,要么完全不读取,不会有中间状态,而页之间的数据组织结构是B树 但是每 ...