基于OPENCV的手势识别技术

基于OPENCV的手势识别技术  本篇博客主要介绍基于OPENCV的手势识别程序,代码为C++,OPENCV版本为OPENCV3会有较为详细的实现流程和源码,并且做到源码尽量简单,注释也自认为较为清晰,希望能帮助到大家。
摘要由CSDN通过智能技术生成

基于OPENCV的手势识别技术

 

前言:
  本篇博客主要介绍基于OPENCV的手势识别程序,代码为C++,OPENCV版本为OPENCV4会有较为详细的实现流程和源码,并且做到源码尽量简单,注释也自认为较为清晰,希望能帮助到大家。(源码将放在文章末尾的链接中,代码较为粗糙,有错误欢迎大家指出。)

 
 
一、手势识别流程图
流程图
  首先是对于流程图的简单说明:两条线是分开进行的,两者在比对分类之前是不会互相影响的(当然有部分函数,例如提取特征的函数,是在两条线中都是会使用到的),因此可以分别完成两条线的工作。如果作为需要分工的项目,可以按照这两部分进行分工,最后进行整合。
 
  而关于两条线的顺序,个人认为是优先进行神经网络的训练部分(也就是下方线路),原因是对于要识别的手势,首先要有对应的样本,优先去寻找样本,以此确定能够识别的手势。(当然,要是已经找到了样本,先做上方线路也没啥太大问题)
 
本篇文章的顺序:
先讲对于图片的处理:
  因为先明白图片如何处理,并知道提取特征的方法,才能理解要把什么东西放到神经网络里,得到的数据又是什么。
再讲神经网路的搭建:
  神经网路的搭建其实就是一个模板性的东西,计算机并不知道你要识别的东西到底是什么,是数字还是手势,对于计算机来说它只是一堆数据,它只负责给你找到——你输入的数据在网络里跟哪个数据最为匹配,然后就给你输出。
 
 
二、读取图片、获取皮肤部分及二值化
 
1)读取图片部分:
  并没有过多好说的,直接使用imread函数对图片进行读入。(注意,读入的图片应该是彩色的而不是灰度图,否则无法进行后面的皮肤区域获取)
 
2)获取皮肤部分及二值化:
  关于皮肤部分的获取,这里列出几种算法。由于图片的光照等的不同,不同算法的优劣也很难对比,各位自行选择算法。
 
①基于RGB颜色空间的简单阈值肤色识别:
 
  根据他人的研究,我们可以知道有这样的一条判别式来用于肤色检测
 
R>95 && G>40 && B>20 && R>G && R>B && Max(R,G,B)-Min(R,G,B)>15 && Abs(R-G)>15
 
  有了条判别式,我们就能够很容易地写出代码来实现肤色检测。但该算法对于光线的抗干扰能力较弱,光线稍微不好就识别不出皮肤点。

Mat getSkin(Mat& ImageIn)//获取皮肤的区域,返回二值化图像
{
   
	vector<Mat> r_g_b;//用于存放RGB分量
	split(ImageIn,r_g_b);//分离RGB分量,顺序为B,G,R

	Mat Binary = Mat::zeros(ImageIn.size(),CV_8UC1);

	Mat R = r_g_b[2];
	Mat G = r_g_b[1];
	Mat B = r_g_b[0];

	for (int i = 0; i < ImageIn.rows; i++)
	{
   
		for (int j = 0; j < ImageIn.cols; j++)
		{
   
			if (R.at<uchar>(i, j) > 95 && G.at<uchar>(i, j) > 40 && B.at<uchar>(i, j) > 20 &&
				R.at<uchar>(i, j) > G.at<uchar>(i, j) && R.at<uchar>(i, j) > B.at<uchar>(i, j) &&
				MyMax(R.at<uchar>(i, j), G.at<uchar>(i, j), B.at<uchar>(i, j)) - MyMin(R.at<uchar>(i, j), G.at<uchar>(i, j), B.at<uchar>(i, j)) > 15
				&& abs(R.at<uchar>(i, j) - G.at<uchar>(i, j)) > 15)
			{
   
				Binary.at<uchar>(i, j) = 255;
			}
		}
	}
	
	return Binary;
}

  代码说明:首先对彩色图片分离开R、G、B分量,然后根据公式,将每一个点的R、G、B分量代入公式中进行判断,符合条件的点我们可以认为它是皮肤中的一个点。(其中的MyMax和MyMin是自写的判断大小函数)将认为是皮肤的点的值置为255,就可以达到二值化的效果。

二值化后的结果
  可以看到除了部分因为光线问题导致的阴影没有被识别出来以外,几乎所有皮肤点都被识别出来了,效果还过得去。
 
 
②基于椭圆皮肤模型的皮肤检测
 
  研究发现,将皮肤映射到YCrCb空间,则在YCrCb空间中皮肤的像素点近似成一个椭圆的分布。因此如果我们得到了一个CrCb的椭圆,对于一个点的坐标(Cr, Cb),我们只需判断它是否在椭圆内(包括边界)就可以得知它是不是肤色点。
  该算法对于光线的敏感性没有这么高,基本上该检测到的皮肤都能够检测到,抗干扰能力相对较强。(原因大概是YCrCb中Y分量表示明亮度,而而“Cr”和“Cb” 表示的则是色度,作用是描述影像色彩及饱和度)

Mat getSkin2(Mat& ImageIn)
{
   
	Mat Image = ImageIn.clone();//复制输入的图片

	//利用OPENCV自带的ellipse函数生成一个椭圆的模型
	Mat skinCrCbHist = Mat::zeros(Size(256, 256), CV_8UC1);
	ellipse(skinCrCbHist, Point
  • 114
    点赞
  • 461
    收藏
    觉得还不错? 一键收藏
  • 88
    评论
评论 88
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值