学习OpenCV——hand tracking手势跟踪

这几日,岛上风云突变,我这个倒霉孩子终究木有躲过感冒的魔掌,中枪鸟~~~

这几天只写了个简单的手势跟踪的代码。

原理是:背景差分+肤色检测。

背景差分:取前30帧图像取平均值,计算前30帧之差的和,再求均值。在背景平均值上下浮动的阈值之外的被检测出来。

肤色检测:利用YCrCb空间。

两个结果相与操作。

这种方式的优点:1.有效解决了肤色检测结果中总是检测到人脸的情况;

2.解决背景差分检测结果杂乱的情况;

缺点:背景要求相对稳定,反差越大越好,鲁棒性差。

注意事项:差分法由于涉及到累加图像,编码时需注意保证归一化!!!NORMALIZE

[cpp] view plain copy

print?

  1. #include "stdafx.h"
  2. #include <cv.h>
  3. #include <highgui.h>
  4. #include <iostream>
  5. using namespace cv;
  6. using namespace std;
  7. void intial(Mat src);
  8. void accbackgound(Mat src,Mat pre);
  9. void backgound(int count);
  10. void foregound(Mat src,Mat pre);
  11. void skin(Mat src);
  12. Mat bg,Th,mask0;
  13. Mat bglow0,bglow1,bglow2;
  14. Mat bghigh0,bghigh1,bghigh2;
  15. Mat mask;
  16. int high=10,low=10;
  17. int main()
  18. {
  19. int count=0;
  20. VideoCapture capture;
  21. capture.open(0);
  22. Mat fram,prefram,result,fg;
  23. int framNum=0;
  24. while(capture.isOpened())
  25. {
  26. capture>>fram;
  27. fram.convertTo(fram,CV_32FC3);
  28. normalize(fram,fram,1,0,CV_MINMAX);
  29. imshow("src",fram);
  30. if(framNum==0)
  31. {
  32. intial(fram);
  33. }
  34. else if(framNum<30)
  35. {
  36. ++count;
  37. accbackgound(fram,prefram);
  38. }
  39. else if(framNum==30)
  40. backgound(count);
  41. else
  42. {
  43. foregound(fram,prefram);
  44. skin(fram);
  45. }
  46. fram.copyTo(prefram);
  47. framNum++;
  48. char key=(char)waitKey(2);
  49. switch(key)
  50. {
  51. case 27:
  52. return 0;
  53. break;
  54. }
  55. }
  56. }
  57. void intial(Mat src)
  58. {
  59. src.copyTo(bg);
  60. }
  61. void accbackgound(Mat src,Mat pre)
  62. {
  63. Mat temp;
  64. accumulate(src,bg);
  65. absdiff(src,pre,temp);
  66. if (Th.data==NULL)
  67. {
  68. temp.copyTo(Th);
  69. }
  70. else
  71. accumulate(temp,Th);
  72. }
  73. void backgound(int count)
  74. {
  75. bg=bg/count;
  76. Th=Th/count;
  77. normalize(bg,bg,1,0,CV_MINMAX);
  78. imshow("backgound",bg);
  79. Mat t[3];
  80. Mat b[3];
  81. split(Th,t);
  82. split(bg,b);
  83. bglow0=b[0]-t[0]*low;
  84. bglow1=b[1]-t[1]*low;
  85. bglow2=b[2]-t[2]*low;
  86. bghigh0=b[0]+t[0]*high;
  87. bghigh1=b[1]+t[1]*high;
  88. bghigh2=b[2]+t[2]*high;
  89. cout<<"Start Traclking"<<endl;
  90. }
  91. void foregound(Mat src,Mat pre)
  92. {
  93. Mat temp0,temp1,temp2;
  94. Mat framNow[3];
  95. Mat frampre[3];
  96. framNow[0].setTo(Scalar(0,0,0));
  97. framNow[1].setTo(Scalar(0,0,0));
  98. framNow[2].setTo(Scalar(0,0,0));
  99. temp0.setTo(Scalar(0,0,0));
  100. temp1.setTo(Scalar(0,0,0));
  101. temp2.setTo(Scalar(0,0,0));
  102. /*
  103. split(pre,frampre);
  104. accumulateWeighted(frampre[0],bglow0,0.1);
  105. accumulateWeighted(frampre[0],bghigh0,0.1);
  106. accumulateWeighted(frampre[1],bglow1,0.1);
  107. accumulateWeighted(frampre[1],bghigh1,0.1);
  108. accumulateWeighted(frampre[2],bglow2,0.1);
  109. accumulateWeighted(frampre[2],bglow2,0.1);
  110. */
  111. split(src,framNow);
  112. inRange(framNow[0],bglow0,bghigh0,temp0);
  113. inRange(framNow[1],bglow1,bghigh1,temp1);
  114. inRange(framNow[2],bglow2,bghigh2,temp2);
  115. bitwise_or(temp0,temp1,temp0);
  116. bitwise_or(temp0,temp2,temp0);
  117. bitwise_not(temp0,temp0);
  118. imshow("Show",temp0);
  119. temp0.copyTo(mask0);
  120. }
  121. void skin(Mat src)
  122. {
  123. src.convertTo(src,CV_8UC3,255);
  124. Mat yuv,dst;
  125. cvtColor(src,yuv,CV_BGR2YCrCb);
  126. Mat dstTemp1(src.rows, src.cols, CV_8UC1);
  127. Mat dstTemp2(src.rows, src.cols, CV_8UC1);
  128. // 对YUV空间进行量化,得到2值图像,亮的部分为手的形状
  129. inRange(yuv, Scalar(0,133,0), Scalar(256,173,256), dstTemp1);
  130. inRange(yuv, Scalar(0,0,77), Scalar(256,256,127), dstTemp2);
  131. bitwise_and(dstTemp1, dstTemp2, mask);
  132. dst.setTo(Scalar::all(0));
  133. bitwise_and(mask,mask0,mask);
  134. src.copyTo(dst,mask);
  135. vector< vector<Point> > contours;   // 轮廓
  136. vector< vector<Point> > filterContours; // 筛选后的轮廓
  137. vector< Vec4i > hierarchy;    // 轮廓的结构信息
  138. vector< Point > hull; // 凸包络的点集
  139. contours.clear();
  140. hierarchy.clear();
  141. filterContours.clear();
  142. // 得到手的轮廓
  143. findContours(mask, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
  144. // 去除伪轮廓
  145. for (size_t i = 0; i < contours.size(); i++)
  146. {
  147. //approxPolyDP(Mat(contours[i]), Mat(approxContours[i]), arcLength(Mat(contours[i]), true)*0.02, true);
  148. if (fabs(contourArea(Mat(contours[i]))) > 1000&&fabs(arcLength(Mat(contours[i]),true))<2000)  //判断手进入区域的阈值
  149. {
  150. filterContours.push_back(contours[i]);
  151. }
  152. }
  153. // 画轮廓
  154. drawContours(src, filterContours, -1, Scalar(0,0,255), 2); //8, hierarchy);
  155. imshow("traclking",src);
  156. }

from: http://blog.csdn.net/yangtrees/article/details/7566284

时间: 2024-10-11 19:09:05

学习OpenCV——hand tracking手势跟踪的相关文章

手势跟踪论文学习:Realtime and Robust Hand Tracking from Depth

本文介绍的方法主要是用到了深度信息.提出了一种新的手指检测以及手型初始化的方法.具有很好的鲁棒性.在不使用GPU的情况下,速度就可以达到25FPS.准确率还相当的高.可以说是现在手势识别中最好的方法了. 当前的很多方法要不就是很慢,要不就是使用了GPU,再或者就是需要非常复杂的初始化.而本文提出的方法重新定义了手势的模型,结合了现在通用的两种方法的优势,并且加上一个约束方程,得到了很好的效果. 1.模型的重新定义 每一只手,定义了一个自由度(DOF)为26 的手的模型,其中的6个自由度代表全局的

基于meanshift的手势跟踪与电脑鼠标控制(手势交互系统)

转自网络:http://blog.csdn.net/zouxy09/article/details/17913745 基于meanshift的手势跟踪与电脑鼠标控制(手势交互系统) [email protected] http://blog.csdn.net/zouxy09 一年多前开始接触计算机视觉这个领域的时候,年幼无知,倍感吃力.当年惶恐,从而盲从.挣扎了不少时日,感觉自己好像还是处于领域的门外汉一样,在理论与实践的鸿沟中无法挣脱,心里空落落的.在这种挥之不去的烦忧中,某个时候豁然开朗,觉

学习OpenCV研究报告指出系列(二)源代码被编译并配有实例project

下载并安装CMake3.0.1 要自己编译OpenCV2.4.9的源代码.首先.必须下载编译工具,使用的比較多的编译工具是CMake. 以下摘录一段关于CMake的介绍: CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描写叙述全部平台的安装(编译过程).他可以输出各种各样的makefile或者project文件,能測试编译器所支持的C 特性,类似UNIX下的automake.仅仅是 CMake 的组态档取名为 CmakeLists.txt.Cmake 并不直接建构出终于的软件,而是

【从零学习openCV】IOS7人脸识别实战

前言 接着上篇<IOS7下的人脸检測>,我们顺藤摸瓜的学习怎样在IOS7下用openCV的进行人脸识别,实际上非常easy,因为人脸检測部分已经完毕,剩下的无非调用openCV的方法对採集到的人脸样本进行训练,终于得到一个能够预測人脸的模型.可是当中的原理可谓是博大精深,因为快临最近末考试了,没时间去琢磨当中详细的细节,这次就先写个大概的demo,下次更新文章就得到6月20号之后了. 原理: 从OpenCV2.4之后,openCV增加了新的类FaceRecognizer,我们能够使用它便捷地进

学习Opencv 2.4.9 (一)---Opencv + vs2012环境配置

作者:咕唧咕唧liukun321 来自:http://blog.csdn.net/liukun321 首先获得最新的Opencv 2.4.9源码:opencv源码下载 一.Opencv环境变量配置 1.将源码安装到制定目录: 2.为Opencv 添加环境变量:计算机-->属性 点击高级系统设置 3.出来系统属性对话框后,点击环境变量. 4.弹出如下对话框:选中PATH 单击新建 5.点击新建添加环境变量 6.将opencv2.4.9变量包含到PATH中去 二.然后再看VS2012 的配置. 1.

《学习opencv》笔记——矩阵和图像操作——cvGEMM,cvGetCol,cvGetCols and cvGetDiag

矩阵和图像的操作 (1)cvGEMM函数 其结构 double cvGEMM(//矩阵的广义乘法运算 const CvArr* src1,//乘数矩阵 const CvArr* src2,//乘数矩阵 double alpha,//1号矩阵系数 const CvArr* src3,//加权矩阵 double beta,//2号矩阵系数 CvArr* dst,//结果矩阵 int tABC = 0//变换标记 ); tABC变换标记及其对应的含义 CV_GEMM_A_T 转置 src1 CV_GE

学习OpenCV的学习笔记系列(三)显示图片及视频

OpenCV是计算机视觉库,那么处理的对象无非两个:"图片"及"视频"(其实视频也是被解压成单帧图像来处理的,总的来说,还是处理图像). 那么要想学习OpenCV,第一步必须知道OpenCV是怎么打开"图像"及"视频"文件然后显示的. 如果要想实现这些功能,其实很简单,步骤如下: 1. 新建工程 打开VS2010,新建一个项目,选择"Win32控制台应用程序"(使用控制台可以省掉很多麻烦),取名"

学习OpenCV的学习笔记系列之-- 环境配置

要想学好OpenCV,首先当然要知道怎么配置环境了.以本人的配置环境为例,步骤如下. 第一步 下载及解压OpenCV源码 虽然很多第三方网站及一些学习论坛会提供OpenCV的源码下载,但是还是推荐到官网进行下载,这样可以避免很多麻烦!(病毒?木马?你懂得!) 官网的下载地址如下: http://opencv.org/downloads.html 在此地址的界面上可以找到最新版本的OpenCV源码.我使用的是2014-04-25更新的2.4.9版本(目前最新),根据自己的系统选择对应的源码版本.

《学习opencv》笔记——矩阵和图像操作——cvDet,cvDit,cvDotProduct,cvEigenVV and cvFlip

矩阵和图像的操作 (1)cvDet函数 其结构 double cvDet(//计算矩阵的行列式 const CvArr* mat ); 实例代码 #include <cv.h> #include <highgui.h> #include <stdio.h> #include <iostream> using namespace std; int main() { double va[] = {1,0,0,0,2,0,0,0,3}; CvMat Va=cvMa