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 如何判断当前使用的摄像头是前置还是后置

android Camera如何判断当前使用的摄像头是前置还是后置

python三步实现人脸识别

用 20 行 python 代码实现人脸识别!

使用 Android Camera2 API 进行人脸检测和画圆