活体识别

最近项目需要做一个活体识别的功能,要求如下:
1.离线识别,本地识别活体。
2.免费,网上收费的项目不采用。
3.引入的新库足够小。
4.代码必须开源。

资源搜索

带着这么一堆的要求,开始一通搜索。

一、专业公司相关SDK

1.讯飞

在github上搜到的比较高的start的一个项目就是依赖讯飞sdk的。就是FaceRecognition这个库,但是这个库依赖的是一个旧版本的讯飞库,新版的讯飞库已经去掉了相关离线识别的代码。同时该库,识别率较低,同时对设备性能要求极高。

NOTE
关于这个库再补充两点,
1.这个库尝试了很多办法无法下载下来,所以采用了最土的办法,把文件一个个保存下来,同时在网上找到了一个将他的库二次打包静态库的骗子FBYFaceRecognitionDemo_iOS,这里可以将讯飞SDK下来下来,两个库组合到一起,就能跑起来了。
2.之后又找到了一个基于这个库进行二次开发的库FaceRecognition,这个库里面有原库的源码。

新版的讯飞库,讯飞SDKSDK在集成开发测试阶段服务量限制为最高500次/每日,完成提额申请或商务合作后可以解除,也就是说,这玩意也是收费的,旧版本收不收费已经无迹可寻。

在讯飞的开放平台上又找到了一个其他的sdk,静默活体检测,但是它是将一段实地拍摄的人脸视频进行云端检测,判断是否为真人活体并给出分值参考,这个跟我们的要求又是背离的。

所以结果就是讯飞SDK只能放弃。

参考

iOS活体人脸识别的Demo和一些思路
人脸识别 – 活体检测(张嘴摇头识别)

2.虹软

github上没有找到使用该库的开源库,官网注册了以后,可以在开发者中心中添加SDK,但是它的活体检测只有安卓版本,没有iOS版本,而且安卓的试了一下,只支持识别是不是活的,动作什么的并不能识别。同时因为该库未开源,所以ArcFace v2.0这个SDK也未去验证是否符合。

3.百度

在百度AI开放平台上找到了一个SDK–iOS-有动作活体版,该SDK满足我们的,离线,免费的要求,但是它需要申请企业认证,需要上传营业执照等申请一个appkey。

so,这个也放弃了。其实这个SDK是目前找到的公司层面的最符合我们要求的一个SDK,建议小公司直接采用该sdk即可,有大厂维护,应该不太会出什么问题。

二、系统原生–AVFoundation–CIDetector

在网上一搜会发现有很多是采用系统原生进行人脸识别的。

下面这些库使用的都是该方法:
FaceRecognition
LMJFaceRecognition

CIDetector只能进行静态图片的检测,也就是给一张图片,检测一下嘴巴眼睛什么的。只能检测当时的状态,无法检测动作。

参考

浅谈iOS中的人脸识别及活体检测
[iOS]CIDetector之CIDetectorTypeFace人脸识别
iOS图像处理(四)CIDetector特征识别(人脸识别)

三、网上开源项目 – dlib

官网
开源地址

因为星星没有opencv高,所以这个库没有做过多的研究,有兴趣的可以去研究一下。

开源代码:
face-landmarking-ios:该库是用swift所写。

四、网上开源项目 – opencv

网上这方面的开源库最流行的,做的最好的应该就是opencv了。

相关资源

opencv官网
资源下载
开源地址
iOS相关代码–cap_ios_video_camera.mm
iOS相关代码–cap_ios_abstract_camera.mm

开源库:
OpenFaceIOS
EyeBlickCheck相关介绍
FaceDetectionDemo_iOS:其中用到的libOliveappCombineSDK2.a貌似是同盾科技的。

识别SDK诞生

下面介绍的这个开源库就是我最终采用的识别库,该库是基于opencvHyperLandmark加入了SDM算法。

其实HyperLandmark北京智云视图科技有限公司开源的,这也是目前找到的唯一一个公司进行开源的人脸识别库。为它点赞。

我最终采用的就是HyperLandmark-iOS。简单说一下该库的有点:
1.提供了68点的标记。
2.支持旋转矩阵的展示。

其实基于以上两点,已经满足我们的需求了。

实现思路

我们的需求大概就是,用户进来->打开摄像头进行活体识别->人脸摆正校准->拍照->开始人脸动作识别->进行录像->人脸动作完成->录像结束。

拍照的话就比较简单了,opencv本来提供的就有摄像头帧的回调,拿到照片就比较简单了。所以现在比较难的几个点就是:

  1. 相关动作的识别。
  2. 录像。

难点解析

1.相关动作的识别

目前所用的库只给出了68点的数据,并没有给出具体的动作识别,所以只能根据这些点来判断用户所作的动作。
我所参考的坐标点就是人脸姿态估计人脸识别简介中所提供的图片,两张图其实是一致的。如下图所示:

张嘴闭嘴:
这个其实就是拿了3个点,分别是上嘴唇最下面一点62,下嘴唇最上面一点66,下嘴唇最下面一点57。然后根据6266的距离差与6657的距离差来判断是否张嘴。目前的规则就是如果6662的差大于5766的差则即为张嘴,否则就是闭嘴。

摇头点头
其实这个最开的思路也是打算使用同一状态下点的差值来估算的,但是后来发现了该库做的有旋转矩阵相关数据,于是就打算使用该数据来实现摇头和点头的判断。
大概看了一下它的接口代码,是没有提供旋转矩阵的数据的,所以只能稍微改了下源代码。它绘制旋转矩阵的方法是void ldmarkmodel::drawPose(cv::Mat& img, const cv::Mat& current_shape, float lineL),这个方法返回值是void,将其改成了cv::Vec3d对象,这样就能在外面拿到绘制的数据。然后再根据绘制的数据去区分是点头还是摇头。

参考

摄像头的旋转问题
OpenCV iOS - 视频处理

2.录像

其实opencv提供的有录像的相关功能,但是里面有些坑。

最开始的时候我使用的是旧版的opencv库,具体是哪个版本我没有去看过。在根据网上的操作去配置了相关属性之后,后来突然发现,在开始录像之后,内存一直急速网上飚,大概十几秒的时间就飚到了1g的内存,app直接crash。当时就说完了,这还玩个毛线。

后来考虑了两个方案:
1.自己维护一套录制视频的代码,不使用opencv提供的视频录制功能。
2.更新一下opencv库。

第一个方案尝试了一下,发现很难实现,因为一半是opencv的逻辑一半又是自己的逻辑,两边很难将时机恰到好处的结合起来。所以此方案宣告失败。

第二个方案,更新了一下opencv,最新版是4.1的版本,二进制文件居然有300多兆,之前才70多兆,好在最后打包其实没变对少。更新了之后发现之前的内存问题解决了。但是因为新旧版本的兼容问题进行了代码的调整与适配。

里面有几个需要注意的点:

  1. opencv的录像功能提供的接口比较简单,不适合特别复杂的录像功能。
  2. 录像过程中一定要维护好recordVideo这个变量,维护不好极易导致崩溃,看了一下OpenCV的源码,崩溃的原因是在写入帧率数据的时候的判断不够安全。
  3. 想要通过压缩帧率来压缩视频的话要自己去重置相关对象。
  4. 前后台切换的时候一定要丢弃应录制的视频,并且重置摄像头数据,不然也极易导致崩溃。
  5. 遇到问题的时候一定要去看下opencv的源码,上面有提供源码的地址。
参考

VideoRecord
WCLRecordVideo
视频的录制、保存、压缩以及base64转码