这可能是全网唯一一篇介绍Android Camera2接口集成人脸算法的文章了~
写在前面:
说起人脸识别,相信大家都不会感到陌生,在我们平时的工作生活中,人脸打卡、刷脸支付等等已经是应用的非常广泛了,人脸识别也给我们的生活带来了极大的便利。
这篇文章的目的是让大家了解熟悉Android平台上人脸算法集成的基本流程(针对应用层的集成)。相信读完这篇文章后,大家会觉的,原来集成人脸识别算法也是so easy。

这篇文章将针对下面几点展开介绍:
一、Android平台人脸识别流程图
二、ArcSoft人脸识别算法sdk下载
三、Camera2 API 集成 ArcSoft人脸识别算法
一、Android平台人脸识别流程图
人脸识别流程图基本如下图所示。
用一句话来说就是获取camera数据,送到算法中进行识别,最后显示识别结果。

二、ArcSoft人脸识别算法sdk下载
人脸识别算法很多,如果是高通平台,高通也是有一套人脸识别算法的。我这里选择的是arcsoft的识别算法,这个目前是免费的,而且相对来说算法效果也还不错。
接下来我们看下如何去获取arcsoft的人脸识别sdk。
1)登录arcsoft官网,然后选择进入开发者中心。
(https://ai.arcsoft.com.cn/)

2)注册并登录开发者中心后,在开发者中心界面,我们选择“新建应用”,然后勾选人脸识别功能。
如下图所示,我创建的应用是“CameraDemo”。这个界面的APP_ID 和SDK_KEY我们后面代码里面需要用到。这个界面还有个“下载SDK”的按钮,点击就可以下载我们需要的sdk demo。

3)Demo下载下来后,我们先跑下arcsoft官方Demo看下效果。

我们选择人脸检测属性(视频)。如下图所示,效果还不错,我们可以看到识别出来的信息里面包含了性别、年龄、是否是真人这些基本信息。

三、Camera2 API 集成 ArcSoft人脸识别算法
通过上面的2步,大家有没觉的集成人脸识别还是蛮简单的。介绍完了官方的demo,那接下来我们看下采用Android Camera2 的api,如何去集成arcsoft的人脸识别算法呢。
1、如下面代码块所示,arcsoft 官方demo采用的是Camera1的api接口,设置的预览数据的回调,回调的直接就是nv21的byte[]数据,然后再把byte[]数据送进去算法处理。
private void initCamera() {DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);CameraListener cameraListener = new CameraListener() {@Overridepublic void onCameraOpened(Camera camera, int cameraId, int displayOrientation, boolean isMirror) {previewSize = camera.getParameters().getPreviewSize();drawHelper = new DrawHelper(previewSize.width, previewSize.height, previewView.getWidth(), previewView.getHeight(), displayOrientation, cameraId, isMirror, false, false);}@Overridepublic void onPreview(byte[] nv21, Camera camera) {if (faceRectView != null) {faceRectView.clearFaceInfo();}List faceInfoList = new ArrayList<>();int code = faceEngine.detectFaces(nv21, previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, faceInfoList);if (code == ErrorInfo.MOK && faceInfoList.size() > 0) {code = faceEngine.process(nv21, previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, faceInfoList, processMask);if (code != ErrorInfo.MOK) {return;}} else {return;}List ageInfoList = new ArrayList<>();List genderInfoList = new ArrayList<>();List face3DAngleList = new ArrayList<>();List faceLivenessInfoList = new ArrayList<>();int ageCode = faceEngine.getAge(ageInfoList);int genderCode = faceEngine.getGender(genderInfoList);int face3DAngleCode = faceEngine.getFace3DAngle(face3DAngleList);int livenessCode = faceEngine.getLiveness(faceLivenessInfoList);// 有其中一个的错误码不为ErrorInfo.MOK,returnif ((ageCode | genderCode | face3DAngleCode | livenessCode) != ErrorInfo.MOK) {return;}if (faceRectView != null && drawHelper != null) {List drawInfoList = new ArrayList<>();for (int i = 0; i < faceInfoList.size(); i++) {Log.v(TAG,"---faceInfoList.get(i).getRect():"+faceInfoList.get(i).getRect());drawInfoList.add(new DrawInfo(drawHelper.adjustRect(faceInfoList.get(i).getRect()), genderInfoList.get(i).getGender(), ageInfoList.get(i).getAge(), faceLivenessInfoList.get(i).getLiveness(), RecognizeColor.COLOR_UNKNOWN, null));}drawHelper.draw(faceRectView, drawInfoList);}}}
2、接下来我们要介绍的是使用Camera2接口,如何集成arcsoft的人脸识别算法。
我自己创建了个应用工程,demo源码地址也在文末会给出。我们先来看下我自己写的demo效果图:

下面来讲解下代码实现的主要步骤:
(不熟悉Camera2接口的同学,建议先找一篇关于Camera2 API的文章先了解下,关于Camera2,我自己前面也写过算是比较详细的文章介绍,也欢迎大家阅读)
i、初始化imageReader。
mImageReader = ImageReader.newInstance(mPreviewSize.getWidth(),mPreviewSize.getHeight(),ImageFormat.YUV_420_888, 2);mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
ii、创建session的时候,把imagerReader的surface也add进去。
这样我们就能拿到实时的视频流。
mPreviewRequestBuilder.addTarget(mImageReader.getSurface());mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),new CameraCaptureSession.StateCallback() {}
iii、在imageReader的实时流回调里面,我们需要把接收到的YUV_420_888的数据先转换成nv21格式,然后再送进arcsoft的人脸检测算法中进行处理
Camera1 接口上,设置预览数据回调后,回调的直接就是nv21格式的数据,相对来说会比Camera2上的处理会简单很多。
不过Android 目前已经不再对Camera旧的架构进行维护,而且目前主流的手机采用的基本上也都是Camera2的接口。所以我们还是非常有必要熟悉掌握Camera2的各种使用。
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener= new ImageReader.OnImageAvailableListener() {@Overridepublic void onImageAvailable(ImageReader reader) {Image image = reader.acquireLatestImage();if(image == null){return;}synchronized (mImageReaderLock) {if(!mImageReaderLock.equals(1)){Log.v(TAG, "--- image not available,just return!!!");image.close();return;}if (ImageFormat.YUV_420_888 == image.getFormat()) {Image.Plane[] planes = image.getPlanes();lock.lock();if (y == null) {y = new byte[planes[0].getBuffer().limit() - planes[0].getBuffer().position()];u = new byte[planes[1].getBuffer().limit() - planes[1].getBuffer().position()];v = new byte[planes[2].getBuffer().limit() - planes[2].getBuffer().position()];}if (image.getPlanes()[0].getBuffer().remaining() == y.length) {planes[0].getBuffer().get(y);planes[1].getBuffer().get(u);planes[2].getBuffer().get(v);if (nv21 == null) {nv21 = new byte[planes[0].getRowStride() * mPreviewSize.getHeight() * 3 / 2];}if(nv21 != null && (nv21.length != planes[0].getRowStride() * mPreviewSize.getHeight() *3/2)){return;}// 回传数据是YUV422if (y.length / u.length == 2) {ImageUtil.yuv422ToYuv420sp(y, u, v, nv21, planes[0].getRowStride(), mPreviewSize.getHeight());}// 回传数据是YUV420else if (y.length / u.length == 4) {ImageUtil.yuv420ToYuv420sp(y, u, v, nv21, planes[0].getRowStride(), mPreviewSize.getHeight());}//调用Arcsoft算法,绘制人脸信息drawFaceInfo(nv21);}lock.unlock();}}image.close();}};
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/21270,转载请注明出处。


评论0