人脸识别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;
private Camera mCamera;
private int CAMERA_WIDHT = 640;
private int CAMERA_HEIGHT = 480;
private boolean detectFace = false;
private MediaRecorder mediaRecorder;
private int height = 480, width = 640;
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) {
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();
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();
}
}
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);
}
}
public void startRecord(String path, String name) {
if (mCamera == null)
return;
mCamera.unlock();
mediaRecorder = new MediaRecorder();
mediaRecorder.setCamera(mCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setVideoEncodingBitRate(700 * 1024);
mediaRecorder.setVideoSize(width, height);
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
mediaRecorder.setOutputFile(path + File.separator + name);
File file1 = new File(path + File.separator + name);
if (file1.exists()) {
file1.delete();
}
mediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());
if (cameraPosition == 1) {
mediaRecorder.setOrientationHint(180);
} else if (cameraPosition == 0) {
mediaRecorder.setOrientationHint(0);
}
try {
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public void stopRecord() {
mediaRecorder.release();
mCamera.release();
mediaRecorder = null;
SystemClock.sleep(200);
if (mCamera != null) {
mCamera = Camera.open();
mediaRecorder = new MediaRecorder();
doChange(mSurfaceView.getHolder());
}
}
public void takePicture(String photoPath, String photoName, TakePictureSuccess mTakePictureSuccess) {
File file = new File(photoPath);
if (!file.exists()) {
file.mkdir();
}
Camera.ShutterCallback shutter = new Camera.ShutterCallback() {
@Override
public void onShutter() {
}
};
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.set("jpeg-quality", 90);
mCamera.setParameters(parameters);
mCamera.takePicture(shutter, null, new PictureCallBack(photoPath, photoName, mTakePictureSuccess));
}
private class PictureCallBack implements Camera.PictureCallback {
private String path;
private String name;
private TakePictureSuccess mTakePictureSuccess;
public PictureCallBack(String path, String name, TakePictureSuccess mTakePictureSuccess) {
this.path = path;
this.name = name;
this.mTakePictureSuccess = mTakePictureSuccess;
}
@Override
public void onPictureTaken(byte[] bytes, Camera camera) {
File file = new File(path, name);
if (file.exists()) {
file.delete();
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
try {
fos.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Log.i(TAG, "onPictureTaken: ----" + cameraPosition);
Matrix matrix = new Matrix();
if (cameraPosition == 0) {
matrix.postRotate(90);
} else {
matrix.postRotate(270);
matrix.postTranslate(-1, 0);
}
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
mTakePictureSuccess.takePictureSuccess(bitmap);
camera.startPreview();
}
}
public interface TakePictureSuccess {
void takePictureSuccess(Bitmap bitmap);
}
private void doChange(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
public Camera.Parameters setParameters(Camera camera, int cameraPosition) {
Camera.Parameters parameters = null;
if (camera != null) {
parameters = camera.getParameters();
Log.i(TAG, "setParameters: ----" + parameters.getMaxNumDetectedFaces());
if (cameraPosition == 0) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
parameters.setPreviewFrameRate(25);
}
parameters.setPictureFormat(ImageFormat.NV21);
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
Log.i(TAG, "setParameters:----111----- " + CAMERA_WIDHT);
Log.i(TAG, "setParameters:----支持预览----- " + sizeList.size());
CAMERA_WIDHT = 640;
CAMERA_HEIGHT = 480;
parameters.setPictureSize(CAMERA_WIDHT, CAMERA_HEIGHT);
parameters.setPreviewSize(CAMERA_WIDHT, CAMERA_HEIGHT);
List<String> supportedFocusModes = parameters.getSupportedFocusModes();
if (supportedFocusModes != null && supportedFocusModes.size() > 0) {
if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
} else if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
}
}
return parameters;
}
public void getVideoSize() {
if (mCamera == null)
return;
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> videoSize = parameters.getSupportedVideoSizes();
for (int i = 0; i < videoSize.size(); i++) {
int width1 = videoSize.get(i).width;
int height1 = videoSize.get(i).height;
if (width1 >= 300 && width1 <= 600) {
if (height1 >= 200 && height1 <= 600) {
width = width1;
height = height1;
}
}
Log.d(TAG, "width " + width + "---height" + height);
}
List<Camera.Size> photoSize = parameters.getSupportedPictureSizes();
for (int i = 0; i < photoSize.size(); i++) {
int width1 = photoSize.get(i).width;
int height1 = photoSize.get(i).height;
if (width1 >= 1000 && width1 <= 2000) {
if (height1 >= 600 && height1 <= 2000) {
widthPhoto = width1;
heightPhoto = height1;
}
}
}
Log.i(TAG, "getVideoSize: " + widthPhoto + "----" + heightPhoto);
}
public interface CurrentCameraPositionInterface {
void cameraPosition(int cameraPosition);
}
public void setCurrentDetectFaceInterface(CurrentDetectFaceInterface currentDetectFaceInterface) {
mCurrentDetectFaceInterface = currentDetectFaceInterface;
}
private CurrentDetectFaceInterface mCurrentDetectFaceInterface;
public interface CurrentDetectFaceInterface {
void detectFace(Bitmap bitmap);
void detectFace2(Bitmap bitmap);
}
public void setCameraErrorCallback(CameraErrorCallback cameraErrorCallback) {
this.cameraErrorCallback = cameraErrorCallback;
}
}
发现人脸的方法
public Bitmap getCutBitmap(Bitmap bitmap) {
Bitmap cutBitmap = null;
Bitmap bitmapDetect = bitmap.copy(Bitmap.Config.RGB_565, true);
Log.i(TAG, "getCutBitmap:---宽度-- "+bitmapDetect.getWidth());
Log.i(TAG, "getCutBitmap:---高度-- "+bitmapDetect.getHeight());
FaceDetector faceDetector = new FaceDetector(bitmapDetect.getWidth(), bitmapDetect.getHeight(), 1);
int face = faceDetector.findFaces(bitmapDetect, faces);
Log.i(TAG, "getCutBitmap:--------- "+face);
if (face > 0) {
FaceDetector.Face face1 = faces[0];
float confidence = face1.confidence();
Log.i(TAG, "------人脸可信度---- "+confidence);
float eyesDistance = face1.eyesDistance();
Log.i(TAG, "------人脸双眼的间距---- "+eyesDistance);
float angle = face1.pose(FaceDetector.Face.EULER_X);
if (confidence < 0.5 || eyesDistance<0.3){
return null;
}
cutBitmap = bitmap;
Log.i(TAG, "getCutBitmap: ");
}
bitmapDetect.recycle();
return cutBitmap;
}
2 . Demo地址
下载地址
|