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


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

  • 相关阅读:
    在阿里云服务器上安装MySQL
    mui中调用ajax时报abort错误
    IDEA根据数据库表生成pojo对象
    java.io.IOException: All specified directories have failed to load.
    mysql隔离级别
    java8新特性
    数据库语言分类
    Spring AOP 代码示例
    java NIO学习(二)
    java NIO学习(一)
  • 原文地址:https://www.cnblogs.com/GarfieldEr007/p/5401897.html
Copyright © 2020-2023  润新知