Android FaceDetector实现人脸检测,人脸追踪(框出人脸)(MVP模式)

时间:2021-11-08 16:46:49

一 主要流程:

1.通过FaceDetector类来检测人脸,返回获取到的人脸信息,以及人脸的坐标,通过人脸坐标可以做人脸追踪的操作。

2.通过两个surfaceview,一个surfaceview用来做相机的预览,另外一个surfaceview附着在相机预览surfaceview上面,用来绘制人脸的相框。

demo 链接http://download.csdn.net/download/a289973483/10108205

二 核心代码:

1.人脸检测类的使用

import android.graphics.Bitmap;
import android.media.FaceDetector;

import com.skyee.medicalrobot.common.Config;
import com.skyee.medicalrobot.recognitionface.view.CameraView;

/**
 * Created by qiandu on 2017/7/4.
 */

public class FaceCheckManager {
    private FaceDetector mFaceDetector;
    private FaceDetector.Face[] mFace = new FaceDetector.Face[Config.FACE_MAX_NUM];
    private FaceCheckManager(Bitmap bitmap){
        mFaceDetector = new FaceDetector(bitmap.getWidth(), bitmap.getHeight(), Config.FACE_MAX_NUM);
    }
    public static class Builder{
        private CameraView mCmView;
        private Bitmap mBitmap;
        public Builder setImgData(Bitmap image){
            this.mBitmap = image;
            return this;
        }
        public Builder setCmView(CameraView mCmView){
            this.mCmView = mCmView;
            return this;
        }
        public FaceCheckManager create(){
            return new FaceCheckManager(mBitmap);
        }

    }
    public void findFace(final FaceCheckCallback faceCallback,Bitmap bitmap){
        if(bitmap == null){
            faceCallback.onError("mBitmap == null");
            return;
        }
 
 
        //Bitmap.Config.RGB_565 这句很重要,可以提高检测率
 
 
 

 
 Bitmap mBitmap = bitmap.copy(Bitmap.Config.RGB_565, true); 
        final int faceResult = mFaceDetector.findFaces(mBitmap, mFace);
faceCallback.onResult(faceResult, mFace, mBitmap); bitmap.recycle(); }}
 

2.绘制人脸相框

 /**
     * 开始预览
     */
    public void takePreview() {
       // Logger.v("takePreview");
        if(mCamera != null){
            if(isPreviewing){
                mCamera.stopPreview();
                return;
            }
            parameters = mCamera.getParameters();
            parameters.setFlashMode("off"); // 无闪光灯
            parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
            parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            parameters.setPreviewFormat(ImageFormat.NV21);
            //mCamera.setDisplayOrientation(90);

            CamParaUtil.getInstance().printSupportPictureSize(parameters);
            CamParaUtil.getInstance().printSupportPreviewSize(parameters);
            Camera.Size pictureSize = CamParaUtil.getInstance().getPropPictureSize(
                    parameters.getSupportedPictureSizes(), previewRate, 800);
            parameters.setPictureSize(pictureSize.width, pictureSize.height);
            Camera.Size previewSize = CamParaUtil.getInstance().getPropPreviewSize(
                    parameters.getSupportedPreviewSizes(), previewRate
                    , 800);
	   //这里的 pictureSize 和 PreviewSize很重要,  一般平板采用上面的CamParaUtil可以获取到默认支持最低的分辨率。偶尔也会出现分辨率不正确的情况,建议采用
自己打印出来看看系统支持的分辨率,然后根据需要,选择相应的分辨率
            parameters.setPictureSize(pictureSize.width, pictureSize.height);
            parameters.setPreviewSize(previewSize.width, previewSize.height);
            mCamera.setParameters(parameters);
            //Logger.v("setPreviewCallback前" + pictureSize.width + "//" + pictureSize.height + " oo "+ previewSize.width + "//" + previewSize.height);
            mCamera.setPreviewCallback(new Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] bytes, Camera camera) {
                   // Logger.v("setPreviewCallback");
                    Camera.Size size = camera.getParameters().getPreviewSize();
                    YuvImage image = new YuvImage(bytes, ImageFormat.NV21, size.width, size.height, null);
                    if(bytes != null){
                        ByteArrayOutputStream out = new ByteArrayOutputStream();
                        image.compressToJpeg(new Rect(0, 0, size.width, size.height), 50, out);
                        byte[] datas = out.toByteArray();
                        BitmapFactory.Options options = new BitmapFactory.Options();
                        options.inPreferredConfig = Bitmap.Config.RGB_565;
                        Bitmap mBitmap = BitmapFactory.decodeByteArray(datas, 0, datas.length, options);
                        long l = System.nanoTime();
                        //FileUtil.saveBitmap("cccc/"+l+"ee.png", mBitmap);
                        Matrix matrix = new Matrix();
                        //matrix.postRotate((float)90);
                        matrix.postScale(0.4f, 0.3125f); //照片的大小使 1280*960 屏幕的大小使 1024*600 这里需要注意换算比例
                       // Logger.v("MyCameraManager faceCheckFlag");
                        //synchronized (this) {
                            //Logger.v("MyCameraManager synchronized");
                            //if(faceCheckFlag){
                                //setFaceCheckFlag(false);
                                //Logger.v("MyCameraManager synchronized" + errornum + mBitmap.getWidth() + "dd " + mBitmap.getHeight());
                                Bitmap bitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);
                                FaceCheckManager faceCheckManager = new FaceCheckManager.Builder().setCmView(mCameraView).setImgData(bitmap).create();
                                faceCheckManager.findFace(MyCameraManager.this, bitmap);
                            //}
                       // }
                        mBitmap.recycle();
                    }
                }
            });
           // Logger.v("setPreviewCallback后");
            mCamera.startPreview();
            isPreviewing = true;
        }
    }
@Override
    public void onResult(int faceNum, final FaceDetector.Face[] faceData, final Bitmap bitmap) {
            //Logger.v("MyCameraManager 发现了几个脸" +faceNum);
            if(faceNum <= 0){
                errornum ++;
                if(errornum>2){
                    clear();
                    errornum = 0;
                }
                setFaceCheckFlag(true);
                return;
            }
            if(befmSurfaceHolder != null ){//&& threadNum < 6)
                //锁定整个SurfaceView
                   /* new Thread(){
                        @Override
                        public void run() {
                            super.run();*/
                           // threadNum ++;
                            Canvas mCanvas = befmSurfaceHolder.lockCanvas();
                            mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                            for(FaceDetector.Face face : faceData){
                                if (face == null) {
                                    break;
                                }
                                errornum = 0;
                                //mCanvas.drawBitmap(MainApplication.mRotaBitmap, 0, 0 ,paint);
                                PointF pointF = new PointF();
                                face.getMidPoint(pointF);
                                float eyesDistance = face.eyesDistance();

                                //Logger.v("onResult"+ pointF.x + "_" + pointF.y);
                                mCanvas.drawRect(new Rect((int)(pointF.x - eyesDistance)*2,
                                                (int)(pointF.y- eyesDistance)*2,
                                                (int)(pointF.x + eyesDistance)*2,
                                                (int)(pointF.y + eyesDistance)*2),paint);//绘制矩形
                            }
                            befmSurfaceHolder.unlockCanvasAndPost(mCanvas);
                           // threadNum --;
                            //mCameraView.onDetectFace(bitmap);
                        }

                    //}.start();

        //}
}
 </pre