C++基于OpenCV实现手势识别的源码

先给大家上效果图:

源码在下面

使用 RGB 值分割手部区域,即手部的 GB 值将与背景不同
或者使用边缘检测
或者
背景减法。

我这里使用了背景减法模型。OpenCV为我们提供了不同的背景减法模型,codebook   它的作用是对某些帧进行一段时间的精确校准。其中对于它获取的所有图像;它计算每个像素的平均值和偏差,并相应地指定框。

在前景中它就像一个黑白图像,只有手是白色的

用 Convex Hull 来找到指尖。Convex hull 基本上是包围手部区域的凸集。

包围手的红线是凸包。基本上它是一个凸起;如果我们在红色区域内取任意两点并将它们连接起来形成一条线,那么这条线就完全位于集合内。

黄点是缺陷点,会有很多这样的缺陷点,即每个谷都有一个缺陷点。现在根据缺陷点的数量,我们可以计算展开的手指数量。

大概就是
手部区域提取是使用背景减法完成的。
对于尖端点,深度点凸度缺陷。
提取轮廓和检测凸点的主要代码在函数中
无效检测(IplImage* img_8uc1,IplImage* img_8uc3);

将相机放在稳定的背景前;运行代码,等待一段时间。校准完成后。你会看到显示一些干扰的连接组件图像。把你的手放在相机视图中。

没什么好说的直接看代码会比较容易理解
核心代码

int main(int argc, char** argv)
{
    const char* filename = 0;
    IplImage* rawImage = 0, *yuvImage = 0;
    IplImage *ImaskCodeBook = 0,*ImaskCodeBookCC = 0;
    CvCapture* capture = 0;

    int c, n, nframes = 0;
    int nframesToLearnBG = 300;

    model = cvCreateBGCodeBookModel();

    model->modMin[0] = 3;
    model->modMin[1] = model->modMin[2] = 3;
    model->modMax[0] = 10;
    model->modMax[1] = model->modMax[2] = 10;
    model->cbBounds[0] = model->cbBounds[1] = model->cbBounds[2] = 10;

    bool pause = false;
    bool singlestep = false;

    for( n = 1; n < argc; n++ )
    {
        static const char* nframesOpt = "--nframes=";
        if( strncmp(argv[n], nframesOpt, strlen(nframesOpt))==0 )
        {
            if( sscanf(argv[n] + strlen(nframesOpt), "%d", &nframesToLearnBG) == 0 )
            {
                help();
                return -1;
            }
        }
        else
            filename = argv[n];
    }

    if( !filename )
    {
        printf("Capture from camera\n");
        capture = cvCaptureFromCAM( 0 );
    }
    else
    {
        printf("Capture from file %s\n",filename);
        capture = cvCreateFileCapture( filename );
    }

    if( !capture )
    {
        printf( "Can not initialize video capturing\n\n" );
        help();
        return -1;
    }

    for(;;)
    {
        if( !pause )
        {
            rawImage = cvQueryFrame( capture );
            ++nframes;
            if(!rawImage)
                break;
        }
        if( singlestep )
            pause = true;

        if( nframes == 1 && rawImage )
        {
            // CODEBOOK METHOD ALLOCATION
            yuvImage = cvCloneImage(rawImage);
            ImaskCodeBook = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
            ImaskCodeBookCC = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
            cvSet(ImaskCodeBook,cvScalar(255));

            cvNamedWindow( "Raw", 1 );
            cvNamedWindow( "ForegroundCodeBook",1);
            cvNamedWindow( "CodeBook_ConnectComp",1);
        }

        if( rawImage )
        {
            cvCvtColor( rawImage, yuvImage, CV_BGR2YCrCb );

            if( !pause && nframes-1 < nframesToLearnBG  )
                cvBGCodeBookUpdate( model, yuvImage );

            if( nframes-1 == nframesToLearnBG  )
                cvBGCodeBookClearStale( model, model->t/2 );

            if( nframes-1 >= nframesToLearnBG  )
            {

                cvBGCodeBookDiff( model, yuvImage, ImaskCodeBook );
               centers if desired
                cvCopy(ImaskCodeBook,ImaskCodeBookCC);
                cvSegmentFGMask( ImaskCodeBookCC );

                cvShowImage( "CodeBook_ConnectComp",ImaskCodeBookCC);
                detect(ImaskCodeBookCC,rawImage);

            }

            cvShowImage( "Raw", rawImage );
            cvShowImage( "ForegroundCodeBook",ImaskCodeBook);

        }

        c = cvWaitKey(10)&0xFF;
        c = tolower(c);

        if(c == 27 || c == 'q')
            break;

        switch( c )
        {
        case 'h':
            help();
            break;
        case 'p':
            pause = !pause;
            break;
        case 's':
            singlestep = !singlestep;
            pause = false;
            break;
        case 'r':
            pause = false;
            singlestep = false;
            break;
        case ' ':
            cvBGCodeBookClearStale( model, 0 );
            nframes = 0;
            break;

        case 'y': case '0':
        case 'u': case '1':
        case 'v': case '2':
        case 'a': case '3':
        case 'b':
            ch[0] = c == 'y' || c == '0' || c == 'a' || c == '3';
            ch[1] = c == 'u' || c == '1' || c == 'a' || c == '3' || c == 'b';
            ch[2] = c == 'v' || c == '2' || c == 'a' || c == '3' || c == 'b';
            printf("CodeBook YUV Channels active: %d, %d, %d\n", ch[0], ch[1], ch[2] );
            break;
        case 'i':
        case 'o':
        case 'k':
        case 'l':
            {
            uchar* ptr = c == 'i' || c == 'o' ? model->modMax : model->modMin;
            for(n=0; n<NCHANNELS; n++)
            {
                if( ch[n] )
                {
                    int v = ptr[n] + (c == 'i' || c == 'l' ? 1 : -1);
                    ptr[n] = CV_CAST_8U(v);
                }
                printf("%d,", ptr[n]);
            }
            printf(" CodeBook %s Side\n", c == 'i' || c == 'o' ? "High" : "Low" );
            }
            break;
        }
    }		

    cvReleaseCapture( &capture );
    cvDestroyWindow( "Raw" );
    cvDestroyWindow( "ForegroundCodeBook");
    cvDestroyWindow( "CodeBook_ConnectComp");
    return 0;
}

要直接跑代码调试的
可以直接去下载

到此这篇关于C++基于OpenCV实现手势识别的源码的文章就介绍到这了,更多相关OpenCV手势识别内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • opencv3/C++ 平面对象识别&透视变换方式

    findHomography( ) 函数findHomography( )找到两个平面之间的透视变换H. 参数说明: Mat findHomography( InputArray srcPoints, //原始平面中点的坐标 InputArray dstPoints, //目标平面中点的坐标 int method = 0, //用于计算单应性矩阵的方法 double ransacReprojThreshold = 3, OutputArray mask=noArray(), //通过鲁棒法(RA

  • C++ opencv实现车道线识别

    本文实例为大家分享了C++ opencv实现车道线识别的具体代码,供大家参考,具体内容如下 先上图 1. 2. (一)目前国内外广泛使用的车道线检测方法主要分为两大类: (1) 基于道路特征的车道线检测: (2) 基于道路模型的车道线检测. 基于道路特征的车道线检测作为主流检测方法之一,主要是利用车道线与道路环境的物理特征差异进行后续图像的分割与处理,从而突出车道线特征,以实现车道线的检测.该方法复杂度较低,实时性较高,但容易受到道路环境干扰. 基于道路模型的车道线检测主要是基于不同的二维或三维

  • c++ 基于opencv 识别、定位二维码

    前言 因工作需要,需要定位图片中的二维码:我遂查阅了相关资料,也学习了opencv开源库.通过一番努力,终于很好的实现了二维码定位.本文将讲解如何使用opencv定位二维码. 定位二维码不仅仅是为了识别二维码:还可以通过二维码对图像进行水平纠正以及相邻区域定位.定位二维码,不仅需要图像处理相关知识,还需要分析二维码的特性,本文先从二维码的特性讲起. 1 二维码特性 二维码在设计之初就考虑到了识别问题,所以二维码有一些特征是非常明显的. 二维码有三个"回""字形图案,这一点非常

  • C++基于OpenCV实现手势识别的源码

    先给大家上效果图: 源码在下面 使用 RGB 值分割手部区域,即手部的 GB 值将与背景不同 或者使用边缘检测 或者 背景减法. 我这里使用了背景减法模型.OpenCV为我们提供了不同的背景减法模型,codebook   它的作用是对某些帧进行一段时间的精确校准.其中对于它获取的所有图像:它计算每个像素的平均值和偏差,并相应地指定框. 在前景中它就像一个黑白图像,只有手是白色的 用 Convex Hull 来找到指尖.Convex hull 基本上是包围手部区域的凸集. 包围手的红线是凸包.基本

  • Android基于OpenCV实现QR二维码检测

    目录 QR二维码 QR二维码格式 QR二维码结构 API QRCodeDetector类结构 检测QR二维码 识别QR二维码 检测并识别QR二维码 操作 结果 源码 QR二维码 QR码(英语:Quick Response Code:全称为快速响应矩阵图码)是二维码的一种,于1994年由日本DENSO WAVE公司发明.QR来自英文Quick Response的缩写,即快速反应,因为发明者希望QR码可以快速解码其内容.QR码使用四种标准化编码模式(数字.字母数字.字节(二进制)和日文(Shift_

  • 基于jquery步骤进度条源码分享

    基于jQuery网页步骤流程进度条代码里面包含两款不同效果的jQuery步骤进度条特效.效果图如下: 在线预览       源码下载 html代码: <div class="step_context test"></div> 当前步骤: 第<input type="text" value="5" id="currentStepVal" />步 <button onclick="

  • 基于java构造方法Vevtor添加元素源码分析

    目录 前言 add(E)方法分析 add(int,E)方法分析 insertElementAt()方法分析 addElement()方法分析 addAll()方法分析 addAll(int,Collection)方法分析 ListItr中的add()方法分析 总结 (注意:本文基于JDK1.8) 前言 算上迭代器的add()方法,Vector中一共有7个添加元素的方法,5个添加单个元素的方法,2个添加多个元素的方法,接下来就一起分析它们的实现--Vector是一个线程安全的容器类,它的添加功能是

  • 基于nopCommerce的开发框架 附源码

    .NET的开发人员应该都知道这个大名鼎鼎的高质量b2c开源项目-nopCommerce,基于EntityFramework和MVC开发,拥有透明且结构良好的解决方案,同时结合了开源和商业软件的最佳特性.官网地址:http://www.nopcommerce.com/,中文网:http://www.nopcn.com/.下载后前后端展示如下.如果你还未了解过该项目,建议从官网下载代码后在本地运行查看效果. 笔者使用该框架开发过不少项目,总的来说,方便简洁,集成了.NET开发许多常用的组件和功能.一

  • 基于Spring Boot的Environment源码理解实现分散配置详解

    前提 org.springframework.core.env.Environment是当前应用运行环境的公开接口,主要包括应用程序运行环境的两个关键方面:配置文件(profiles)和属性.Environment继承自接口PropertyResolver,而PropertyResolver提供了属性访问的相关方法.这篇文章从源码的角度分析Environment的存储容器和加载流程,然后基于源码的理解给出一个生产级别的扩展. 本文较长,请用一个舒服的姿势阅读. Environment类体系 Pr

  • 基于java构造方法Vector创建对象源码分析

    目录 前言 构造方法Vector()分析 构造方法Vector(int)分析 构造方法Vecotor(int,int)分析 构造方法Vector(Collection)分析 重要字段介绍(不含基类中定义的字段) (注意:本文基于JDK1.8) 前言 Vector是线程安全的动态数组类,提供4个创建Vector对象的构造方法,接下来我们逐个分析每个创建Vector对象的构造方法 构造方法Vector()分析 public Vector() { this(10); } 用于创建Vector对象的默认

  • Spring Security 基于URL的权限判断源码解析

    目录 1. FilterSecurityInterceptor 源码阅读 2. 自定义基于url的授权 1. FilterSecurityInterceptor 源码阅读 org.springframework.security.web.access.intercept.FilterSecurityInterceptor 通过过滤器实现对HTTP资源进行安全处理. 该安全拦截器所需的 SecurityMetadataSource 类型为 FilterInvocationSecurityMetad

  • 基于jdk1.8的Java源码详解 Integer

    public final class Integer extends Number implements Comparable<Integer> Integer 由final修饰了,所以该类不能够被继承,同时 Integer 继承了Number类,因此可以将Integer转换成 int .double.float.long.byte和short类型的数据,另外,也实现了comparable接口,因此Integer类也可以进行自然排序. 构造方法只有两个: public Integer(int

  • 基于jquery的图片幻灯展示源码

    复制代码 代码如下: //图片幻灯展示 $(function() { var imgPro = { imgWidth : 626, //图片宽度 imgConLength : 0, //图片总长度 index : 0, //导航锁定索引 count : 0, //图片数量 left : 0, //绝对定位left pre : -1, //上个图片索引 curr : 0, //当前图片索引 next : 1, //下个图片索引 direction : 1, //自动播放方向 interTime :

随机推荐