Android图片管理工具 弹窗 保活 音乐播放器 自定义View 计步器 项目框架

使用Android自带SDK进行人脸识别

2017-12-13  本文已影响0人  雷圣来

       现在市面上有很多人脸识别以及人脸对比的SDK,比如说FACE++(旷世)、阿里云、百度云、科大讯飞、云从科技等等,基本上都是通过API调用返回相应的数据,经过资料查询以及体验部分第三方的API,最后我选择了Android 自带的人脸识别的SDK,亲测有效,话不多说,代码走起。(代码传送门:http://download.csdn.net/download/u010718838/10157191),android6.0以上需要自己写一下动态请求相机的权限代码。

首先我们通过SurfaceView获取摄像头的数据。

SurfaceView preview;

preview= (SurfaceView) findViewById(R.id.preview);

// 设置缓冲类型

preview.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

// 设置surface的分辨率

preview.getHolder().setFixedSize(1920,1080);

// 设置屏幕常亮

preview.getHolder().setKeepScreenOn(true);

preview.getHolder().addCallback(new SurfaceCallback());

然后通过SurfaceCallback()回调设置相机获取图片的相应参数;

private final classSurfaceCallbackimplementsCallback {

@Override

public voidsurfaceChanged(SurfaceHolder holder, intformat, intwidth,

intheight) {

if(camera!=null) {

parameters=camera.getParameters();

parameters.setPictureFormat(PixelFormat.JPEG);

// 设置预览区域的大小

parameters.setPreviewSize(width,height);

// 设置每秒钟预览帧数  帧数越大识别速度越快,但建议范围25-60帧数,视手机自身性能而定

parameters.setPreviewFrameRate(60);

// 设置预览图片的大小

parameters.setPictureSize(width,height);

parameters.setJpegQuality(80);

}

}

@Override

public voidsurfaceCreated(SurfaceHolder holder) {

intcameraCount =0;

Camera.CameraInfo cameraInfo =newCamera.CameraInfo();

cameraCount = Camera.getNumberOfCameras();

for(inti =0;i < cameraCount;i++) {

Camera.getCameraInfo(i,cameraInfo);

if(cameraInfo.facing== Camera.CameraInfo.CAMERA_FACING_FRONT) {

try{

camera= Camera.open(i);

camera.setPreviewDisplay(holder);

setCameraDisplayOrientation(i,camera);

camera.setPreviewCallback(newMyPreviewCallback());

camera.startPreview();

}catch(Exception e) {

e.printStackTrace();

}

}

}

}

@Override

public voidsurfaceDestroyed(SurfaceHolder holder) {

if(camera!=null) {

camera.setPreviewCallback(null);

camera.stopPreview();

camera.release();

camera=null;

}

}

}

通过camera.setPreviewCallback(newMyPreviewCallback());回调的图像数据进行处理  

重点来了

private classMyPreviewCallbackimplementsPreviewCallback {

@Override

public voidonPreviewFrame(byte[] data,Camera camera) {

Camera.Size size = camera.getParameters().getPreviewSize();

YuvImage yuvImage =newYuvImage(data,ImageFormat.NV21,

size.width,size.height, null);

ByteArrayOutputStream baos =newByteArrayOutputStream();

yuvImage.compressToJpeg(newRect(0,0,size.width,size.height),

80,baos);

byte[] byteArray = baos.toByteArray();

detectionFaces(byteArray);

}

}

/**

* 检测人脸

*

*@paramdata预览的图像数据

*/

private voiddetectionFaces(byte[] data) {

BitmapFactory.Options options =newBitmapFactory.Options();

Bitmap bitmap1 = BitmapFactory.decodeByteArray(data,0,data.length,

options);

intwidth = bitmap1.getWidth();

intheight = bitmap1.getHeight();

Matrix matrix =newMatrix();

Bitmap bitmap2 =null;

FaceDetector detector =null;

switch(orientionOfCamera) {

case0:

detector =newFaceDetector(width,height,10);

matrix.postRotate(0.0f,width /2,height /2);

// 以指定的宽度和高度创建一张可变的bitmap(图片格式必须是RGB_565,不然检测不到人脸)

bitmap2 = Bitmap.createBitmap(width,height,Bitmap.Config.RGB_565);

break;

case90:

detector =newFaceDetector(height,width,1);

matrix.postRotate(-270.0f,height /2,width /2);

bitmap2 = Bitmap.createBitmap(height,width,Bitmap.Config.RGB_565);

break;

case180:

detector =newFaceDetector(width,height,1);

matrix.postRotate(-180.0f,width /2,height /2);

bitmap2 = Bitmap.createBitmap(width,height,Bitmap.Config.RGB_565);

break;

case270:

detector =newFaceDetector(height,width,1);

matrix.postRotate(-90.0f,height /2,width /2);

bitmap2 = Bitmap.createBitmap(height,width,Bitmap.Config.RGB_565);

break;

}

faces=newFaceDetector.Face[10];

Paint paint =newPaint();

paint.setDither(true);

Canvas canvas =newCanvas();

canvas.setBitmap(bitmap2);

canvas.setMatrix(matrix);

// 将bitmap1画到bitmap2上(这里的偏移参数根据实际情况可能要修改)

canvas.drawBitmap(bitmap1,0,0,paint);

faceNumber= detector.findFaces(bitmap2,faces);

Log.e("---------->","faceNumber:"+faceNumber+"faces.size:"+faces.length);

//        mTV.setText("facnumber----" + faceNumber);

mTV.setTextColor(Color.RED);

if(faceNumber!=0) {

mFindFaceView.setVisibility(View.VISIBLE);

mFindFaceView.drawRect(faces,faceNumber);

}else{

mFindFaceView.setVisibility(View.GONE);

}

bitmap2.recycle();

bitmap1.recycle();

}

/**

* 设置相机的显示方向(这里必须这么设置,不然检测不到人脸)

*

*@paramcameraId相机ID(0是后置摄像头,1是前置摄像头)

*@paramcamera相机对象

*/

private voidsetCameraDisplayOrientation(intcameraId,Camera camera) {

Camera.CameraInfo info =newCamera.CameraInfo();

Camera.getCameraInfo(cameraId,info);

introtation = getWindowManager().getDefaultDisplay().getRotation();

intdegree =0;

switch(rotation) {

caseSurface.ROTATION_0:

degree =0;

break;

caseSurface.ROTATION_90:

degree =90;

break;

caseSurface.ROTATION_180:

degree =180;

break;

caseSurface.ROTATION_270:

degree =270;

break;

}

orientionOfCamera= info.orientation;

intresult;

if(info.facing== Camera.CameraInfo.CAMERA_FACING_FRONT) {

result = (info.orientation+ degree) %360;

result = (360- result) %360;

}else{

result = (info.orientation- degree +360) %360;

}

camera.setDisplayOrientation(result);

}

如果需要对找到人脸的大致范围,可以使用自定义控件  FindFaceView

// 因为拍摄的相片跟实际显示的图像是镜像关系,所以在图片上获取的两眼中间点跟手机上显示的是相反方向

//根据人脸数据的返回的人脸中心点以及两眼之间的距离,算出大致的范围,需要根据不同的分辨进行调整,然后使用画笔画出。

canvas.drawRect((int) ((mWidth-midPoint.x) - (eyesDistance*2+eyesDistance/2)),

(int) (midPoint.y-eyesDistance)+210,

(int) ( (mWidth-midPoint.x) + (eyesDistance/3)),

(int) (midPoint.y+  (eyesDistance*2+eyesDistance/2))+210,paint);

上一篇下一篇

猜你喜欢

热点阅读