基于机器学习的笑脸检测

摘 要
目前已经有很多的基于机器学习的方法用来进行人脸面部表情分析,然而,它们中的大部分都是在公开人脸库上进行测试。这些公开库里面仅有为数不多的几个人的图片,而且通常都是光照条件良好的图片。因此,用这些公开库做的表情分析算法,当应用在实际图片中的情况下,并不见得能取得较好的效果。为提升人工智能环境下笑脸表情识别正确率, 将笑脸表情识别与人工智能更好地结合起来, 进行笑脸识别技术研究。采用Viola-Jones算法检测人脸, 利用Gabor和HOG两种特征提取方法提取人脸特征和嘴部特征, 将提取的特征交叉组合成融合特征, 输入到支持向量机进行分类, 达到笑脸识别目的。另外提出了一种基于嘴角坐标关系的笑脸检测识别方法, 该方法采用Shi&Tomasi角点检测算法对嘴部进行角点检测得到嘴部特征, 再通过计算嘴角坐标平均值进行笑脸识别。实验结果表明, 基于嘴角坐标法识别笑脸正确率为92%, 高于Gabor和HOG特征提取方法。
关键词 角点检测;笑脸检测;特征提取;支持向量机;特征曲线
 

引言
面部表情是由人脸肌肉的运动形成的, 是情感变化在面部可观察到的表现。面部表情的变化能显示人的心理活动, 调整人之间的社会行为。随着服务机器人产业的兴起, 模式识别走进大众视野, 人们对表情的研究也逐渐增多。其中笑脸识别技术被广泛应用于机器人视觉及数码相机等智能设备。
近年来研究学者提出了多种笑脸检测的方法, 例如深圳华为技术有限公司获得了笑脸检测发明专利权, 其原理主要是通过获取到的人脸视频中嘴部的运动信息来判断是否检测到笑脸;何聪利用一种高层次仿真生物视觉方法来实现笑脸的识别与分类, 该方法主要基于生物启发特征来进行笑脸的特征提取和分类;陈俊研究了基于生物启发特征的真实环境下的笑脸识别, 构造了一个符合人类识别机制的笑脸分类系统;郭礼华等人利用分层梯度方向直方图 (Pyramid Histogram of Oriented Gradients, PHOG) 特征与聚类特征选择进行笑脸识别;严新平融合局部二值模式 (LOCAL BinarPatterns, LBP) 特征与HOG特征来进行笑脸识别研究。
采用Viola-Jones算法来检测人脸, 可将人脸部分提取出来, 采用HOG和Gabor两种特征提取方法提取图片特征, 并送入支持向量机 (support vector machine, SVM) 进行训练。通过观察训练样本中的不同表情, 发现嘴唇的形状变化最能代表不同表情。同时嘴唇外周的特征例如法令纹等, 则不是十分清晰, 不同的图片效果差异很大, 不适合作为判断表情的标准。通过对嘴部特征点拟合曲线进行分析发现, 笑脸的拟合曲线会产生明显的弧度并且拟合曲线两个端点纵坐标的平均值较小, 而其他表情的拟合曲线则接近一条水平线且拟合曲线两个端点纵坐标的平均值较大。故此提出一种基于嘴角坐标平均值变化的笑脸识别方法, 该方法通过对嘴角坐标的计算, 可以准确识别笑脸表情。图1为其主要工作流程。
 

1 人脸检测
检测采用Viola-Jones算法来识别人脸和嘴部。该算法是由Paul viola和Michael J.Jones共同提出的一种人脸检测框架。它极大地提高了人脸检测的速度和准确率。该算法利用积分图像来提取图像特征值, 利用adaboost分类器的特征筛选特性, 保留最有用特征, 从而有效减少了检测时的运算复杂度, 提升了运算速度。同时将adaboost分类器进行改造, 变成级联adaboost分类器, 提高了人脸检测的准确率。
Viola-Jones算法采用haar-like特征提取方法。Haar-like是由许多黑白块组成的, 分别将白色和黑色区域中的所有像素相加, 然后做差, 就是区域的特征值, 即:

(1)
但是考虑到多尺度问题, 即利用不同大小的扫描窗口去检测不同大小的人脸的问题, 这个特征需要进行归一化处理。首先选定检测窗口的大小, 利用这个窗口对整个图像进行滑动, 每滑动到一个位置, 就在窗口中提取一系列haar-like特征。由于哈尔特征极多, 而这些特征中只有一小部分是有用的, 所以采用adaboost分类器进行特征选择。adaboost分类器的原理就是构造一个由多个弱分类器并联而成的强分类器, 每个弱分类器都根据自己的准确率将自己的分类结果乘以权值, 最后的输出是所有弱分类器输出的加权和。每个弱分类器的分类准确率可以很低, 但是整个强分类器的准确率却会很高。图2为采用Viola-Jones算法提取人脸部分和嘴唇部分。
16.    public class WordCount {
17.    
18.      public static class TokenizerMapper 
19.           extends Mapper<Object, Text, Text, IntWritable>{
20.        
21.        private final static IntWritable one = new IntWritable(1);
22.        private Text word = new Text();
23.          
24.        public void map(Object key, Text value, Context context
25.                        ) throws IOException, InterruptedException {
26.          StringTokenizer itr = new StringTokenizer(value.toString());
27.          while (itr.hasMoreTokens()) {
28.            word.set(itr.nextToken());
29.            context.write(word, one);
30.          }
31.        }
32.      }
33.      
34.      public static class IntSumReducer 
35.           extends Reducer<Text,IntWritable,Text,IntWritable> {
36.        private IntWritable result = new IntWritable();
37.    
38.        public void reduce(Text key, Iterable<IntWritable> values, 
39.                           Context context
40.                           ) throws IOException, InterruptedException {
41.          int sum = 0;
42.          for (IntWritable val : values) {
43.            sum += val.get();
44.          }
45.          result.set(sum);
46.          context.write(key, result);
47.        }
48.      }
49.    
50.      public static void main(String[] args) throws Exception {
51.        Configuration conf = new Configuration();
52.        String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
53.        if (otherArgs.length < 2) {
54.          System.err.println("Usage: wordcount <in> [<in>...] <out>");
55.          System.exit(2);
56.        }
57.        Job job = Job.getInstance(conf, "word count");
58.        job.setJarByClass(WordCount.class);
59.        job.setMapperClass(TokenizerMapper.class);
60.        job.setCombinerClass(IntSumReducer.class);
61.        job.setReducerClass(IntSumReducer.class);
62.        job.setOutputKeyClass(Text.class);
63.        job.setOutputValueClass(IntWritable.class);
64.        for (int i = 0; i < otherArgs.length - 1; ++i) {
65.          FileInputFormat.addInputPath(job, new Path(otherArgs[i]));
66.        }
67.        FileOutputFormat.setOutputPath(job,
68.          new Path(otherArgs[otherArgs.length - 1]));
69.        System.exit(job.waitForCompletion(true) ? 0 : 1);
70.      }
71.    }
 

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>