android 拍摄预览过程中人脸识别

来源:互联网 发布:网上挂号软件 编辑:程序博客网 时间:2024/06/04 05:13

仔细想想距离写上篇文章已经很久了,最近都忙于工作和睡觉打游戏(朋友的名字叫游溪),以至于没有写接下来的东西。。记得上篇文章写的是关于自定义camera的(http://blog.csdn.net/lzan13/article/details/54017224)。。那么该篇将在原有的基础上加上人脸识别的功能。

已经亲测,可以实现!!!

三个类,很简单,其他难得我也不会搞:

  主要通过:FaceDetectionListener 实现

废话不多说直接上代码:

AutioTakeActiity  该页面只有一个跳转按钮,和一个用来显示拍摄照片的imageview

package com.example.auto_take_picture;import android.Manifest;import android.app.Activity;import android.content.Intent;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.view.View;import android.widget.ImageView;import android.widget.Toast;/** * Created by Administrator on 2017/5/5 0005. */public class AutioTakeActiity extends Activity {    private static final int REQUEST_CAMERA_CODE_TEACHER = 1;// 拍照    private ImageView ima;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_takephoto_result);        ima=(ImageView)findViewById(R.id.ima);    }    /**     * 点击拍照     * @param view     */    public void takePhoto(View view){        getPerssiom();    }    /**     * android6.0 申请拍照权限     */    private void getPerssiom(){        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED                && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED                && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {            gotoTake();        } else {            ActivityCompat.requestPermissions(this, new String[]{                    Manifest.permission.WRITE_EXTERNAL_STORAGE,                    Manifest.permission.CAMERA,                    Manifest.permission.READ_EXTERNAL_STORAGE            }, REQUEST_CAMERA_CODE_TEACHER);        }    }    /**     * 跳转至自定义的拍照页面     */    private void gotoTake(){        Intent intent =new Intent(this,AutioTakePhotoActivity.class);        startActivityForResult(intent ,1);    }    /**     * 拍照完成之后拿到路径设置imageview     * @param requestCode     * @param resultCode     * @param data     */    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if(resultCode==RESULT_OK){            if(requestCode==1){               boolean isBack= data.getBooleanExtra("isBack",true);                String path  =  data.getStringExtra("picPath");                Bitmap bitmap = BitmapFactory.decodeFile(path);                Matrix matrix=new Matrix();                if(isBack){//由于拍照时旋转了90度。这里通矩阵旋转回来。(后置摄像头)                    matrix.setRotate(90);                }else{                    matrix.setRotate(-90);             // ( 前置摄像头)                }                Bitmap bit=  bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);                ima.setImageBitmap(bit);            }        }    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        switch (requestCode) {            case REQUEST_CAMERA_CODE_TEACHER:                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED                        && grantResults.length > 1 && grantResults[1] == PackageManager.PERMISSION_GRANTED                        && grantResults.length > 2 && grantResults[2] == PackageManager.PERMISSION_GRANTED) {                    gotoTake();                } else {                    Toast.makeText(this, "获取权限失败", Toast.LENGTH_SHORT).show();                }                break;            default:                break;        }    }}
//上面类对应的布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <TextView        android:id="@+id/take"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="去拍照"        android:padding="15dp"        android:onClick="takePhoto"        android:layout_gravity="center"        />    <ImageView        android:id="@+id/ima"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center"        android:src="@drawable/show"        /></LinearLayout>

// 该类完成拍摄和展示,以及人脸识别的功能
package com.example.auto_take_picture;import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.hardware.Camera;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.WindowManager;import android.widget.ImageView;import android.widget.RelativeLayout;import android.widget.TextView;import android.widget.Toast;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.util.List;/** * Created by Administrator on 2017/5/5 0005. */public class AutioTakePhotoActivity extends Activity implements  SurfaceHolder.Callback{    private SurfaceHolder holder;    private SurfaceView surfaceView;    Camera mCamera;    byte[] photoBytes;    private ImageView image;    private RelativeLayout rela_result;    public static int cameraId;    private boolean isBack=true;    private FaceView faceView;    private TextView txt_turn;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_take_photo);        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//保持屏幕常亮        rela_result=(RelativeLayout)findViewById(R.id.result) ;  //在预览界面之上覆盖一层页面,显示拍摄的图片        image=(ImageView)findViewById(R.id.image);               //显示拍摄的图片        surfaceView=(SurfaceView)findViewById(R.id.surfaceview);        holder= surfaceView.getHolder();        faceView=(FaceView)findViewById(R.id.face_view);        //自定义的view 。用来绘制检测人脸的方框;        cameraId=findBackCamera();                              //摄像头的id,区分前置还是后置摄像头        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        txt_turn=(TextView)findViewById(R.id.turn);        txt_turn.setText("前置/后置------当前:后置");        holder.addCallback(this);    }    public void take(View view){          //点击拍照的方法。        Camera.Parameters parameters =mCamera.getParameters();        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);        mCamera.autoFocus(new Camera.AutoFocusCallback() {            @Override            public void onAutoFocus(boolean b, Camera camera) {                if(b){        //如果焦点获取成功,拍照                    mCamera.takePicture(null,null,pictureCallBack);  //pictureCallBack 为拍照的回掉。                }            }        });    }    /**     * 摄像头的切换     * @param view     */    public void turn(View view){            if(isBack){                cameraId=findFrontCamera();  //前置摄像头id                txt_turn.setText("前置/后置------当前:前置");            }else{                cameraId=findBackCamera();  //后置                txt_turn.setText("前置/后置------当前:后置");            }        isBack=!isBack;        if (mCamera != null) {            mCamera.stopPreview();            mCamera.release(); // 释放照相机        }        mCamera = Camera.open(cameraId);        setCameraParams(1080,1920);//随便设的值        try {            mCamera.setPreviewDisplay(holder);            mCamera.setDisplayOrientation(90);            mCamera.startPreview();            mainHandler.sendEmptyMessage(1);        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * 点击完成保存图片,并将路径回传给上个页面     * @param view     */    public void finish(View view){          //完成        File file=new File(Environment.getExternalStorageDirectory().getPath() + "/test2.jpg");        if (file.exists()) {            file.delete();        }        try {            FileOutputStream fo=new FileOutputStream(file);            fo.write(photoBytes);            fo.close();            Toast.makeText(AutioTakePhotoActivity.this,"已保存图片", Toast.LENGTH_SHORT).show();            Intent intent =new Intent(AutioTakePhotoActivity.this,AutioTakeActiity.class);                         //完成拍照,回到mainActivity,并将图片的路径回传            intent.putExtra("picPath", Environment.getExternalStorageDirectory().getPath() + "/test2.jpg");            intent.putExtra("isBack",isBack);            setResult(RESULT_OK,intent);            finish();        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * 取消,放弃该图片     * @param view     */    public void cancle(View view){          //取消        photoBytes=null;        rela_result.setVisibility(View.GONE);        mCamera.startPreview();    }    /**     * 显示拍出的图片     */    private  void show(byte[] photoBytes){        Bitmap bitmap = BitmapFactory.decodeByteArray(photoBytes, 0, photoBytes.length);        Matrix matrix=new Matrix();        if(isBack){  //后置摄像头            matrix.setRotate(90);        }else{            matrix.setRotate(-90); //前置摄像头        }        Bitmap bit=  bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);        if(bitmap!=null&&!bitmap.isRecycled()){            bitmap.recycle();        }        if(bit!=null){            image.setImageBitmap(bit);        }        rela_result.setVisibility(View.VISIBLE);    }    private Camera.PictureCallback  pictureCallBack =new Camera.PictureCallback() {        @Override        public void onPictureTaken(byte[] bytes, Camera camera) {     //bytes 即是拍照回来的内容,将内容写入本地即可            photoBytes=bytes;            show(photoBytes);        }    };    /**     * 拿到前置摄像头id     */    public static int findFrontCamera() {        int cameraId = -1;        int numberCameras = Camera.getNumberOfCameras();        for (int i = 0; i < numberCameras; i++) {            Camera.CameraInfo info = new Camera.CameraInfo();            Camera.getCameraInfo(i, info);            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {                cameraId = i;                break;            }        }        return cameraId;    }    /**     * 拿到后置摄像头id     */    public static int findBackCamera() {        int cameraId = -1;        int numberCameras = Camera.getNumberOfCameras();        for (int i = 0; i < numberCameras; i++) {            Camera.CameraInfo info = new Camera.CameraInfo();            Camera.getCameraInfo(i, info);            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {                cameraId = i;                break;            }        }        return cameraId;    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        Log.e("zjun","surfaceCreated");        try {            if(mCamera==null){                mCamera= Camera.open(cameraId);                mCamera.setPreviewDisplay(holder);               setCameraParams(1080,1920);            }        } catch (IOException e) {            e.printStackTrace();        }    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        Log.e("zjun","surfaceChanged");        mCamera.startPreview();        mainHandler.sendEmptyMessage(1);    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        if (mCamera != null) {            mCamera.release(); // 释放照相机            mCamera = null;        }    }    /**     * 设置参数     * @param width     * @param height     */    private void setCameraParams(int width, int height) {        Camera.Parameters parameters = mCamera.getParameters();        // 获取摄像头支持的PictureSize列表        List<Camera.Size> pictureSizeList = parameters.getSupportedPictureSizes();        /**从列表中选取合适的分辨率*/        Camera.Size picSize = getProperSize(pictureSizeList, ((float) height / width));        if (null == picSize) {            picSize = parameters.getPictureSize();        }        // 根据选出的PictureSize重新设置SurfaceView大小        parameters.setPictureSize(picSize.width,picSize.height);        // 获取摄像头支持的PreviewSize列表        List<Camera.Size> previewSizeList = parameters.getSupportedPreviewSizes();        Camera.Size preSize = getProperSize(previewSizeList, ((float) height) / width);        if (null != preSize) {            Log.e("zjun", "preSize.width=" + preSize.width + "  preSize.height=" + preSize.height);            parameters.setPreviewSize(preSize.width, preSize.height);        }        parameters.setJpegQuality(100); // 设置照片质量        if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 连续对焦模式        }        mCamera.cancelAutoFocus();//自动对焦。        mCamera.setDisplayOrientation(90);// 设置PreviewDisplay的方向,效果就是将捕获的画面旋转多少度显示        mCamera.setParameters(parameters);    }    private MainHandler mainHandler = new MainHandler();    private void startGoogleDetect() {        Camera.Parameters parameters =mCamera.getParameters();        if (parameters.getMaxNumDetectedFaces() > 0) {            if (faceView != null) {                faceView.clearFaces();                faceView.setVisibility(View.VISIBLE);            }            mCamera.setFaceDetectionListener(new GoogleDetectListenerImpl(AutioTakePhotoActivity.this, mainHandler));            mCamera.startFaceDetection();        }    }    private class MainHandler extends Handler {        @Override        public void handleMessage(final Message msg) {            int what = msg.what;            switch (what) {                case 1:                    startGoogleDetect();                    Log.e("renlei110", "开启人脸识别");                    break;                case 2:                    runOnUiThread(new Runnable() {                        @Override                        public void run() {                            Camera.Face[] faces = (Camera.Face[]) msg.obj;                            faceView.setFaces(faces);                            Log.e("renlei111", "收到人脸识别的信息");                        }                    });                    break;            }            super.handleMessage(msg);        }    }    /**     * 从列表中选取合适的分辨率     * 默认w:h = 4:3     * <p>注意:这里的w对应屏幕的height     *            h对应屏幕的width<p/>     */    private Camera.Size getProperSize(List<Camera.Size> pictureSizeList, float screenRatio) {        Log.i("zjun", "screenRatio=" + screenRatio);        Camera.Size result = null;        for (Camera.Size size : pictureSizeList) {            float currentRatio = ((float) size.width) / size.height;            if (currentRatio - screenRatio == 0) {                result = size;                break;            }        }        if (null == result) {            for (Camera.Size size : pictureSizeList) {                float curRatio = ((float) size.width) / size.height;                if (curRatio == 4f / 3) {// 默认w:h = 4:3                    result = size;                    break;                }            }        }        return result;    }}
//上面类对应布局
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <SurfaceView    android:id="@+id/surfaceview"    android:layout_width="match_parent"    android:visibility="visible"    android:layout_height="match_parent" />    <TextView    android:id="@+id/take"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:padding="15dp"    android:onClick="take"    android:text="拍照"    android:background="@android:color/holo_green_light"    android:layout_centerHorizontal="true"    android:layout_alignParentBottom="true"/>    <TextView        android:id="@+id/turn"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:padding="15dp"        android:onClick="turn"        android:text="前置/后置"        android:background="@android:color/holo_green_light"        android:layout_centerHorizontal="true"/>    <com.example.auto_take_picture.FaceView        android:id="@+id/face_view"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:visibility="gone"        ></com.example.auto_take_picture.FaceView>    <RelativeLayout        android:id="@+id/result"        android:layout_width="match_parent"        android:background="#222"        android:visibility="gone"        android:layout_height="match_parent">        <ImageView            android:id="@+id/image"            android:layout_width="match_parent"            android:layout_alignParentTop="true"            android:layout_height="match_parent" />        <TextView            android:id="@+id/finish"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="15dp"            android:onClick="finish"            android:text="完成"            android:background="@android:color/holo_green_light"            android:layout_alignParentBottom="true"/>        <TextView            android:id="@+id/cancle"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="15dp"            android:onClick="cancle"            android:text="取消"            android:layout_alignParentRight="true"            android:background="@android:color/holo_green_light"            android:layout_alignParentBottom="true"/>    </RelativeLayout></RelativeLayout>
//FaceView 类用来绘制人脸识别的方框
package com.example.auto_take_picture;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.drawable.Drawable;import android.hardware.Camera;import android.util.AttributeSet;import android.util.Log;import android.widget.ImageView;/** * Created by Administrator on 2017/5/9 0009. */public class FaceView extends ImageView {    private Context mContext;    private Camera.Face[] mFaces;    private Matrix mMatrix = new Matrix();    private boolean mirror;    private Paint mLinePaint;    public FaceView(Context context, AttributeSet attrs) {        super(context, attrs);        initPaint();        this.mContext = context;    }    public void setFaces(Camera.Face[] faces) {        this.mFaces = faces;        invalidate();    }    public void clearFaces(){        mFaces = null;        invalidate();    }    @Override    protected void onDraw(Canvas canvas) {        if(mFaces == null || mFaces.length < 1){            return;        }        if (mFaces != null&&mFaces.length>=1) {            canvas.translate(getWidth()/2,getHeight()/2);            canvas.rotate(-0);            mirror=(AutioTakePhotoActivity.cameraId== Camera.CameraInfo.CAMERA_FACING_FRONT) ;            Log.e("mFaces","mFaces"+mFaces.length);            for (int i = 0; i < mFaces.length; i++) {                Camera.Face face= mFaces[i];                int width=face.rect.right-face.rect.left;                int  needWidth=getWidth()*width/2000;                if(!mirror){                    int cx = -face.rect.centerY(); //因为之前对camera做了旋转,所以这里需要转换一下坐   //后置摄像头                    int cy = face.rect.centerX();                    RectF rectF = new RectF(getWidth()*cx/2000f-needWidth/2,getHeight()*cy/2000f-needWidth/2,getWidth()*cx/2000f+needWidth/2,getHeight()*cy/2000f+needWidth/2);                    canvas.drawRect(rectF,mLinePaint);                }else{                    int cx = -face.rect.centerY(); //因为之前对camera做了旋转,所以这里需要转换一下坐  //前置摄像头                    int cy = -face.rect.centerX();                    RectF rectF = new RectF(getWidth()*cx/2000f-needWidth/2,getHeight()*cy/2000f-needWidth/2,getWidth()*cx/2000f+needWidth/2,getHeight()*cy/2000f+needWidth/2);                    canvas.drawRect(rectF,mLinePaint);                }            }        }        super.onDraw(canvas);    }    /**     * <p>Here is the matrix to convert driver coordinates to View coordinates     * in pixels.</p>     * <pre>     * Matrix matrix = new Matrix();     * CameraInfo info = CameraHolder.instance().getCameraInfo()[cameraId];     * // Need mirror for front camera.     * boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);     * matrix.setScale(mirror ? -1 : 1, 1);     * // This is the value for android.hardware.Camera.setDisplayOrientation.     * matrix.postRotate(displayOrientation);     * // Camera driver coordinates range from (-1000, -1000) to (1000, 1000).     * // UI coordinates range from (0, 0) to (width, height).     * matrix.postScale(view.getWidth() / 2000f, view.getHeight() / 2000f);     * matrix.postTranslate(view.getWidth() / 2f, view.getHeight() / 2f);     * </pre>     */    private void prepareMatrix() {        mMatrix.setScale(mirror ? -1 : 1, 1);        mMatrix.postRotate(9);        mMatrix.postScale(getWidth() / 2000f, getHeight() / 2000f);        mMatrix.postTranslate(getWidth() / 2f, getHeight() / 2f);    }    private void initPaint() {        mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);//      int color = Color.rgb(0, 150, 255);        int color = Color.rgb(98, 212, 68);//      mLinePaint.setColor(Color.RED);        mLinePaint.setColor(color);        mLinePaint.setStyle(Paint.Style.STROKE);        mLinePaint.setStrokeWidth(5f);        mLinePaint.setAlpha(180);    }}

《完。。》很简单的三个类,不怎么写文章,也不知道怎么说,如果发现有坑,恭候怼我。

0 0
原创粉丝点击