一 主要流程:
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