1. FectDetector
人脸的检测方法是用双眼来检测人脸的位置,也就是说无法检测到嘴、侧脸等,双眼必须同时可见,并且眼镜会影响检测的效果。实际上,FaceDetector检测到的并不是人的全脸,而只是双眼。输入图片必须为Bitmap RGB565格式
图片太小的话检测不到人脸,小于100x100的图片检测不到人脸,由于Android内存有限,图片太大的话,会出现无法加载图片的异常。
检测到的人脸存放到FaceDetector.Face类中,该类无法再扩展。从该类可以获取到人眼的中心位置和双眼之间的具体。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
// 图片路径
//setContentView(R.layout.activity_main);
//String path = "sdcard/1.jpg";
//String path = "sdcard/2.jpg";
//hasFace(path);
}
/**
* 判断图片中是否存在一个人脸
*
* @param path 图片路径
* @return true, 存在人脸; false, 不存在人脸.
*/
private boolean hasFace(String path) {
BitmapFactory.Options options = new BitmapFactory.Options();
// 必须为RGB_565
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int numberOfFace = 10;
FaceDetector.Face[] faces = new FaceDetector.Face[numberOfFace];
FaceDetector faceDetector = new FaceDetector(width, height, numberOfFace);
int number = faceDetector.findFaces(bitmap, faces);
return number != 0;
}
private class MyView extends View {
/** 人脸的数量 */
private static final int NUMBEROFFACE = 10;
/** 图片宽度和高度 */
private int mImageWidth, mImageHeight;
/** 人脸识别工具类 */
private FaceDetector myFaceDetect;
/** 识别到的人脸数组 */
private FaceDetector.Face[] mFaces;
/** 眼睛的位置 */
private float mEyesDistance;
/** 识别出的人脸总数 */
private int mNumberOfFaceDetected;
/** 要识别的图片 */
private Bitmap mBitmap;
public MyView(Context context) {
super(context);
// 创建图像参数
BitmapFactory.Options options = new BitmapFactory.Options();
// 设置图片涂色格式为RGB_565
options.inPreferredConfig = Bitmap.Config.RGB_565;
// 创建一个Bitmap
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.wqer, options);
// 获取图片的宽度
mImageWidth = mBitmap.getWidth();
// 获取图片的高度
mImageHeight = mBitmap.getHeight();
// 创建人脸数组
mFaces = new FaceDetector.Face[NUMBEROFFACE];
// 创建图片解析
myFaceDetect = new FaceDetector(mImageWidth, mImageHeight, NUMBEROFFACE);
// 获取人脸的数量
mNumberOfFaceDetected = myFaceDetect.findFaces(mBitmap, mFaces);
}
@Override protected void onDraw(Canvas canvas) {
// 绘制原图
canvas.drawBitmap(mBitmap, 0, 0, null);
// 创建一个抗锯齿的画笔
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 设置画笔的颜色
paint.setColor(Color.GREEN);
// 设置画笔的风格,粗体
paint.setStyle(Paint.Style.STROKE);
// 设置画笔的宽度
paint.setStrokeWidth(3);
// 打印识别出的人脸数量
Log.e(TAG, mNumberOfFaceDetected + "");
// 遍历人脸数组
for (int i = 0; i < mNumberOfFaceDetected; i++) {
// 获取相应位置的人脸
FaceDetector.Face face = mFaces[i];
// 创建一个长度可为小数的矩形
PointF pointF = new PointF();
// 从人脸中获取到中心点
face.getMidPoint(pointF);
// 从人脸中获取到眼睛的位置
mEyesDistance = face.eyesDistance();
// 打印人脸的位置
Log.e(TAG, mEyesDistance + "");
// 画出矩形
canvas.drawRect(
// 左上角横轴坐标
(int) (pointF.x - mEyesDistance),
// 左上角纵轴坐标
(int) (pointF.y - mEyesDistance),
// 右下角横轴坐标
(int) (pointF.x + mEyesDistance),
// 右下角纵轴坐标
(int) (pointF.y + mEyesDistance),
// 画笔
paint);
}
}
}
}
效果图:
2. Play Services Vision
1). 导入库
- app/build.gradle文件添加依赖
compile 'com.google.android.gms:play-services-vision:8.1.0'
- AndroidManifest.xml文件中添加
<meta-data
android:name="com.google.android.gms.vision.DEPENDENCIES"
android:value="face"/>
2). 自定义View
public class FaceOverlayView extends View {
private Bitmap mBitmap;
private SparseArray<Face> mFaceSparseArray;
public FaceOverlayView(Context context) {
this(context, null);
}
public FaceOverlayView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FaceOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 设置Bitmap
* @param bitmap bitmap
*/
public void setBitmap(Bitmap bitmap) {
this.mBitmap = bitmap;
// 创建一个人脸识别工具
FaceDetector detector =
new FaceDetector.Builder(getContext())
.setTrackingEnabled(true)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.setMode(FaceDetector.FAST_MODE)
.build();
// 判断是否可以使用
if (!detector.isOperational()) {
// 不可用
Toast.makeText(getContext(), "不可用", Toast.LENGTH_SHORT).show();
} else {
// 根据图片创建一帧
Frame frame = new Frame.Builder().setBitmap(bitmap).build();
// 使用工具解析这一帧,获取到人脸的数组
mFaceSparseArray = detector.detect(frame);
// 释放工具
detector.release();
}
// 重绘
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (null != mBitmap && null != mFaceSparseArray) {
double scale = drawableBitmap(canvas);
drawFaceBox(canvas, scale);
}
}
/**
* 画脸框
* @param canvas 绘图工具
* @param scale 缩放工具
*/
private void drawFaceBox(Canvas canvas, double scale) {
// 创建画笔
Paint paint = new Paint();
// 设置颜色
paint.setColor(Color.GREEN);
// 设置风格
paint.setStyle(Paint.Style.STROKE);
// 设置线宽2
paint.setStrokeWidth(5);
float left;
float top;
float right;
float bottom;
// 遍历数组
for (int i = 0; i < mFaceSparseArray.size(); i++) {
// 获取对应的脸部信息
Face face = mFaceSparseArray.valueAt(i);
// 获取所上角坐标
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);
}
}
/**
* 绘图
* @param canvas 绘图工具
* @return 返回缩放比
*/
private double drawableBitmap(Canvas canvas) {
// 获取view的宽高
double viewWidth = canvas.getWidth();
double viewHeight = canvas.getHeight();
// 获取图片宽高
double imageWidth = mBitmap.getWidth();
double imageHeight = mBitmap.getHeight();
// 获取缩放比
double scale = Math.min(viewWidth / imageWidth, viewHeight / imageHeight);
// 矩形框
Rect destBounds = new Rect(0, 0, (int)(imageWidth * scale), (int)(imageHeight * scale));
// 绘制图片
canvas.drawBitmap(mBitmap, null, destBounds, null);
// 返回缩放比
return scale;
}
}
3). 使用
activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.mazaiting.visiontest.MainActivity">
<com.mazaiting.visiontest.FaceOverlayView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/face_overlay"
/>
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FaceOverlayView faceOverlayView = (FaceOverlayView) this.findViewById(R.id.face_overlay);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.face);
faceOverlayView.setBitmap(bitmap);
}
}
4). 示例图