These days, the island choppy, I this unfortunate child after all the wood has escaped the clutches of a cold, the gun bird ~ ~ ~
Only a simple gesture tracking code was written these days.
The principle is: background difference + skin tone detection.
Background difference: Take the average of the first 30 frames, calculate the sum of the difference between the first 30 frames, and then seek the mean value. is detected outside the threshold that the background mean is floating above and below the value.
Skin Tone Detection: use YCRCB space.
Two results and operation.
Advantages of this approach: 1. Effectively solve the skin color test results are always detected in the face of the situation;
2. Solve the background difference detection results of the chaotic situation;
Disadvantage: The background requirements are relatively stable, the greater the contrast, the better, poor robustness.
Note: The difference method due to the accumulation of images, the code should pay attention to ensure normalization!!! NORMALIZE
[CPP]View PlainCopy print?
- #include "stdafx.h"
- #include <cv.h>
- #include
- #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 :
- 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);
- //quantify YUV space, get 2 value image, bright part is hand shape
- 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; //Contour
- vector< vector<point> > filtercontours; //Profile after screening
- vector< vec4i > hierarchy; //Profile structure information
- vector< Point > Hull; //Convex-enveloping point set
- Contours.clear ();
- Hierarchy.clear ();
- Filtercontours.clear ();
- //The contour of the hand
- Findcontours (Mask, contours, hierarchy, cv_retr_external, cv_chain_approx_simple);
- //Remove pseudo-contour
- 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 ) //To determine the threshold value of the hand entry area
- {
- Filtercontours.push_back (Contours[i]);
- }
- }
- //Draw Contour
- Drawcontours (SRC, filtercontours,-1, Scalar (0,0,255), 2); //8, hierarchy);
- Imshow ("traclking", SRC);
- }
from:http://blog.csdn.net/yangtrees/article/details/7566284
Learn Opencv--hand tracking gesture Tracking