写点什么

全网首发:Android Camera2 集成人脸识别算法

用户头像
小驰嘻嘻
关注
发布于: 2021 年 04 月 11 日
全网首发:Android Camera2 集成人脸识别算法

这可能是全网唯一一篇介绍 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() { @Override public 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); }

@Override public void onPreview(byte[] nv21, Camera camera) {
if (faceRectView != null) { faceRectView.clearFaceInfo(); } List<FaceInfo> 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<AgeInfo> ageInfoList = new ArrayList<>(); List<GenderInfo> genderInfoList = new ArrayList<>(); List<Face3DAngle> face3DAngleList = new ArrayList<>(); List<LivenessInfo> 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,return if ((ageCode | genderCode | face3DAngleCode | livenessCode) != ErrorInfo.MOK) { return; } if (faceRectView != null && drawHelper != null) { List<DrawInfo> 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() {
@Override public 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; }
// 回传数据是YUV422 if (y.length / u.length == 2) { ImageUtil.yuv422ToYuv420sp(y, u, v, nv21, planes[0].getRowStride(), mPreviewSize.getHeight()); } // 回传数据是YUV420 else if (y.length / u.length == 4) { ImageUtil.yuv420ToYuv420sp(y, u, v, nv21, planes[0].getRowStride(), mPreviewSize.getHeight()); }
//调用Arcsoft算法,绘制人脸信息 drawFaceInfo(nv21); } lock.unlock(); } } image.close(); } };
复制代码


Demo 代码地址:

https://pan.baidu.com/s/1z44mAtkJu0lAQTdTOmsNhw


这篇文件介绍的,是针对应用层上的人脸算法集成。

现在很多手机厂商,人脸算法有一部分是在 hal 层完成的。比如美颜算法这些,直接就是在 hal 层完成的了,这样处理效率会更高。

针对 hal 层的算法集成,感兴趣同学的欢迎留言,后面的文章我会进行更新介绍。


------------------------------------------------------------

*本人从事 Android Camera 相关开发已有 5 年,

*目前在深圳上班,

*欢迎关注我的微信公众号 小驰笔记

*希望和更多的小伙伴一起交流学习~


-------- 2021.04.11 深圳 00:45


发布于: 2021 年 04 月 11 日阅读数: 63
用户头像

小驰嘻嘻

关注

公众号: 小驰笔记 2021.03.30 加入

14年开始从事Android Camera相关软件开发 做过车载、手机、执法记录仪~

评论

发布
暂无评论
全网首发:Android Camera2 集成人脸识别算法