学习OpenCV——hand tracking手势跟踪
这几日,岛上风云突变,我这个倒霉孩子终究木有躲过感冒的魔掌,中枪鸟~~~
这几天只写了个简单的手势跟踪的代码。
原理是:背景差分+肤色检测。
背景差分:取前30帧图像取平均值,计算前30帧之差的和,再求均值。在背景平均值上下浮动的阈值之外的被检测出来。
肤色检测:利用YCrCb空间。
两个结果相与操作。
这种方式的优点:1.有效解决了肤色检测结果中总是检测到人脸的情况;
2.解决背景差分检测结果杂乱的情况;
缺点:背景要求相对稳定,反差越大越好,鲁棒性差。
注意事项:差分法由于涉及到累加图像,编码时需注意保证归一化!!!NORMALIZE
- #include "stdafx.h"
- #include <cv.h>
- #include <highgui.h>
- #include <iostream>
- using namespace cv;
- using namespace std;
- void intial(Mat src);
- void accbackgound(Mat src,Mat pre);
- void backgound(int count);
- void foregound(Mat src,Mat pre);
- void skin(Mat src);
- Mat bg,Th,mask0;
- Mat bglow0,bglow1,bglow2;
- Mat bghigh0,bghigh1,bghigh2;
- Mat mask;
- int high=10,low=10;
- int main()
- {
- int count=0;
- VideoCapture capture;
- capture.open(0);
- Mat fram,prefram,result,fg;
- int framNum=0;
- while(capture.isOpened())
- {
- capture>>fram;
- fram.convertTo(fram,CV_32FC3);
- normalize(fram,fram,1,0,CV_MINMAX);
- imshow("src",fram);
- if(framNum==0)
- {
- intial(fram);
- }
- else if(framNum<30)
- {
- ++count;
- accbackgound(fram,prefram);
- }
- else if(framNum==30)
- backgound(count);
- else
- {
- foregound(fram,prefram);
- skin(fram);
- }
- fram.copyTo(prefram);
- framNum++;
- char key=(char)waitKey(2);
- switch(key)
- {
- case 27:
- return 0;
- break;
- }
- }
- }
- void intial(Mat src)
- {
- src.copyTo(bg);
- }
- void accbackgound(Mat src,Mat pre)
- {
- Mat temp;
- accumulate(src,bg);
- absdiff(src,pre,temp);
- if (Th.data==NULL)
- {
- temp.copyTo(Th);
- }
- else
- accumulate(temp,Th);
- }
- void backgound(int count)
- {
- bg=bg/count;
- Th=Th/count;
- normalize(bg,bg,1,0,CV_MINMAX);
- imshow("backgound",bg);
- Mat t[3];
- Mat b[3];
- split(Th,t);
- split(bg,b);
- bglow0=b[0]-t[0]*low;
- bglow1=b[1]-t[1]*low;
- bglow2=b[2]-t[2]*low;
- bghigh0=b[0]+t[0]*high;
- bghigh1=b[1]+t[1]*high;
- bghigh2=b[2]+t[2]*high;
- cout<<"Start Traclking"<<endl;
- }
- void foregound(Mat src,Mat pre)
- {
- Mat temp0,temp1,temp2;
- Mat framNow[3];
- Mat frampre[3];
- framNow[0].setTo(Scalar(0,0,0));
- framNow[1].setTo(Scalar(0,0,0));
- framNow[2].setTo(Scalar(0,0,0));
- temp0.setTo(Scalar(0,0,0));
- temp1.setTo(Scalar(0,0,0));
- temp2.setTo(Scalar(0,0,0));
- /*
- split(pre,frampre);
- accumulateWeighted(frampre[0],bglow0,0.1);
- accumulateWeighted(frampre[0],bghigh0,0.1);
- accumulateWeighted(frampre[1],bglow1,0.1);
- accumulateWeighted(frampre[1],bghigh1,0.1);
- accumulateWeighted(frampre[2],bglow2,0.1);
- accumulateWeighted(frampre[2],bglow2,0.1);
- */
- split(src,framNow);
- inRange(framNow[0],bglow0,bghigh0,temp0);
- inRange(framNow[1],bglow1,bghigh1,temp1);
- inRange(framNow[2],bglow2,bghigh2,temp2);
- bitwise_or(temp0,temp1,temp0);
- bitwise_or(temp0,temp2,temp0);
- bitwise_not(temp0,temp0);
- imshow("Show",temp0);
- temp0.copyTo(mask0);
- }
- void skin(Mat src)
- {
- src.convertTo(src,CV_8UC3,255);
- Mat yuv,dst;
- cvtColor(src,yuv,CV_BGR2YCrCb);
- Mat dstTemp1(src.rows, src.cols, CV_8UC1);
- Mat dstTemp2(src.rows, src.cols, CV_8UC1);
- // 对YUV空间进行量化,得到2值图像,亮的部分为手的形状
- inRange(yuv, Scalar(0,133,0), Scalar(256,173,256), dstTemp1);
- inRange(yuv, Scalar(0,0,77), Scalar(256,256,127), dstTemp2);
- bitwise_and(dstTemp1, dstTemp2, mask);
- dst.setTo(Scalar::all(0));
- bitwise_and(mask,mask0,mask);
- src.copyTo(dst,mask);
- vector< vector<Point> > contours; // 轮廓
- vector< vector<Point> > filterContours; // 筛选后的轮廓
- vector< Vec4i > hierarchy; // 轮廓的结构信息
- vector< Point > hull; // 凸包络的点集
- contours.clear();
- hierarchy.clear();
- filterContours.clear();
- // 得到手的轮廓
- findContours(mask, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
- // 去除伪轮廓
- for (size_t i = 0; i < contours.size(); i++)
- {
- //approxPolyDP(Mat(contours[i]), Mat(approxContours[i]), arcLength(Mat(contours[i]), true)*0.02, true);
- if (fabs(contourArea(Mat(contours[i]))) > 1000&&fabs(arcLength(Mat(contours[i]),true))<2000) //判断手进入区域的阈值
- {
- filterContours.push_back(contours[i]);
- }
- }
- // 画轮廓
- drawContours(src, filterContours, -1, Scalar(0,0,255), 2); //8, hierarchy);
- imshow("traclking",src);
- }

from: http://blog.csdn.net/yangtrees/article/details/7566284
学习OpenCV——hand tracking手势跟踪的更多相关文章
- 基于meanshift的手势跟踪与电脑鼠标控制(手势交互系统)
基于meanshift的手势跟踪与电脑鼠标控制(手势交互系统) zouxy09@qq.com http://blog.csdn.net/zouxy09 一年多前开始接触计算机视觉这个领域的时候,年幼无 ...
- 学习OpenCV研究报告指出系列(二)源代码被编译并配有实例project
下载并安装CMake3.0.1 要自己编译OpenCV2.4.9的源代码.首先.必须下载编译工具,使用的比較多的编译工具是CMake. 以下摘录一段关于CMake的介绍: CMake是一个 ...
- 学习opencv之路(一)
先看一下<学习opencv> 找几个demo 学会相机标定 我做的是单目相机的标定.
- [纯小白学习OpenCV系列]官方例程00:世界观与方法论
2015-11-11 ----------------------------------------------------------------------------------- 其实,写博 ...
- 《学习OpenCV》中求给定点位置公式
假设有10个三维的点,使用数组存放它们有四种常见的形式: ①一个二维数组,数组的类型是CV32FC1,有n行,3列(n×3) ②类似①,也可以用一个3行n列(3×n)的二维数组 ③④用一个n行1列(n ...
- 对人脑处理视觉的描述(摘《学习OpenCV(中文版)》)
人脑将视觉信号划分入很多个通道,将各种不同的信息输入你的大脑.你的大脑有一个关注系统,会根据任务识别出图像的重要部分,并做重点分析,而其他部分则分析得较少 .在人类视觉流中存在大量的反馈,但是目前我们 ...
- 《学习OpenCV》练习题第五章第二题abc
代码: #include <stdio.h> #include <opencv/highgui.h> #include <opencv/cv.h> #include ...
- 《学习OpenCV》练习题第五章第一题ab
这道题是载入一幅带有有趣纹理的图像并用不同的模板(窗口,核)大小做高斯模糊(高斯平滑),然后比较用5*5大小的窗口平滑图像两次和用11*11大小的窗口平滑图像一次是否接近相同. 先说下我的做法,a部分 ...
- 《学习OpenCV》练习题第四章第八题ab
这道题是利用OpenCV例子程序里自带的人脸检测程序,做点图像的复制操作以及alpha融合. 说明:人脸检测的程序我参照了网上现有的例子程序,没有用我用的OpenCV版本(2.4.5)的facedet ...
随机推荐
- 【转载】在LoadRunner中执行命令行程序之:popen()取代system()
我想大家应该都知道在LoadRunner可以使用函数system()来调用系统指令,结果同在批处理里执行一样. 但是system()有个缺陷:无法获取命令的返回结果. 也许你可以用`echo comm ...
- Delphi指针的用法
DELPHI指针的使用 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才 ...
- 【转】android中最好的瀑布流控件PinterestLikeAdapterView
[源地址]http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0919/1696.html 之前我们介绍过一个开源的瀑布流控件Stag ...
- UML 关系
1. 关联关系(association) 关联关系式是用一条直线表示的,如A—B.表示在一段时间内将多个类的实例连接在一起,关联关系描述了某个对象在一段时间内一直知道另一个对象的存在.在Rose中为了 ...
- 在HCI层ACL Connection的建立
一.概述 上一篇博文介绍的是inquiry的整个过程中HCI层的command和event.在寻找到有效的远端蓝牙设备后,开始建立ACL连接,这里仅仅反应HCI层的数据包,对于LM层和Base ...
- MyBatis-Generator 最佳实践
为数据库中的表A生成A.java, A.java, A.xml 由于该插件生成的A.java, A.xml会带有example, 不希望生成example 数据库中的字段写有注释, 希望注释能自动生成 ...
- MySQL- 锁(3)
InnoDB在不同隔离级别下的一致性读及锁的差异 前面讲过,锁和多版本数据是InnoDB实现一致性读和ISO/ANSI SQL92隔离级别的手段,因此,在不同的隔离级别下,InnoDB处理SQL时采用 ...
- ZooKeeper Recipes and Solutions 翻译
ZooKeeper 秘诀 与解决方案 A Guide to Creating Higher-level Constructs with ZooKeeper Out of the Box Applica ...
- 编写SqlHelper使用,在将ExecuteReader方法封装进而读取数据库中的数据时会产生Additional information: 阅读器关闭时尝试调用 Read 无效问题,解决方法与解释
在自学杨中科老师的视频教学时,拓展编写SqlHelper使用,在将ExecuteReader方法封装进而读取数据库中的数据时 会产生Additional information: 阅读器关闭时尝试调用 ...
- 其他常用HTML 片段
1.input placeholder 文字居中 字体大小+上下padding值等于设计稿宽度 设计稿中总高度为86px padding:27px 0;font-size:30px; 2.英文 ...