Android人脸检测汇总PlaySvervice

Play Svervice视觉库的一个主要组件,Face Detection

人脸检这一功能经常用到,我们可以使用android系统提供的API进行人脸检测,也可以使用OpenCv等三方库进行人脸检测

Google Play服务8.1中引入了视觉库,作为一个开发者,Face Detection让你可以更容易的通过分析视频或图像来定位人脸(face)。

如果想了解更多请查看 官方文档

使用方法:

build.gradle文件中添加依赖库,8.1以上版本可以根据自己需求添加

1
2
3
4
5
6
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
...
...
compile 'com.google.android.gms:play-services:9.8.0'
}

AndroidManifest.xml的Application 中添加如下代码

1
<meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="face"/>

接下来我们获取位图对象,这是实例具体可以根据自己的方式获取Bitmap对象

1
2
InputStream stream = getResources().openRawResource( R.raw.face );
Bitmap bitmap = BitmapFactory.decodeStream(stream);

下面正式进入人脸检测阶段:

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
import com.google.android.gms.vision.face.Face;//导入人脸对象
import com.google.android.gms.vision.face.FaceDetector;//导入人脸检测器

... ... ...

/** 创建人脸检测器 */
FaceDetector detector = new FaceDetector.Builder( getContext() )
.setTrackingEnabled(false)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.setMode(FaceDetector.FAST_MODE)
.build();

... ... ...

/** 进行人脸检测 */
if (!detector.isOperational()) {//判断人脸检测器是否可用
//Handle contingency
} else {
Frame frame = new Frame.Builder().setBitmap(bitmap).build();//需要将Bitmap文件转换成Frame对象
Face[] mFaces = detector.detect(frame);
detector.release();//使用后及时释放资源

for( int i = 0; i < mFaces.size(); i++ ) {
Face face = mFaces.valueAt(i);
//绘制人脸框, scale为图片实际大小与显示大小的比例
left = (float) ( face.getPosition().x * scale );
top = (float) ( face.getPosition().y * scale );
right = (float) scale * ( face.getPosition().x + face.getWidth() );
bottom = (float) scale * ( face.getPosition().y + face.getHeight() );

canvas.drawRect( left, top, right, bottom, paint );
}
}

通过上面代码我们获取到了人脸信息,并将之绘制到图片上去,别急还有其他功能,通过人脸对象我们还可以获取到人脸关键点的信息,

共十二个关键点信息:左右眼 左右耳 左右耳廓尖 鼻子基部 左右脸颊 嘴的左右角 嘴基部

注:关键点信息的多少取决于人脸角度

主要代码如下:

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
//通过Face对象获取人脸关键点集合
List<Landmark> landmark = face.getLandmarks()

... ... ...

//通过循环画出所有人脸关键点信息
for ( Landmark landmark : face.getLandmarks() ) {
int cx = (int) ( landmark.getPosition().x * scale );
int cy = (int) ( landmark.getPosition().y * scale );
canvas.drawCircle( cx, cy, 10, paint );
}


//Landmark对象
public static final int BOTTOM_MOUTH = 0;
public static final int LEFT_CHEEK = 1;
public static final int LEFT_EAR_TIP = 2;
public static final int LEFT_EAR = 3;
public static final int LEFT_EYE = 4;
public static final int LEFT_MOUTH = 5;
public static final int NOSE_BASE = 6;
public static final int RIGHT_CHEEK = 7;
public static final int RIGHT_EAR_TIP = 8;
public static final int RIGHT_EAR = 9;
public static final int RIGHT_EYE = 10;
public static final int RIGHT_MOUTH = 11;
private final PointF aOa;
private final int nV;

上面我们知悉了人脸检测,人脸关键点的获取,接下来我们学习额外人脸数据的获取,通过这些数据我们可以判断人练动作,是不是很有意思!!!

getIsSmilingProbability(),getIsLeftEyeOpenProbability()和getIsRightEyeOpenProbability()方法会返回一个0.0到1.0的浮点数,你可以用其确定眼睛是否睁开或者检测到的这个人是否在笑。返回值越接近1.0,这个人就越有可能在小或者他的左右眼越有可能是睁开的。

你也可以通过检查图像的欧拉值找出一张图像中人脸在Y轴和Z轴上的角度。Z欧拉值的一直都能收到。但是,要想接受到X值你必须使用精确模式。在下面的代码片段中你会看到如何获取这些值。

1
2
3
4
5
6
7
8
for( int i = 0; i < mFaces.size(); i++ ) {
Face face = mFaces.valueAt(i);
float smilingProbability = face.getIsSmilingProbability();//微笑
float leftEyeOpenProbability = face.getIsLeftEyeOpenProbability();//左眼状态
float rightEyeOpenProbability = face.getIsRightEyeOpenProbability();//右眼状态
float eulerY = face.getEulerY();
float eulerZ = face.getEulerZ();
}
  • 欧拉Y角度参考
1
2
3
4
5
6
欧拉 Y 角度	     可见的关键点
< -36° 左眼,嘴的左半边,左耳,鼻子基部,左脸颊
-36° to -12° 嘴的左半边,鼻子基部,嘴的底部,右眼,左眼,左脸颊,左耳尖
-12° to 12° 右眼,左眼,鼻子基部,左脸颊,右脸颊,嘴的左半边,嘴的右半边,嘴的底部
12° to 36° 嘴的右半边,鼻子基部,嘴的底部,左眼,右眼,右脸颊,右耳尖
> 36° 右眼,嘴的右半边,右耳,鼻子基部,右脸颊