这几日,岛上风云突变,我这个倒霉孩子终究木有躲过感冒的魔掌,中枪鸟~~~
这几天只写了个简单的手势跟踪的代码。
原理是:背景差分+肤色检测。
背景差分:取前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(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);
-
- 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++)
- {
-
- 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);
- imshow("traclking",src);
- }

from: http://blog.csdn.net/yangtrees/article/details/7566284
学习OpenCV——hand tracking手势跟踪
原文:http://www.cnblogs.com/GarfieldEr007/p/5401897.html