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

 更新时间:2021年09月14日 09:26:38   作者:OKjokull  
这篇文章主要介绍了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手势识别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言超详细梳理排序算法的使用

    C语言超详细梳理排序算法的使用

    这篇文章主要介绍了C语言完成排序的实例,在C语言基本类型的排序中特别有用,下面我们一起进入文章学习更详细的内容吧,需要的朋友可以参考下
    2022-03-03
  • C语言下快速排序(挖坑法)详解

    C语言下快速排序(挖坑法)详解

    大家好,本篇文章主要讲的是C语言下快速排序(挖坑法)详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • 浅谈C++中的string 类型占几个字节

    浅谈C++中的string 类型占几个字节

    本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节
    2013-08-08
  • C语言中你不知道的隐式类型转换规则详解

    C语言中你不知道的隐式类型转换规则详解

    在C语言中,类型转换的方式一般可分为隐式类型转换和显示类型转换(也称为强制类型转换),其中隐式类型转换由编译器自动进行,不需要程序员干预,本文给大家详细介绍了C语言中隐式类型转换规则,需要的朋友可以参考下
    2024-01-01
  • C++类与对象深入之静态成员与友元及内部类详解

    C++类与对象深入之静态成员与友元及内部类详解

    朋友们好,这篇播客我们继续C++的初阶学习,现在对我们对C++的静态成员,友元,内部类知识点做出总结,整理出来一篇博客供我们一起复习和学习,如果文章中有理解不当的地方,还希望朋友们在评论区指出,我们相互学习,共同进步
    2022-06-06
  • C语言之实现栈的基础创建

    C语言之实现栈的基础创建

    这篇文章主要介绍了C语言之实现栈的基础创建,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++ 重载运算符在HotSpot VM中的应用小结

    C++ 重载运算符在HotSpot VM中的应用小结

    C++支持运算符重载,对于Java开发者来说,这个可能比较陌生一些,因为Java不支持运算符重载,下面介绍一下HotSpot VM中的运算符重载,感兴趣的朋友跟随小编一起看看吧
    2023-09-09
  • 使用C语言实现绘制立体分离式环图

    使用C语言实现绘制立体分离式环图

    这篇文章主要为大家详细介绍了使用C语言实现绘制立体分离式环图的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03
  • 深度解析三个常见的C语言内存函数

    深度解析三个常见的C语言内存函数

    这篇文章主要深度解析了三个常见的C语言内存函数memcpy,memmove,memcmp,所以本文将对memcpy,memmove,memcmp 三个函数进行详解和模拟实现,需要的朋友可以参考下
    2023-07-07
  • 最短时间学会基于C++实现DFS深度优先搜索

    最短时间学会基于C++实现DFS深度优先搜索

    常见使用深度优先搜索(DFS)以及广度优先搜索(BFS)这两种搜索,今天我们就来讲讲什么是深度优先搜索,感兴趣的可以了解一下
    2021-08-08

最新评论