前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >全网首发:Android Camera2 集成人脸识别算法

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

作者头像
小驰随想录
发布2021-04-30 14:43:35
1.1K0
发布2021-04-30 14:43:35
举报
文章被收录于专栏:Android Camera开发Android Camera开发

这可能是全网唯一一篇介绍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[]数据送进去算法处理。

代码语言:javascript
复制
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。

代码语言:javascript
复制
 mImageReader = ImageReader.newInstance(mPreviewSize.getWidth(), 
              mPreviewSize.getHeight(),ImageFormat.YUV_420_888, 2);
 mImageReader.setOnImageAvailableListener(
                        mOnImageAvailableListener, mBackgroundHandler);

ii、创建session的时候,把imagerReader的surface也add进去。

这样我们就能拿到实时的视频流。

代码语言:javascript
复制
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的各种使用。

代码语言:javascript
复制
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层的算法集成,感兴趣同学的欢迎留言,后面的文章我会进行更新介绍。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小驰成长圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面:
  • 一、Android平台人脸识别流程图
  • 二、ArcSoft人脸识别算法sdk下载
  • 三、Camera2 API 集成 ArcSoft人脸识别算法
相关产品与服务
人脸识别
腾讯云神图·人脸识别(Face Recognition)基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、比对、搜索、验证、五官定位、活体检测等多种功能,为开发者和企业提供高性能高可用的人脸识别服务。 可应用于在线娱乐、在线身份认证等多种应用场景,充分满足各行业客户的人脸属性识别及用户身份确认等需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档