人工智能早已不是什么新鲜的事物,人脸识别是当前比较热门的技术,在国内也越来越多的运用,例如刷脸打卡,刷脸APP,身份识别,人脸门禁等。人脸识别技术为我们的生活带来了一些便利,但是也存在很明显的缺陷,那就是活体的问题。想象一下如果人脸门禁普及到家庭中,如果一个人拿着你的照片就能进入你的房间,那门禁岂不是形同虚设,因此活体检测是一个必不可少的部分。
那么如何在Android平台上实现活体检测这一功能呢,本文将借助虹软提供的SDK进行介绍。
本文将实现视频模式与图像模式的人脸检测。
1.进入http://ai.arcsoft.com.cn/product/arcface.html网站,注册账号并登录
2.选择需要下载的SDK版本填写下载申请,并提交
点击提交后获得APPID和SDKKey,点击下载链接下载SDK压缩包,AppID与SDKKey在后面激活时会用到,所以可以先保存下来。
下载成功后我们拿到的包结构应该是如下所示,红框标出的三个库为引擎库,也就是我们后面需要用到的库。
包和key都已经到手,那么该如何使用这个包,来实现我们想要的活体检测呢?我发现在下载的包中有一个samplecode,这个示例代码虽然简单,但是也能足够实现我想要的效果了,因此在这里偷一下懒,直接使用虹软提供的示例代码来进行本次项目的说明。
打开示例代码的工程,我们可以看到目录结构如下,lib目录下存放jar包,jnilibs下存放so包,后面如果我们自己要写一个新的工程就要这样做了。
说完了库接下来说一下每个类的作用,Constants是用来写我们在官网获得的SDKKey与APPID,首先我们将官网上得到的Key 根据名称一个个的替换上去,注意一定要一一对应。
DrawUtils是用来画人脸框的工具类,ImageUtil是图像的工具类,提供了NV21转换以及YUV转换的方法,挺好用的但是和我们的主题并不相关,这里就不介绍了。接下来就是重头戏了,我们开始使用虹软的SDK,我们在第一次使用引擎之前必须需要先激活引擎,在MainActivity我们可以找到。具体的调用流程可以参照下图。
如果提示激活失败,可以根据提供的errorCode到开发文档中对比错误码定位问题,一般都是因为激活时没联网或者没有给与权限的问题导致的,也有APPID与Key填反或者填错的大马虎的存在。当点击激活按钮时,界面toast提示活体引擎激活成功,说明我们填写和调用都没问题,接下来我们就可以开始使用引擎了。
先从图片模式下的活体检测开始,首先我们要明确一个问题,既然是活体检测,那么图片怎么样检测活体呢?图片模式下的活体(以下是我个人的理解,如果有问题欢迎指正),就是指以图片为输入源,检测图片内的人是否为真人。像图片内是相片或者拍摄的屏幕等方式的,都无法通过活体检测,为了说的更清晰一些,下面给出三种情况的典型例子。
图一为活体,图二图三均为非活体,相信看到图片说明后,会更清晰一些。概念讲完了我们该知道如何使用SDK。在任何引擎使用之前,我们都要先进行初始化,由于是以图片形式进行的活体检测,我们要用到FD与Liveness两个引擎,首先要进行初始化。
活体引擎初始化需要两个参数,第一个是上下文(即context),第二个是检测的类型由于我们是用的图片模式,所以使用Image模式,如果初始化出错,可以去对照错误码表上的错误码定位自己的问题。引擎初始化的参数,活体引擎只需要指定Image模式或者video模式即可。FD引擎稍微复杂一些,(第一个参数就是我们之前输入的APPID(注意不是活体的AppID),SDKKey,图片的角度(默认为0度我们上面的三张图均为0度,逆时针为90度,顺时针为270度),最小人脸检测大小,检测的最多人脸数量)
初始化完成,接下来我们要去调用活体的引擎了,首先看看活体检测需要哪些参数,
在官方文档中有很详尽的介绍,首先是传入的图像数据,由于我们后面会选择NV21,所以要先用mageUtils.getNV21方法将图像数据转为NV21格式,图像宽度高度很简单就不多说,颜色空间格式我选择NV21,当然官方也提供了BGR24的格式,大家可根据需要选择,接下来参数是使用FD引擎跟踪的人脸信息格式,因此在活体检测前我们要先使用FD引擎进行人脸跟踪,才能进行活体的检测,最后一个参数是用来保存活体检测的信息。
这里就是FD进行人脸检测的代码,参数大部分和活体检测的差不多,唯一一点不同的是最后的fdFaceList是作为输出端保存检测到的人脸位置等数据,而活体部分是作为输入端输入人脸位置数据。好了,到了这一步我们需要的参数都已经齐全,总算可以进行活体的检测了。由于活体检测目前只能支持单人脸,因此我们需要先清理一下FD跟踪到的人脸数据,以实际情况来看,一般我们想检测的都是最大的人脸,因此我们先找到FDlist中最大的人脸。
清理完成,我们可以开始进行活体的检测,参数上面都已经讲过了,这里就不多赘述,直接看代码吧。
如果你的errorCode为0,那么恭喜你,起码在所有参数上你都没有问题了,之后只要从Liveneessinfo中拿到检测的结果就可以了,0代表非活体,1代表活体,2代表多余一张人脸(由于前面对数据已经做了最大人脸的清理,因此不会出现,看起来后续还会出多人脸的版本啊期待一下),其他均为未知。当然不要高兴的太早,在使用完引擎后我们要进行引擎的销毁。
好了图片模式的活体检测已经完成,具体的效果这边就不展示了,大家自己可以去尝试一下。接下来是视频模式下的活体检测,这才是我们日常生活中最常碰到的场景,而虹软也没有吝啬,给了它独立的Activity,和图片模式的待遇完全不一样呢:)
其实Video模式下的人脸检测与Image模式大同小异,无非是一个使用相机实时传回的数据源,另一个采用固定的数据源。稍微有所不同的是,我们的人脸跟踪引擎由FD改为了FT,FT相对于FD更快,更适合Video模式下的人脸实时跟踪。FT与FD的初始化参数一模一样,如果忘记的话可以往上翻一下。活体引擎我们由刚才的Image 改为了Video。
之后就是怎么使用FT与活体了,首先我们要拿到相机的预览数据,在preview的回调中我们可以拿到数据。
接下来的流程与Image模式一致,首先要找出数据源中的人脸,也就是调用FT寻找人脸。
与刚才不同的是我们要在视频的预览数据内画一个人脸框,让我们能清除的知道人脸有没有被检测到,检测到的是哪一个人脸。
活体检测的代码与上面的Image模式的代码一模一样,这里就不多做赘述,有不清楚的可以往上翻一翻。好了我们来看一下Video模式下的活体检测效果吧。
总的来说,在我自己测试的时感觉准确率还是相当的高的,也尝试了各种各样的方式去攻击,但是还是无法通过活体检测,证明虹软的算法确实很不错,更重要的是这些算法是免费提供的,对于我这种想尝尝鲜的人来说真的是个好消息。而且上手也快,官方的文档写的非常详细,对每个函数以及变量都有解释,而且也有示例的代码,在我的使用过程中基本没有碰到过什么阻碍,很轻松的就上手了,有些地方写的有些拖沓或者不清还请大家多多包涵,有不明白的问题也欢迎大家和我多多交流,后面的话等自己有时间可能会再写一篇用虹软的SDK进行二次开发的完整应用。