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应用程序).它可以用来测试静 ...
随机推荐
- thinkphp _complex 复合查询 where多个子组实现
SELECT * FROM `user` WHERE ( `mobile` = '13824653465' OR `nickname` = 'evan' OR `openid` = '14545-fd ...
- 纯CSS仿制Google女生节Doodle
看到google今天的女生节Doodle,自己用纯css仿制一个,送给老妈.老婆.女儿. 大家可以点这里在线观看效果,点这里下载收藏效果. 实现原理 1.利用checkbox侦听处理单击事件. 2.单 ...
- ECSHOP中 {insert name='ads' id=$ads_id num=$ads_num}含义
<div class="smallban"> <ul> <!-- TemplateBeginEditabl ...
- linux查找文件或目录命令
inux查找文件或目录命令,前提:知道文件或者目录的具体名字,例如:sphinx.conf find 查找 find / -name dirname 查找目录 find -name filenam ...
- 关于table边框,设置了border-collapse:collapse之后,设置border-radius没效果
做项目遇到边框需要设置圆角,然后发现在设置了border-collapse:collapse之后,border-radius:10px不起作用了,发现这个是css本身的问题,两者不能混在一起使用. 代 ...
- SpringBoot常用配置
前言:springboot集成了主流的第三方框架,但是需要使用springboot那一套配置方式.但是我这里只列举了非常非常常用的,可以看已发的几篇博客,慢慢会补充.当然官方文档里也有相应的配置,可惜 ...
- [Agc011F] Train Service Planning
[Agc011F] Train Service Planning 题目大意: 有n+1个车站,n条轨道,第i条轨道联通i-1和i车站,通过它要花a[i]时间,这条轨道有b[i]=1或2条车道,也就是说 ...
- POJ 2778 DNA Sequence(AC自动机+矩阵)
[题目链接] http://poj.org/problem?id=2778 [题目大意] 给出一些字符串,求不包含这些字符串的长度为n的字符串的数量 [题解] 我们将所有串插入自动机计算match,对 ...
- java集合之二(collection架构)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3308513.html 首先,我们对Collection进行说明.下面先看看Collection的一些框架 ...
- zoj 3157 Weapon 逆序数/树状数组
B - Weapon Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Submit Sta ...