zoukankan      html  css  js  c++  java
  • 手势识别方法综述(hand detect) 肤色(转)

    看了一天的论文,总结出手势识别的三种方法

    1、通过肤色识别
    2、通过haar-like基
    3、通过HandUv
    说下各个优缺点
    1、通过肤色识别
    设定人的肤色的范围,监测在这个范围内的 肤色InRange,然后画出给定的区域。
    例子:

    #include "cv.h"
    #include "cxcore.h"
    #include "highgui.h"
    #include "math.h"
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <conio.h>
    #include <sstream>
    #include <time.h>
    using namespace std;
    int main()
    {
    int c = 0;
    CvSeq* a = 0;
    CvCapture* capture = cvCaptureFromCAM(0);//从对摄像头的初始化捕获
    if(!cvQueryFrame(capture)) cout<<"Video capture failed, please check the camera."<<endl;
    else cout<<"Video camera capture status: OK"<<endl;
    CvSize sz = cvGetSize(cvQueryFrame( capture));//得到摄像头图像大小
    IplImage* src = cvCreateImage( sz, 8, 3 );//3通道,每个通道8位
    IplImage* hsv_image = cvCreateImage( sz, 8, 3);//
    IplImage* hsv_mask = cvCreateImage( sz, 8, 1);
    IplImage* hsv_mask2 = cvCreateImage( sz, 8, 1);
    IplImage* hsv_edge = cvCreateImage( sz, 8, 1);
    CvScalar hsv_min = cvScalar(0, 30, 80, 0);//最小像素的RGB值
    CvScalar hsv_max = cvScalar(20, 150, 255, 0);//最大像素的RGB值

    //CvScalar hsv_min = cvScalar(30, 30, 30, 0);//最小像素的RGB值
    //CvScalar hsv_max = cvScalar(200, 200, 200, 0);//最大像素的RGB值
    //
    CvMemStorage* storage = cvCreateMemStorage(0);//分配大小为0的内存空间
    CvMemStorage* areastorage = cvCreateMemStorage(0);
    CvMemStorage* minStorage = cvCreateMemStorage(0);
    CvMemStorage* dftStorage = cvCreateMemStorage(0);
    CvSeq* contours = NULL;
    //
    cvNamedWindow( "src",1);
    //在屏幕上创建一个窗口,第一个参数为窗口标题,第二个参数为窗口属性,
    //设置为0(默认值),或者CV_WINDOW_AUTOSIZE,设置为0,则窗口不会因图像的大小而改变
    //图像只能在窗口中根据窗口的大小进行拉伸或缩放;设置为CV_WINDOW_AUTOSIZE时,窗口会根据图像
    //的实际大小进行自动拉伸或缩放。
    //cvNamedWindow( "hsv-msk",1);
    //cvNamedWindow( "contour",1);
    //////
    IplImage * background=cvLoadImage("c:\\002.jpg");
    if (background==0)
    {
    cout<<"open background error"<<endl;
    }
    else
    cout<<"open background ok!"<<endl;
    CvRect rect=cvRect(0,0,background->width,background->height);
    cvSetImageROI(background,rect);
    IplImage * src3=cvCreateImage(cvGetSize(background),background->depth,background->nChannels);
    while( c != 27)//27为ASCII键值(ESC),
    {
    IplImage* bg = cvCreateImage( sz, 8, 3);//
    cvRectangle( bg, cvPoint(0,0), cvPoint(bg->width,bg->height), CV_RGB( 255, 255, 255), -1, 8, 0 );//画矩形,参数:Image,两个顶点坐标,线的颜色,线的厚度
    bg->origin = 1;
    for(int b = 0; b< int(bg->width/10); b++)//画网格
    {
    cvLine( bg, cvPoint(b*20, 0), cvPoint(b*20, bg->height), CV_RGB( 200, 200, 200), 1, 8, 0 );//画竖线
    cvLine( bg, cvPoint(0, b*20), cvPoint(bg->width, b*20), CV_RGB( 200, 200, 200), 1, 8, 0 );//画横线
    }
    src = cvQueryFrame( capture);//得到一帧图像
    cvSaveImage("c:\\src.bmp",src);
    cvCvtColor(src, hsv_image, CV_BGR2HSV);//色彩空间转换,HSV
    cvSaveImage("c:\\hsv.bmp",hsv_image);
    cvInRangeS (hsv_image, hsv_min, hsv_max, hsv_mask);//检查数组元素是否在两个数量之间,输出新图像hsv_mask,从3通道到1通道
    //hsv_mask的数据要么为0,要么为1,在min和max范围内为1,得到ROI区域,找到在像素RGB范围内的数据
    //cvSmooth( hsv_mask, hsv_mask, CV_MEDIAN, 27, 0, 0, 0 );
    cvSaveImage("c:\\mask.bmp",hsv_mask);
    //cvSmooth( hsv_mask, hsv_mask2, CV_MEDIAN, 27, 0, 0);//图像平滑,
    cvSmooth( hsv_mask, hsv_mask2, CV_MEDIAN, 3, 0, 0, 0 );
    //CV_MEDIAN (median blur) - 对图像进行核大小为param1×param1 的中值滤波 (i.e. 邻域是方的).
    cvCanny(hsv_mask2, hsv_edge, 1, 3, 5);
    //cvCanny(hsv_mask, hsv_edge, 1, 3, 5);//采用 Canny 算法做边缘检测
    cvFindContours( hsv_mask, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
    //对单通道图像检索轮廓,返回第一个轮廓的指针
    CvSeq* contours2 = NULL;
    double result = 0, result2 = 0;
    while(contours)//得到最大的两个感兴趣区
    {
    result = fabs( cvContourArea( contours, CV_WHOLE_SEQ ) );//计算感兴趣区域的像素点数
    if ( result > result2) {result2 = result; contours2 = contours;};
    contours = contours->h_next;
    }
    if ( contours2 )//最大的感兴趣区,ROI
    {
    //cout << "contours2: " << contours2->total << endl;
    CvRect rect = cvBoundingRect( contours2, 0 );//返回一个2d矩形的点集合
    cvRectangle( bg, cvPoint(rect.x, rect.y + rect.height), cvPoint(rect.x + rect.width, rect.y), CV_RGB(200, 0, 200), 1, 8, 0 );
    //在bg的矩形区域中画rect的图形
    //cout << "Ratio: " << rect.width << ", " << rect.height << ", " << (float)rect.width / rect.height << endl;
    int checkcxt = cvCheckContourConvexity( contours2 );//检测输入的轮廓是否是凸的
    //cout << checkcxt <<endl;
    CvSeq* hull = cvConvexHull2( contours2, 0, CV_CLOCKWISE, 0 );//二维凸包
    CvSeq* defect = cvConvexityDefects( contours2, hull, dftStorage );//凸包中的缺陷
    if( defect->total >=40 ) {cout << " Closed Palm " << endl;}
    else if( defect->total >=30 && defect->total <40 ) {cout << " Open Palm " << endl;}
    else{ cout << " Fist " << endl;}
    cout << "defet: " << defect->total << endl;
    CvBox2D box = cvMinAreaRect2( contours2, minStorage );//包围所有点的轮廓的最小矩形
    //cout << "box angle: " << (int)box.angle << endl;
    cvCircle( bg, cvPoint(box.center.x, box.center.y), 3, CV_RGB(200, 0, 200), 2, 8, 0 );//画圆
    cvEllipse( bg, cvPoint(box.center.x, box.center.y), cvSize(box.size.height/2, box.size.width/2), box.angle, 0, 360, CV_RGB(220, 0, 220), 1, 8, 0 );//椭圆
    //cout << "Ratio: " << (float)box.size.width/box.size.height <<endl;
    }
    //cvShowImage( "hsv-msk", hsv_mask); hsv_mask->origin = 1;
    //IplImage* contour = cvCreateImage( sz, 8, 3 );
    cvDrawContours( bg, contours2, CV_RGB( 0, 200, 0), CV_RGB( 0, 100, 0), 1, 1, 8, cvPoint(0,0));//绘制轮廓的图像到bg图像中
    cvShowImage( "src", src);
    //cvShowImage("src",src3);
    //contour->origin = 1; cvShowImage( "contour", contour);
    //cvReleaseImage( &contour);
    cvNamedWindow("bg",0);
    cvShowImage("bg",bg);
    cvNamedWindow( "ROI",0);
    cvShowImage("ROI",hsv_mask2);
    //cvShowImage("ROI",hsv_mask2);
    cvReleaseImage( &bg);
    c = cvWaitKey( 100);
    }
    //////
    cvReleaseCapture( &capture);
    cvDestroyAllWindows();
    }
    缺陷在于不能区分脸的颜色和手的颜色,而且识别出来的是全部在这个范围内的东西,难以满足要求。
    比较有特点的是http://vinjn.spaces.live.com/
    他提供的是“虚拟鼓”比较有特色,是
    原理
      1.原始视频->人脸识别
      2.根据人脸的颜色分布,找到手
      3.去除手和脸以外的区域
       3.1 对手和脸进行连通区域划分
       3.2 对双手进行运动分析,满足条件则击鼓
    他的方法从部分上克服了上述缺陷,但是从他提供的视频可以看出来他穿的一个长袖的衣服,而且衣服颜色和肤色差距很大,如果是短袖的衣服效果估计不会怎么样了。
  • 相关阅读:
    Java8实战之Stream流式操作
    类、对象、引用
    java对象的四种引用:强引用、软引用、弱引用和虚引用
    《将博客搬至CSDN》
    **JAVA参数传递方式 (按值传递与引用传递区别)
    JavaWeb--ServletContext
    HttpSessionListener的用法
    SpringMVC优雅的获取HttpSevletRequest及HttpServletResponse简录
    setnx
    JVM命令工具开发
  • 原文地址:https://www.cnblogs.com/xingma0910/p/2606216.html
Copyright © 2011-2022 走看看