前几年在做毕业设计时候曾用opencv1.0中defects做过简单的手势识别,这几天看OpenCV2.46中的轮廓函数,发现和以前差别挺大,函数调用完全不一样,重新实现了简单手势的代码。

1.首先用简单的肤色检测算法,得到手的区域。

Mat img = cv::imread("../hand2.jpg");
    namedWindow("image");
    imshow("image", img);

Mat hsvimg;

首先把图像转化到HSV颜色空间,利用肤色色度、饱和度和亮度的特殊范围,得到手的区域。最后对得到的二值手的区域进行开闭操作,去掉一些小的干扰点。
    //得到HSV颜色空间的图像
    cvtColor( img, hsvimg, CV_BGR2HSV );
    //初始化手的图像和原始图像一样大小
    Mat handimg1(img.rows,img.cols, CV_8UC1, Scalar(0));

//简单的肤色检测算法,基于HSV颜色空间和域值
    uchar* p;
    uchar* p1;
    uchar h, s, v;
    int i, j;
    for( i = 0; i < hsvimg.rows; ++i)
        {
        p = hsvimg.ptr<uchar>(i);
        p1= handimg1.ptr<uchar>(i);
        for ( j = 0; j < hsvimg.cols; ++j)
            {
            //printf (" %d %d %d",p[j*3], p[j*3+1],p[j*3+2]);
            h = p[j*3];
            s = p[j*3+1];
            v = p[j*3+2];
            if(h <= 19 && s >= 48 && v > 40)
                {
                p1[j] = 255;
                }
            else p1[j] = 0;
            }
        }
    //对得到手区域二值图做简单的开闭操作
    cv::Mat element = cv::getStructuringElement( cv::MORPH_RECT,
        cv::Size( 5,5 ),
        cv::Point( 2, 2 ) );
    morphologyEx( handimg1, handimg1, MORPH_OPEN, element );
    morphologyEx( handimg1, handimg1, MORPH_CLOSE, element );

简单肤色算法后的效果:

接着对得到的手区域二值图,查找轮廓,找出面积最大的轮廓区域,这个区域一般为手的区域,对该区域求凸包以及defect数目,根据defect的数目,可以判断伸出几个手指头。注意:在判断defect数目时候,我们根据defect点到凸包的距离长度,过滤了一些小的defect。

过滤的代码为:

if ( defectVector.val[3] <= 10000 ) { continue; }

下面是过滤前后的defect点(黄色点),可以看到过滤后,只有4个defect点,我们可以得出此时伸出了5个手指头。

而下面的图,只有1个defect点,则表示伸出2个手指头。

检测defect的代码如下:

vector<vector<Point> > contours;
vector<Vec4i> hierarchy; //查找轮廓
findContours( handimg1, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
printf("轮廓数目:%d\n", contours.size());
vector<vector<Point> >hull( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ convexHull( Mat(contours[i]), hull[i], false ); } Mat drawing = Mat::zeros( handimg1.size(), CV_8UC3 );
int area = 0; //轮廓索引
int k = 0;
for(i = 0; i< contours.size(); i++ )
{
Scalar color1 = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color1, 1, 8, vector<Vec4i>(), 0, Point() );
Scalar color2 = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, hull, i, color2, 1, 8, vector<Vec4i>(), 0, Point() );
int tt = contourArea(contours[i]);
printf("轮廓面积%d = %d\n", i, tt);
if( tt > area)
{
area = contourArea(contours[i]);
k = i;
} } if (!isContourConvex(contours[k]) &&contours[k].size() > 3)
{
vector<int> convexHull_IntIdx;
vector<Vec4i> defects;
convexHull(contours[k], convexHull_IntIdx, true);
convexityDefects(contours[k], convexHull_IntIdx, defects); int defectcount = 0;
for(i=0;i < defects.size();++i)
{
Matx<int,4,1> defectVector = defects[i];
vector<Point> contours1 =contours[k];
Point point1 = contours1[defectVector.val[0]];//开始点
Point point2 = contours1[defectVector.val[1]];//结束点
Point point3 = contours1[defectVector.val[2]];//深度点
float dist = defectVector.val[3];
printf("dist: %f \n", dist);
if ( defectVector.val[3] <= 10000 ) { continue; } // skip defects that are shorter than 100 pixel
circle(drawing, point1, 3, Scalar(255,255,0), 2, CV_AA);
circle(drawing, point2, 8, Scalar(0,255,0), 2, CV_AA);
circle(drawing, point3, 3, Scalar(0,255,255), 2, CV_AA);
defectcount++;
}
printf("指缝数目:%d\n", defectcount); }

程序源码:工程FirstOpenCV26

OpenCV学习(31) 基于defects的简单手势的更多相关文章

  1. 【opencv学习笔记五】一个简单程序:图像读取与显示

    今天我们来学习一个最简单的程序,即从文件读取图像并且创建窗口显示该图像. 目录 [imread]图像读取 [namedWindow]创建window窗口 [imshow]图像显示 [imwrite]图 ...

  2. OpenCV学习(30) 轮廓defects

    上一篇教程中,我们学习了如何计算轮廓的凸包,其实对一个轮廓而言,可能它的凸包和它本身是重合的,也有可能不是重合的.比如下面左边图像的轮廓本身就是凸包,而右边图像的轮廓则不是.我们可以通过函数bool ...

  3. Netty学习——基于netty实现简单的客户端聊天小程序

    Netty学习——基于netty实现简单的客户端聊天小程序 效果图,聊天程序展示 (TCP编程实现) 后端代码: package com.dawa.netty.chatexample; import ...

  4. OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波

    http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...

  5. OpenCV 学习笔记03 boundingRect、minAreaRect、minEnclosingCircle、boxPoints、int0、circle、rectangle函数的用法

    函数中的代码是部分代码,详细代码在最后 1 cv2.boundingRect 作用:矩形边框(boundingRect),用于计算图像一系列点的外部矩形边界. cv2.boundingRect(arr ...

  6. OpenCV 学习笔记03 findContours函数

    opencv-python   4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...

  7. OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现

    # OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现 [-= 博客目录 =-] 1-学习目标 1.1-本章介绍 1.2-实践内容 1.3-相关说明 2-学习过程 2.1-环 ...

  8. opencv学习笔记D01

    目录 opencv学习笔记D01 一.图片读取 二.图片保存 三.图片展示 四.图片缩放 五.四种常用插值方式的比较 1.最近邻插值 2.双线性插值 3.区域插值 4.三次样条插值 我是尾巴: ope ...

  9. 【转载】JMeter学习(一)工具简单介绍

    JMeter学习(一)工具简单介绍 一.JMeter 介绍 Apache JMeter是100%纯JAVA桌面应用程序,被设计为用于测试客户端/服务端结构的软件(例如web应用程序).它可以用来测试静 ...

随机推荐

  1. python之web框架(1):完成静态页面web服务器

    python的web框架(1) 1.首先写一个最简单的web服务器,只能给客户回应一个固定的hello world的页面. from socket import * from multiprocess ...

  2. Revit二次开发示例:APIAppStartup

    下面介绍一个在Revit启动和关闭时调用外部程序的例子.   Revit调用的dll主程序: using System; using System.Collections.Generic; using ...

  3. 深入理解yield

    yield的英文单词意思是生产,刚接触Python的时候感到非常困惑,一直没弄明白yield的用法. 只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子: 1 2 3 def ad ...

  4. python开发_tkinter_菜单选项中英文切换_菜单选项不可用操作_博主推荐

    我使用的python版本为:3.3.2 如果你对python中tkinter模块的菜单操作不是很了解,你可以看看: python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推 ...

  5. Codeforces Round #FF (Div. 1) B. DZY Loves Modification 优先队列

    B. DZY Loves Modification 题目连接: http://www.codeforces.com/contest/446/problem/B Description As we kn ...

  6. Codechef December Challenge 2014 Chef and Apple Trees 水题

    Chef and Apple Trees Chef loves to prepare delicious dishes. This time, Chef has decided to prepare ...

  7. LNMP环境下打击那搭建Bugfree

    说明: LNMP: L=linx;N= Nginx:M=MySQL:p=PHP 本文分四部分进行讲解说明: 1.Nginx的搭建:2.php-fpm安装配置:3.源码安装Mysql5.6版本的数据库: ...

  8. 在C#中实现视频播放器

    当我们需要在C#中实现视频播放器的时候,可以使用如下几种方法: 一.使用MediaPlayer ActiveX控件 在C#中支持视屏播放器最简单的方式就是插入MediaPlayer控件了,在WPF中还 ...

  9. 记录一次软件Bug发生的过程

    结束一周的紧张工作,难得的休息时光,坐在电脑前浏览博客.听听歌.看看大片,这也算是一种享受. 因为年度的开发任务已经开始了,所以最近会特别忙,新人的成长又没有想象中的好,经常在他们身上看到自己去年的影 ...

  10. hdu 1847 博弈基础题 SG函数 或者规律2种方法

    Good Luck in CET-4 Everybody! Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...