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

@Override
public 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,return
if ((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效果图:

image.png

下面来讲解下代码实现的主要步骤: (不熟悉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 代码地址: pan.baidu.com/s/1z44mAtkJ…
这篇文件介绍的,是针对应用层上的人脸算法集成。现在很多手机厂商,人脸算法有一部分是在hal层完成的。比如美颜算法这些,直接就是在hal层完成的了,这样处理效率会更高。针对hal层的算法集成,感兴趣同学的欢迎留言,后面的文章我会进行更新介绍。


*本人从事Android Camera相关开发已有5年,
*目前在深圳上班,
*欢迎关注我的微信公众号: 小驰笔记
*希望和更多的小伙伴一起交流学习~
-------- 2021.04.17 深圳 16:21

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

文末

面试:如果不准备充分的面试,完全是浪费时间,更是对自己的不负责!

不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值