基於Aforge的手勢識別之三~~~多點手勢識別

2023-10-12 00:58

本文主要是介绍基於Aforge的手勢識別之三~~~多點手勢識別,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文來自http://blog.csdn.net/hellogv/ ,引用必須注明出處!

       上次介紹了單點手勢識別,這次就繼續介紹一下如何實現多點手勢識別,先來看看本文實現的效果圖,圖片有點大,請稍候。。。:

 

       我預先讓程序學習了B和C這兩個字母,第一個對象通過點擊鼠標左鍵去選擇顏色(對象為綠色),第二個對象通過點擊鼠標右鍵去選擇顏色(對象為紅色),然後通過兩支手指的手勢識別分別向程序繪畫圖形,所以點擊recorgize時,就自動把圖形的特征對應的字母給識別出來了。

       本文上一篇文章的延伸,如圖中所示,這裡通過一個對象的消失/重現來識別是否開始繪圖,當突然消失/重現則開始繪圖,再次消失/重現則停止繪圖。本文的代碼可以到這裡下載:http://download.csdn.net/source/2323958

        接下來貼出本文的核心代碼:

[c-sharp]  view plain copy print ?
  1. private void videoSourcePlayer1_NewFrame( object sender, ref Bitmap image )  
  2. {  
  3.     //保存捕獲到的對象  
  4.     List<Rectangle> []rects = new List<Rectangle>[2];  
  5.   
  6.     Bitmap[] objectImage = new Bitmap[2];  
  7.     for (int i = 0; i < ObjectSum; i++)//捕獲對象  
  8.     {  
  9.         nowImg[i] = (Bitmap)image.Clone();  
  10.   
  11.         objectImage[i] = colorFilter[i].Apply(nowImg[i]);  
  12.   
  13.         // lock image for further processing  
  14.         BitmapData objectData = objectImage[i].LockBits(new Rectangle(0, 0, image.Width, image.Height),  
  15.             ImageLockMode.ReadOnly, image.PixelFormat);  
  16.   
  17.         // grayscaling  
  18.         UnmanagedImage grayImage = new GrayscaleBT709().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<Rectangle>();  
  26.         rects[i].AddRange(blobCounter[i].GetObjectsRectangles());  
  27.   
  28.         //如果當前對象i不存在,並且原有的對象i又是存在的,則表示是對象i隱藏起來了  
  29.         if (rects[i].Count == 0 && oldRect[i].IsEmpty == false)  
  30.         {  
  31.             isCapture[i] = !isCapture[i];//改變為反模式  
  32.             clsHandWrite[i].Clear();  
  33.         }  
  34.         else if (rects[i].Count > 0)//如果當前對象i存在  
  35.         {  
  36.             #region 去掉內部和黏在一起的對象  
  37.             for (int ii = 0; ii < rects[i].Count - 1; ii++)  
  38.             {  
  39.                 //true表示X軸上不能相交,false表示相交  
  40.                 Boolean isNoTouchX = Math.Max(rects[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軸上不能相交,false表示相交  
  42.                 Boolean isNoTouchY = Math.Max(rects[i][ii + 1].Bottom, rects[i][ii].Bottom) - Math.Min(rects[i][ii + 1].Top, rects[i][ii].Top) > (rects[i][ii].Height + rects[i][ii + 1].Height);  
  43.                 if (isNoTouchX == false && isNoTouchY == false)//如果兩個對象相交  
  44.                 {  
  45.                     Rectangle rect = new Rectangle(Math.Min(rects[i][ii].Left, rects[i][ii + 1].Left),  
  46.                         Math.Min(rects[i][ii].Top, rects[i][ii + 1].Top),  
  47.                         Math.Max(rects[i][ii].Right, rects[i][ii + 1].Right) - Math.Min(rects[i][ii].Left, rects[i][ii + 1].Left),  
  48.                         Math.Max(rects[i][ii].Bottom, rects[i][ii + 1].Bottom) - Math.Min(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 = Graphics.FromImage(image);  
  61.   
  62.             if (isCapture[i])//如果捕捉到對象  
  63.             {  
  64.                 Pen pen = new Pen(Color.FromArgb(255, 255, 255), 3);  
  65.                 g.DrawRectangle(pen, objectRect);  
  66.                 int x = (objectRect.Left + objectRect.Width / 2) * pbDraw1.Width / videoSourcePlayer1.Width;  
  67.                 int y = (objectRect.Top + objectRect.Height / 2) * pbDraw1.Height / videoSourcePlayer1.Height;  
  68.                 clsHandWrite[i].Draw(x, y);  
  69.             }  
  70.             else//如果沒有捕捉到對象  
  71.             {  
  72.                 Pen pen = new Pen(Color.FromArgb(160, 255, 160), 3);  
  73.                 g.DrawRectangle(pen, objectRect);  
  74.             }  
  75.   
  76.             g.Dispose();  
  77.   
  78.             oldRect[i] = new Rectangle();//初始化  
  79.             oldRect[i] = rects[i][0];  
  80.             #endregion  
  81.         }  
  82.     }  
  83.     Cls_Common.UpdateObjectPicture(ref pictureBox1, objectImage[0]);//顯示過濾顏色的對象1  
  84.     Cls_Common.UpdateObjectPicture(ref pictureBox2, objectImage[1]);//顯示過濾顏色的對象2  
  85. }  
  86.   
  87. /// <summary>  
  88. /// 選擇綠色的物體為識別的對象  
  89. /// </summary>  
  90. private void videoSourcePlayer1_MouseUp(object sender, MouseEventArgs e)  
  91. {  
  92.     if (e.Button == MouseButtons.Left)//點擊左鍵,識別綠色對象  
  93.         Cls_Common.MarkGreen(nowImg[0], ref colorFilter[0], e.X, e.Y);  
  94.     else  if (e.Button == MouseButtons.Right)//點擊右鍵,識別紅色對象  
  95.         Cls_Common.MarkRed(nowImg[1], ref colorFilter[1], e.X, e.Y);  
  96. }  

这篇关于基於Aforge的手勢識別之三~~~多點手勢識別的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/192095

相关文章

LLM 模型压缩之三: FoldGPT

0. 资源链接 论文: FoldGPT: Simple and Effective Large Language Model Compression Scheme 项目: to be released. 1. 背景动机 现有的大语言模型推理存在以下问题: LLM 模型因为有大量的参数,以及 next token 的预测方式,导致 LLM 模型推理慢,计算消耗大。 模型压缩,量化和

selenium 自动化之三----元素定位多窗口切换

针对多窗口切换操作,定位方式 import timefrom selenium import webdriverdriver=webdriver.Chrome()driver.implicitly_wait(10)driver.get("http://www.baidu.com")sreach_window=driver.current_window_handle # 获取当前窗口dri

内部排序之三:堆排序

前言    堆排序、快速排序、归并排序(下篇会写这两种排序算法)的平均时间复杂度都为O(n*logn)。要弄清楚堆排序,就要先了解下二叉堆这种数据结构。本文不打算完全讲述二叉堆的所有操作,而是着重讲述堆排序中要用到的操作。比如我们建堆的时候可以采用堆的插入操作(将元素插入到适当的位置,使新的序列仍符合堆的定义)将元素一个一个地插入到堆中,但其实我们完全没必要这么做,我们有执行操作更少的方法,

RFC6455-The WebSocket protocol 之三:WebSocket URIs

3.WebSocket URIs This specification defines two URI schemes, using the ABNF syntax defined in RFC 5234 [RFC5234], and terminology and ABNF productions defined by the URI specification RFC 3986 [RF

Windows驱动_UMDF驱动之三UMDF取消IO完成IO访问IO类型HID驱动

Canceling I/O Requests(取消I/O请求)         正在被设备处理的IO请求,可以被应用程序,系统,或者驱动取消。如果设备的IO操作被取消,IO管理器尝试取消所有的和IO操作所关联的没有被处理的IO请求。设备驱动可以一个例程得到通知但IO管理器尝试取消IO请求的时候,然后驱动可以通过设置IO请求的完成状态值为ERROR_OPERATION_ABORTED取消请求。

Vue通信组件之三:父组件向子组件传值

【父组件向子组件传值data和props区别】      子组件中默认是无法访问到父组件中data上的数据和methods中的方法。我们可以在父组件引用子组件的时候,通过属性绑定(v-bind:)的形式,把需要传递给子组件的数据,以属性绑定的形式,传递到子组件内部,以供子组件使用。      子组件的data(){}中的数组是子组件自己私有的数据,而子组件props中的数据是父组件传

局部凸空间及其在算子空间中的应用之三

局部凸空间及其在算子空间中的应用之三 前言一、豪斯多夫局部凸空间的例子二、线性算子的连续性刻画总结 数学是一种艺术,如同诗歌一样,它寻求美和简洁。—— André Weil 前言 本文继续该系列的上一篇文章,介绍一个特殊而重要的豪斯多夫局部凸空间,并证明其上的结论。然后我们给出了线性算子的连续性刻画的几个重要结论,方便后续文章的引用。 一、豪斯多夫局部凸空间的例子

主题模型Gensim入门系列之三:主题和变换

系列目录: (1)主题模型Gensim入门系列之一:核心概念 (2)主题模型Gensim入门系列之二:语料和向量空间 (3)主题模型Gensim入门系列之三:主题和变换 (4)主题模型Gensim入门系列之四:文本相似度查询 ————————————————————————————   本节主要介绍Gensim中从一个向量空间转换到另外一个向量空间的变换的概念,通过一个简单的语料加以

CAFFE-probuffer之三

之前已经发了三篇有关Protocol Buffer的技术博客,其中第一篇介绍了Protocol Buffer的语言规范,而后两篇则分别基于C++和Java给出了一些相对比较实用而又简单的示例。由于近期工作压力很大,因此对于是否继续写本篇博客也确实让我纠结了几天。但每每想到善终如始则无败事这句话时,最终的决定还是既然开始了,就要尽自己最大的努力去做,而不要留有丝毫的遗憾。       该篇Bl

“J.U.C”:ReentrantLock之三unlock方法分析

前篇博客LZ已经分析了ReentrantLock的lock()实现过程,我们了解到lock实现机制有公平锁和非公平锁,两者的主要区别在于公平锁要按照CLH队列等待获取锁,而非公平锁无视CLH队列直接获取锁。但是对于unlock()而已,它是不分为公平锁和非公平锁的。 [java]  view plain copy public void unlock() {