基于反向投影的肤色学习以及手势模型建立
来源:互联网 发布:程序员 1000万 编辑:程序博客网 时间:2024/04/25 09:06
主要想做的内容:
- 在室内条件下,用一些手和脸来建立H-S直方图(肤色的直方图)
- 利用函数calcbackproject()来找到肤色区域,分别代表了不同手势
- 对所找到的手势进行直方图建立模型,从而可作为后续输入手势的手势识别器。
操作过程:
首先是肤色直方图的建,我使用的是如左下图所示的皮肤图像,可以计算出其二维直方图,作为肤色的描述子,如右图所示。
下一步是通过calcbackproject()寻找不同手势,这一步比较简单,如下图所示为反投影出的一些手势
手势1
手势2
手势3
下一步需要建立不同手势的直方图,但从以上结果可以看到,投影出的结果不是很理想,除了有噪声外,轮廓内部有很多黑洞(我们希望是实心的)。以下处理过程只使用一幅图片为例子。
我的处理思路是:
- 形态学去噪
首先将投影出的图像转换为二值化图像,更易于处理,使用开操作+闭操作的方法去噪 - 轮廓提取
轮廓提取有两个目的,一是通过检测轮廓长度可以去除较小的轮廓(同样是噪声),二是可以提取出手型轮廓的坐标信息。 - 漫水填充
计算轮廓坐标的质心,可以认为在手型的内部。可以将该点作为种子点,做漫水填充,这一步是为了解决轮廓内很多黑洞的问题。
下图为形态学去噪的结果,除了黑洞外,还是有一些小噪声。
形态学去噪
再对形态学去噪图像的轮廓提取图像,由于要求轮廓长度大于图像周长的四分之一,右上角的小块噪声已经不见了,如下图。
轮廓图像
通过计算轮廓的零阶矩和一阶矩就可以计算出轮廓的质心坐标,该坐标作为下一步漫水填充的种子点。
为漫水填充的算法的使用建立一个新的模板,填充过后为1的点,我们就可以认为是手势的区域,该mask可以传入直方图计算函数,仅仅计算手势的直方图分布。
在试验过程中可以发现opencv中漫水填充算法中的lodiff和updiff并不好选,需要多次尝试才可以找到比较满意的结果,由于手的边缘有一些阴影,因此如果lodiff取的较大的话常常会得到更多的填充区域。
如下图,为填充过后的模板区域。
漫水填充结果
可以跟最初反投影计算结果比较,此时的模板更加符合一个剪刀手势了,也就是我们真正感兴趣的区域。通过下一步函数,就可以建立该手势的直方图。
Hist = cvCalcHist(img,hist_size,range,1,flood_fill_mask);
因此,通过不同的手势图像学习,我们就可以获得不同手势的直方图了,即完成手势模型的建立。
后续实验:
既然已经建立了手势的模型,我便希望可以完成手势识别,采用了基于块的反向投影函数calcbackprojectpatch(),实验图像如左下所示,实验结果右下所示:
可以看出在复杂的背景条件下,同时检测出了手势以及脸型。因此可以说明前面所建立的剪刀手直方图是不完善的,即可以检测出皮肤,但对皮肤形状不能进行分类,因此,如果将更多的信息考虑在内,可能会收获更好地效果(例如轮廓HU矩)。
总结:
直方图是一种基于统计学的操作,不受平移或旋转的影响,因此它用于目标信息的学习和检测效果还是不错的。但该方法会受到光线变化、阴影等影响,一种解决办法是学习不同光照下的直方图,进行多次匹配,但从实验过程中可知,直方图匹配的过程是比较慢的,因此实时性较差。
#include<cv.h>#include<highgui.h>using namespace cv;int main(){ Mat skin_learning = imread("skin.jpg"); Mat gesture = imread("gesture.jpg"); Mat hsv_skin; Mat hsv_gesture; cvtColor(skin_learning, hsv_skin, CV_BGR2HSV); cvtColor(gesture, hsv_gesture, CV_BGR2HSV); int hbins = 20, sbins = 22; int histSize[] = {hbins, sbins}; // hue varies from 0 to 179, see cvtColor float hranges[] = { 0, 180 }; // saturation varies from 0 (black-gray-white) to // 255 (pure spectrum color) float sranges[] = { 0, 256 }; const float* ranges[] = { hranges, sranges }; MatND hist; // we compute the histogram from the 0-th and 1-st channels int channels[] = {0, 1}; calcHist( &hsv_skin, 1, channels, Mat(), // do not use mask hist, 2, histSize, ranges, true, // the histogram is uniform false ); //反投影 MatND back_pro; calcBackProject(&hsv_gesture,1,channels,hist,back_pro,ranges,1.0); //二值化 threshold(back_pro,back_pro,30,255,CV_THRESH_BINARY); //去噪 Mat k = getStructuringElement(MORPH_RECT,Size(3,3), Point(-1,-1)); morphologyEx(back_pro,back_pro,MORPH_OPEN,k); morphologyEx(back_pro,back_pro,MORPH_CLOSE,k); ////寻找轮廓(目标为寻找质心),此处不直接使用掩模图像,也是为了多目标分离 //flood fill寻找区域 //利用mask建立手势直方图 MatND gesture_hist; calcHist( &hsv_gesture, 1, channels,back_pro , // use mask gesture_hist, 2, histSize, ranges, true, // the histogram is uniform false ); //读入图像测试 Mat test = imread("test.jpg"); Mat hsv; cvtColor(test,hsv, CV_BGR2HSV); MatND back_pro2; calcBackProject(&hsv,1,channels,gesture_hist,back_pro2,ranges,1.0); namedWindow("test"); imshow("test",test); namedWindow("backproject"); imshow("backproject",back_pro2); cvWaitKey(0); return 0;}
- 基于反向投影的肤色学习以及手势模型建立
- 基于人脸检测的肤色采集以及两种常见肤色模型建模
- 图像直方图和反向投影的肤色检测
- 基于高斯模型的彩色图像反向投影
- Opencv 基于肤色的手势分割
- opencv学习笔记(三十一)基于块的反向投影
- cvCalcBackProjectPatch() 基于块的反向投影
- 肤色检测算法 - 基于二次多项式混合模型的肤色检测。
- 肤色检测算法 - 基于二次多项式混合模型的肤色检测
- 肤色检测算法 - 基于二次多项式混合模型的肤色检测。
- 人脸--基于肤色模型的人脸检测研究
- OpenCV 反向投影, 基于块的反向投影 和 模板匹配
- 基于彩色直方图反向投影的CamShift追踪
- 直方图的反向投影
- 直方图的反向投影
- 反向投影的意义
- 直方图的反向投影
- 直方图的反向投影
- 递归原理及常见应用
- 一个整型数组中数字出现两次,但是只有2个数字出现一次,求解这两个只出现一次的数的代码
- 遍历Map集合四中方法
- Struts2学习记录1
- 第十一周项目1——二叉树算法验证(3) 中序线索化二叉树的算法验证
- 基于反向投影的肤色学习以及手势模型建立
- [BZOJ2276][Poi2011]Temperature(单调队列)
- hibernate入门第三课 导入必要的jar包
- 微信公众平台开发(二):交互与接口
- iOS App图标和启动画面尺寸
- source insight 字体乱码问题
- Vijos P1901 学姐的钱包
- 对高等数学中的基本概念的剖析
- Android动画机制-属性动画(一)