OpenCV学习(31) 基于defects的简单手势
前几年在做毕业设计时候曾用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的简单手势的更多相关文章
- 【opencv学习笔记五】一个简单程序:图像读取与显示
今天我们来学习一个最简单的程序,即从文件读取图像并且创建窗口显示该图像. 目录 [imread]图像读取 [namedWindow]创建window窗口 [imshow]图像显示 [imwrite]图 ...
- OpenCV学习(30) 轮廓defects
上一篇教程中,我们学习了如何计算轮廓的凸包,其实对一个轮廓而言,可能它的凸包和它本身是重合的,也有可能不是重合的.比如下面左边图像的轮廓本身就是凸包,而右边图像的轮廓则不是.我们可以通过函数bool ...
- Netty学习——基于netty实现简单的客户端聊天小程序
Netty学习——基于netty实现简单的客户端聊天小程序 效果图,聊天程序展示 (TCP编程实现) 后端代码: package com.dawa.netty.chatexample; import ...
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...
- OpenCV 学习笔记03 boundingRect、minAreaRect、minEnclosingCircle、boxPoints、int0、circle、rectangle函数的用法
函数中的代码是部分代码,详细代码在最后 1 cv2.boundingRect 作用:矩形边框(boundingRect),用于计算图像一系列点的外部矩形边界. cv2.boundingRect(arr ...
- OpenCV 学习笔记03 findContours函数
opencv-python 4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...
- OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现
# OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现 [-= 博客目录 =-] 1-学习目标 1.1-本章介绍 1.2-实践内容 1.3-相关说明 2-学习过程 2.1-环 ...
- opencv学习笔记D01
目录 opencv学习笔记D01 一.图片读取 二.图片保存 三.图片展示 四.图片缩放 五.四种常用插值方式的比较 1.最近邻插值 2.双线性插值 3.区域插值 4.三次样条插值 我是尾巴: ope ...
- 【转载】JMeter学习(一)工具简单介绍
JMeter学习(一)工具简单介绍 一.JMeter 介绍 Apache JMeter是100%纯JAVA桌面应用程序,被设计为用于测试客户端/服务端结构的软件(例如web应用程序).它可以用来测试静 ...
随机推荐
- Python入门1(简介、安装)
第一次写博客,希望自己能养成每天一篇的好习惯(表示有很大的挑战,就不立Flag了) 先从Python开始吧.下面是本人所学习的主要教材电子版: 链接:http://pan.baidu.com/s/1e ...
- 解决命令行运行python文件,出现No module named *** 报错问题
有时候在一个项目中运行的时候,可能是之前已经mark成sources root 你自己忘记了, 于是就在命令行也执行python文件,然后就出现 No module named *** 等 相关你认为 ...
- mysql正则表达式,实现多个字段匹配多个like模糊查询
现在有这么一个需求 一个questions表,字段有题目(TestSubject),选项(AnswerA,AnswerB,AnswerC,AnswerD,AnswerE) 要求字段不包含png,jpg ...
- JAVAEE——宜立方商城10:使用freemarker实现网页静态化、ActiveMq同步生成静态网页、Sso单点登录系统分析
1. 学习计划 1.使用freemarker实现网页静态化 2.ActiveMq同步生成静态网页 2. 网页静态化 可以使用Freemarker实现网页静态化. 2.1. 什么是freemarker ...
- JAVA 9 新特性
Oracle已将JAVA 9的开发提上日程.OpenJDK上已经出现了关于下一个主版本JAVA 9的改进建议(JEP).与以往不同,Oracle在这次谈及了一些真正的特性.而早期对于JDK9的声明仅 ...
- python opencv3 矩形 圆形边框
git:https://github.com/linyi0604/Computer-Vision # coding:utf8 import cv2 import numpy as np # 读入图像 ...
- 我们不能把JavaScript作为一个全功能的编程语言。它缺乏以下重要特征
客户端JavaScript不允许读或写文件.这已被保存的安全原因. JavaScript不能用于网络的应用,因为没有这样的支持. JavaScript没有任何多线程或多处理器的能力.
- Codeforces Round #461 (Div. 2)
A - Cloning Toys /* 题目大意:给出两种机器,一种能将一种原件copy出额外一种原件和一个附件, 另一种可以把一种附件copy出额外两种附件,给你一个原件, 问能否恰好变出题目要求数 ...
- 【贪心】【后缀自动机】Gym - 101466E - Text Editor
题意:给你两个串A,B,以及一个整数K,让你找到B的一个尽可能长的前缀,使得其在A串中出现的次数不小于K次. 对A串建立后缀自动机,然后把B串放在上面跑,由于每到一个结点,该结点endpos集合的大小 ...
- Linux下gcc与g++用法以及编写makefile
1. gcc与g++编译流程: 1) 编译流程: 2) 预处理:生成.i的预处理文件. Ø 只激活预处理,这个不生成文件,需要把它重定向一个输出文件. ...