Android 原生的人脸识别Camera+FaceDetector示例
Posted zhang106209
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 原生的人脸识别Camera+FaceDetector示例相关的知识,希望对你有一定的参考价值。
人脸识别google有自带api,Androoid 原生的人脸识别是利用相机的摄像功能和android.media.FaceDetector这个类来实现的
1、android.hardware.camera
1.1 简介
Camera 类用于设置图像捕获设置、开始/停止预览、抓拍图片和检索帧以进行视频编码
Camera的源码
1.2 人脸识别步骤:
1. 初始化相机并设置相机参数;
2. 设置预览监听setPreviewDisplay();
3. 开始预览startPreview();
4. 实现预览的接口onPreviewFrame并处理每一帧的数据转成Bitmap;
5. 通过 faceDetector.findFaces()发现人脸,注意:faceDetector只能识别Bitmap.Config.RGB_565的Bitmap
1.3 示例类
工具类CameraUtils
package com.zw.camera2test.camera;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.os.SystemClock;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
public class CameraUtils implements Camera.PreviewCallback
private static final String TAG = "Camera2Utils";
private SurfaceView mSurfaceView;
private FaceRectView mFaceRectView;
private static CameraUtils mCameraUtils;
private SurfaceHolder mSurfaceViewHolder;
private int cameraPosition = 1; //0 后置 1 前置
private Camera mCamera;
private int CAMERA_WIDHT = 640;
private int CAMERA_HEIGHT = 480;
// private int CAMERA_WIDHT = 320;
// private int CAMERA_HEIGHT = 240;
private boolean detectFace = false;
private MediaRecorder mediaRecorder;
/***录制视频的videoSize*/
private int height = 480, width = 640;
/***保存的photo的height ,width*/
private int heightPhoto = 480, widthPhoto = 640;
private CameraErrorCallback cameraErrorCallback;
public static CameraUtils getInstance()
if (mCameraUtils == null)
synchronized (CameraUtils.class)
if (mCameraUtils == null)
mCameraUtils = new CameraUtils();
return mCameraUtils;
public void initCamera(SurfaceView surfaceView, FaceRectView faceRectView)
this.mSurfaceView = surfaceView;
this.mFaceRectView = faceRectView;
mSurfaceViewHolder = mSurfaceView.getHolder();
mSurfaceViewHolder.setFormat(PixelFormat.OPAQUE);
surfaceHolderCB = new SurfaceHolderCB();
SurfaceHolderCB surfaceHolderCB;
public void startCamera()
if (mSurfaceViewHolder != null)
mSurfaceViewHolder.addCallback(surfaceHolderCB);
public void stopCamera()
stopPreview();
//打开摄像头失败
public static final int ERROR_CAMERA_OPEN = 100001;
public void startPreview()
Log.i(TAG, "--11111---2-----" + mCamera);
if (mCamera != null)
stopCamera();
if (mCamera == null)
Log.i(TAG, "startPreview: " + cameraPosition);
try
mCamera = Camera.open(cameraPosition);
Log.i(TAG, "startPreview:------ " + (Camera.getNumberOfCameras() - 1));
catch (RuntimeException e)
Log.i(TAG, "startPreview: 方法有问题");
if (cameraErrorCallback != null)
cameraErrorCallback.onCameraError(ERROR_CAMERA_OPEN);
return;
Camera.Parameters parameters = setParameters(mCamera, cameraPosition);
if (parameters.getMaxNumDetectedFaces() > 0)
Log.e("tag", "【FaceDetectorActivity】类的方法:【startFaceDetection】: " + parameters.getMaxNumDetectedFaces());
else
Log.e("tag", "【FaceDetectorActivity】类的方法:【startFaceDetection】: " + "不支持");
mCamera.setDisplayOrientation(0);
mCamera.setErrorCallback(cameraErrorCallback);
try
if (cameraPosition == 0)
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); //后置必须聚焦设置
mCamera.setPreviewDisplay(mSurfaceViewHolder);
mCamera.setParameters(parameters);
if (mCamera != null)
mCamera.setPreviewCallback(this);
catch (IOException e)
Log.i(TAG, "startPreview: " + e.getMessage());
Camera.Parameters parameters1 = mCamera.getParameters();// 得到摄像头的参数
mCamera.setParameters(parameters1);
mCamera.startPreview();
mCamera.cancelAutoFocus();//聚焦
detectFace = true;
/**
* 脸部检测接口
*/
private class FaceDetectorListener implements Camera.FaceDetectionListener
@Override
public void onFaceDetection(Camera.Face[] faces, Camera camera)
if (faces.length > 0)
int score = faces[0].score;
Log.i(TAG, "onFaceDetection: score " + score);
detectFace = true;
mFaceRectView.drawFaceRects(faces, mSurfaceView, cameraPosition);
else
Log.i(TAG, "onFaceDetection: 没有人脸 ");
detectFace = false;
mFaceRectView.clearRect();
public void setDetectFace(boolean detectFace)
this.detectFace = detectFace;
/**
* 切换前后相机
*/
public void changeCamera(CurrentCameraPositionInterface cameraPositionInterface)
int numberOfCameras = Camera.getNumberOfCameras();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
if (numberOfCameras >= 2)
if (cameraPosition == 0) //现在为后置,变成为前置
Camera.getCameraInfo(1, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) //CAMERA_FACING_FRONT 前置方位 CAMERA_FACING_BACK 后置方位
if (mCamera != null)
stopPreview();
cameraPosition = 1;
startPreview();
else if (cameraPosition == 1) //前置更改为后置相机
Camera.getCameraInfo(0, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK)
if (mCamera != null)
stopPreview();
cameraPosition = 0;
startPreview();
cameraPositionInterface.cameraPosition(cameraPosition);
private class SurfaceHolderCB implements SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder)
Log.i(TAG, "--11111--------" + holder);
startPreview();
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
Log.i(TAG, "--2222222--------" + holder);
@Override
public void surfaceDestroyed(SurfaceHolder holder)
holder.removeCallback(this);
stopPreview();
@Override
public void onPreviewFrame(byte[] data, Camera camera)
if (detectFace)
Bitmap bmp = byte2bitmap(data, camera);
mCurrentDetectFaceInterface.detectFace(bmp);
mCurrentDetectFaceInterface.detectFace2(bmp);
private Bitmap byte2bitmap(byte[] bytes, Camera camera)
Bitmap bitmap = null;
Camera.Size size = camera.getParameters().getPreviewSize(); // 获取预览大小
final int w = size.width; // 宽度
final int h = size.height;
final YuvImage image = new YuvImage(bytes, ImageFormat.NV21, w, h,
null);
ByteArrayOutputStream os = new ByteArrayOutputStream(bytes.length);
if (!image.compressToJpeg(new Rect(0, 0, w, h), 100, os))
return null;
byte[] tmp = os.toByteArray();
bitmap = BitmapFactory.decodeByteArray(tmp, 0, tmp.length);
Matrix matrix = new Matrix();
// matrix.setRotate(-90);
Log.i(TAG, "byte2bitmap: " + bitmap.getWidth() + "---" + bitmap.getHeight());
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return bitmap;
private void stopPreview()
if (mCamera != null)
try
mCamera.setPreviewCallback(null);
mCamera.setPreviewDisplay(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
catch (Exception e)
e.printStackTrace();
detectFace = false;
mFaceRectView.clearRect();
/**
* 开启闪光灯
*/
public void turnFlash()
try
if (mCamera == null || mCamera.getParameters() == null
|| mCamera.getParameters().getSupportedFlashModes() == null)
return;
Camera.Parameters parameters = mCamera.getParameters();
String mode = parameters.getFlashMode();
if (Camera.Parameters.FLASH_MODE_OFF.equals(mode))
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
else if (Camera.Parameters.FLASH_MODE_TORCH.equals(mode))
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(parameters);
catch (Exception e)
e.printStackTrace();
/**
* 调节预览的焦距
*
* @param maxValue
* @param currentValue
*/
public void changZoom(int maxValue, int currentValue)
if (mCamera != null)
Camera.Parameters parameters = mCamera.getParameters();
int maxZoom = parameters.getMaxZoom();
Log.i(TAG, "changZoom: " + maxZoom);
float setZoom = ((float) maxZoom / maxValue) * currentValue;
parameters.setZoom((int) setZoom);
mCamera.setParameters(parameters);
/**
* @param path 保存的路径
* @param name 录像视频名称(包含后缀)
*/
public void startRecord(String path, String name)
if (mCamera == null)
return;
//解锁摄像头并将其分配给MediaRecorder
mCamera.unlock();
mediaRecorder = new MediaRecorder();
mediaRecorder.setCamera(mCamera);
//指定用于录制的输入源
mediaRecorder.setAudiosource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
//设置配置文件,或者定义输出格式,音频视频编码器,帧速以及输出尺寸
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
// 设置录制的视频编码h263 h264
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
// 设置录制的视频帧率。必须放在设置编码和格式的后面,否则报错
mediaRecorder.setVideoEncodingBitRate(700 * 1024);
// 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错
mediaRecorder.setVideoSize(width, height);
// mediaRecorder.setVideoFrameRate(24); //容易报错 还有上面的setVideoSize 都是需要底层支持
基于OpenCV和C++原生(JNI)的Android数字图像处理+人脸识别demo
android Camera 如何判断当前使用的摄像头是前置还是后置