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

       现在市面上有很多人脸识别以及人脸对比的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);

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容