很多手机图片管理应用都开始集成人脸识别功能。一提到人脸识别,模式识别,滤波,BlahBlah 一堆复杂的技术名字戳入脑海中,立刻觉得这玩意儿没法碰,太玄乎了。其实Android SDK从1.0版本中(API level 1)就已经集成了简单的人脸识别功能,通过调用FaceDetector 我们可以在Android平台上实现Bitmap多人脸识别(一张图中有多个人脸出现的话)。周五啦,我就简简单单写写,希望感兴趣的同学对这个深藏在Android SDK中的功能有所了解。
流程是这样的:
1. 读取一张图片至Bitmap (从Resource中,或是从手机相册中选取)
2. 使用FaceDetector API分析Bitmap,将探测到的人脸数据以FaceDetector.Face存储在一个Face list中;
3.将人脸框显示在图片上。
Step 1: 读取图片
从Drawable中读取图片资源
1 |
|
或者直接从手机的图片库读取(Album/Gallery)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
当然,也可以直接从摄像头读取(Camera Capture)。但我读摄像头返回图片的代码在模拟器上运行正常,而在三星的手机上Bug多多,后来看了下确实不少人遇到读取三星手机摄像头报错的问题。所以这段代码我就先不贴了。
好了,我们拿到了Bitmap,识别起来!
Step 2: 通过FaceDetector API进行人脸识别
FaceDetecor只能读取RGB 565格式的Bitmap,所以在开始识别前,我们需要将上面得到的Bitmap进行一次格式转换。
1 |
|
图片格式没问题了,我们来创建一个FaceDetector的实例。FaceDetector是能从一张图中找出多个人脸的,可以通过设置MAX_FACES来控制搜索人脸的个数(我的程序里把MAX_FACES设成了1,只找出一个可信度最高的人脸)。
1 |
|
1 2 |
|
通过调用FaceDetector 的findFaces方法,我们可以找到tmpBmp中的人脸数据,并存储在FaceDetector.Face 数组里(facelist)。
其实通过查看FaceDetector API文档我们发现,它查找人脸的原理是:找眼睛。它返回的人脸数据face,通过调用public float eyesDistance (),public void getMidPoint (PointF point),我们可以得到探测到的两眼间距,以及两眼中心点位置(MidPoint)。public float confidence () 可以返回该人脸数据的可信度(0~1),这个值越大,该人脸数据的准确度也就越高。
通过读取保存在Face中的人脸数据,我们可以得到一个以两眼间距为边长,中心在两眼中点的一个正方形。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
有了这组RectF,把它显示在图片上,我们就大功告成了。
Step3:对原图进行缩放,并在图上显示人脸框。
自然,这里我们需要使用一个自定义的View。我把它命名为FaceView,每当FaceView人脸检测完成,如果检测到人脸,则invalidate一下(这样才能调用View 的 onDraw方法),然后在onDraw里,将人脸框显示出来。这里涉及到自定义View,以及图片,人脸框的按比例缩放。这里贴一下大概的代码,示例代码你可以在文末的链接里下载。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|
注意:FaceDetector搜索人脸的过程是比较耗时的,尤其当图片Size较大(例如640*480)时,耗时个一两秒是很常见的。为防止程序长时间没相应报错,人脸检测部分我使用了AsyncTask