代码地址如下:
http://www.demodashi.com/demo/12011.html

之前公司项目需要,研究了一下人脸识别和活体识别,并运用免费的讯飞人脸识别,在其基础上做了二次开发,添加了活体识别。项目需要就开发了张嘴和摇头两个活体动作的识别。 这里简单介绍一下当时的开发思路和一些个人拙见,欢迎大神指点。
首先说一下讯飞第三方的人脸识别的几个缺点:1.识别不稳定,各点坐标跳动偏差比较大,不容易捕捉;2.CPU使用率比较高,连续识别一会儿手机会明显发烫,手机配置低的,就会反应很慢,本人使用的iPhone 6s,配置还可以,还算比较流畅,但也会发烫。3.屏幕小的手机识别率相对会低一点,当然这也和手机的配置脱不了干系。
下面开始我们的活体识别开发之路:

确定位置

讯飞的人脸识别坐标跳动比较大,如果全屏识别发现很容易出现错误的识别,导致识别错误的被通过,所以为了降低这个可能性,特意加了脸部位置的限制,把识别位置和范围大大缩小,大大提高了识别精度和成功率。
原版的Demo里给出了人脸框的坐标,也显示出了人脸的框,代码如下:

-(void)drawPointWithPoints:(NSArray *)arrPersons
{if (context) {CGContextClearRect(context, self.bounds) ;}context = UIGraphicsGetCurrentContext();for (NSDictionary *dicPerson in arrPersons) {if ([dicPerson objectForKey:POINTS_KEY]) {for (NSString *strPoints in [dicPerson objectForKey:POINTS_KEY]) {CGPoint p = CGPointFromString(strPoints);CGContextAddEllipseInRect(context, CGRectMake(p.x - 1 , p.y - 1 , 2 , 2));}}BOOL isOriRect=NO;if ([dicPerson objectForKey:RECT_ORI]) {isOriRect=[[dicPerson objectForKey:RECT_ORI] boolValue];}if ([dicPerson objectForKey:RECT_KEY]) {CGRect rect=CGRectFromString([dicPerson objectForKey:RECT_KEY]);if(isOriRect){//完整矩形CGContextAddRect(context,rect) ;}else{ //只画四角// 左上CGContextMoveToPoint(context, rect.origin.x, rect.origin.y+rect.size.height/8);CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width/8, rect.origin.y);//右上CGContextMoveToPoint(context, rect.origin.x+rect.size.width*7/8, rect.origin.y);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width, rect.origin.y);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width, rect.origin.y+rect.size.height/8);//左下CGContextMoveToPoint(context, rect.origin.x, rect.origin.y+rect.size.height*7/8);CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y+rect.size.height);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width/8, rect.origin.y+rect.size.height);//右下CGContextMoveToPoint(context, rect.origin.x+rect.size.width*7/8, rect.origin.y+rect.size.height);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width, rect.origin.y+rect.size.height);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width, rect.origin.y+rect.size.height*7/8);}}}[[UIColor greenColor] set];CGContextSetLineWidth(context, 2);CGContextStrokePath(context);
}

在这段代码的启发下,我对此作了改装,把动态的人脸框,改成了静态的框,这个静态框,就是指示和限定人脸位置的框,根据屏幕大小画出的,代码如下:

-(void)drawFixedPointWithPoints:(NSArray *)arrFixed
{for (NSDictionary *dicPerson in arrFixed) {if ([dicPerson objectForKey:POINTS_KEY]) {for (NSString *strPoints in [dicPerson objectForKey:POINTS_KEY]) {CGPoint p = CGPointFromString(strPoints);CGContextAddEllipseInRect(context, CGRectMake(p.x - 1 , p.y - 1 , 2 , 2));}}if ([dicPerson objectForKey:RECT_KEY]) {CGRect rect=CGRectFromString([dicPerson objectForKey:RECT_KEY]);// 左上CGContextMoveToPoint(context, rect.origin.x, rect.origin.y+rect.size.height/8);CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width/8, rect.origin.y);//右上CGContextMoveToPoint(context, rect.origin.x+rect.size.width*7/8, rect.origin.y);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width, rect.origin.y);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width, rect.origin.y+rect.size.height/8);//左下CGContextMoveToPoint(context, rect.origin.x, rect.origin.y+rect.size.height*7/8);CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y+rect.size.height);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width/8, rect.origin.y+rect.size.height);//右下CGContextMoveToPoint(context, rect.origin.x+rect.size.width*7/8, rect.origin.y+rect.size.height);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width, rect.origin.y+rect.size.height);CGContextAddLineToPoint(context, rect.origin.x+rect.size.width, rect.origin.y+rect.size.height*7/8);}}[[UIColor blueColor] set];CGContextSetLineWidth(context, 2);CGContextStrokePath(context);
}

这里的框是限定脸部位置的,所以脸部位置超出设置的范围的时候,就需要停止人脸识别,停止动作识别,并给出用户提示,提示用户调整位置,或者明确告诉用户,脸部距离屏幕太近了,或者太远了。判定脸部位置的代码如下:

#pragma mark --- 判断位置
-(BOOL)identifyYourFaceLeft:(CGFloat)left right:(CGFloat)right top:(CGFloat)top bottom:(CGFloat)bottom
{//判断位置if (right - left < 230 || bottom - top < 250) {self.textLabel.text = @"太远了...";[self delateNumber];//清数据isCrossBorder = YES;return YES;}else if (right - left > 320 || bottom - top > 320) {self.textLabel.text = @"太近了...";[self delateNumber];//清数据isCrossBorder = YES;return YES;}else{if (isJudgeMouth != YES) {self.textLabel.text = @"请重复张嘴动作...";[self tomAnimationWithName:@"openMouth" count:2];
#pragma mark --- 限定脸部位置为中间位置if (left < 100 || top < 100 || right > 460 || bottom > 400) {isCrossBorder = YES;isJudgeMouth = NO;self.textLabel.text = @"调整下位置先...";[self delateNumber];//清数据return YES;}}else if (isJudgeMouth == YES && isShakeHead != YES) {self.textLabel.text = @"请重复摇头动作...";[self tomAnimationWithName:@"shakeHead" count:4];number = 0;}else{takePhotoNumber += 1;if (takePhotoNumber == 2) {[self timeBegin];}}isCrossBorder = NO;}return NO;
}

这个方法基于Demo中第三方封装库中给的代理方法-(NSString*)praseDetect:(NSDictionary* )positionDic OrignImage:(IFlyFaceImage*)faceImg; 判断脸部并返回人脸的脸框的坐标,所以利用给的脸部框坐标做判断,超出设置的范围时停止识别。
其中,脸部框两边的坐标左边大于一定值且右边小于一定值的时候,判定为脸部位置“太远了”;同理,脸部框两边的坐标左边小于设定边框点且右边大于设定边框右边点的时候,判定为脸部位置“太近了”;如果位置正确,则脸部位置到达正确位置,这个时候显示脸部各点,并开始活体动作识别:张嘴和摇头。我这里先做张嘴,再做摇头。

张嘴识别

张嘴识别,这里的嘴部定点有五个:上、下、左、右、中。这里我取的是上下左右四个点,并判断上下点的距离变化和左右点的距离变化,一开始只判断了上下点距离变化超过设定值得时候就判断为张嘴,后来测试过程中,上下晃动屏幕,会判断失败,直接通过。所以为了解决这个bug,并判断更严谨,加上了左右点的判断,即上下点变化大于设定值并且左右点变化小于设定值的时候判定为张嘴动作识别通过。代码如下:

#pragma mark --- 判断是否张嘴
-(void)identifyYourFaceOpenMouth:(NSString *)key p:(CGPoint )p
{if ([key isEqualToString:@"mouth_upper_lip_top"]) {upperY = p.y;}if ([key isEqualToString:@"mouth_lower_lip_bottom"]) {lowerY = p.y;}if ([key isEqualToString:@"mouth_left_corner"]) {leftX = p.x;}if ([key isEqualToString:@"mouth_right_corner"]) {rightX = p.x;}if (rightX && leftX && upperY && lowerY && isJudgeMouth != YES) {number ++;if (number == 1 || number == 300 || number == 600 || number ==900) {mouthWidthF = rightX - leftX < 0 ? abs(rightX - leftX) : rightX - leftX;mouthHeightF = lowerY - upperY < 0 ? abs(lowerY - upperY) : lowerY - upperY;NSLog(@"%d,%d",mouthWidthF,mouthHeightF);}else if (number > 1200) {[self delateNumber];//时间过长时重新清除数据[self tomAnimationWithName:@"openMouth" count:2];}mouthWidth = rightX - leftX < 0 ? abs(rightX - leftX) : rightX - leftX;mouthHeight = lowerY - upperY < 0 ? abs(lowerY - upperY) : lowerY - upperY;NSLog(@"%d,%d",mouthWidth,mouthHeight);NSLog(@"张嘴前:width=%d,height=%d",mouthWidthF - mouthWidth,mouthHeight - mouthHeightF);if (mouthWidth && mouthWidthF) {//张嘴验证完毕if (mouthHeight - mouthHeightF >= 20 && mouthWidthF - mouthWidth >= 15) {isJudgeMouth = YES;imgView.animationImages = nil;}}}
}

张嘴动作识别通过后,开始判断摇头动作。

摇头识别

摇头识别,这里的摇头动作相比于张嘴动作,摇头动作我没有限制位置,张嘴识别必须在设置的框内完成动作,摇头动作不需要,因为摇头动作幅度大,需要的位置大,如果再限定位置的话,识别要求比较高,不容易识别通过,用户体验差。
摇头识别的思路比较简单,没有做细致的计算分析,仅仅是判断了鼻尖的点的坐标改变大于设定值,即判定为摇头动作通过。代码如下:

#pragma mark --- 判断是否摇头
-(void)identifyYourFaceShakeHead:(NSString *)key p:(CGPoint )p
{if ([key isEqualToString:@"mouth_middle"] && isJudgeMouth == YES) {if (bigNumber == 0 ) {firstNumber = p.x;bigNumber = p.x;smallNumber = p.x;}else if (p.x > bigNumber) {bigNumber = p.x;}else if (p.x < smallNumber) {smallNumber = p.x;}//摇头验证完毕if (bigNumber - smallNumber > 60) {isShakeHead = YES;[self delateNumber];//清数据}}
}

其实这样判断摇头是有bug的,左右晃动手机超过一定的距离,也会判定摇头通过,当时时间紧张,没做过多处理,所以就暂时这样判定了。

其他细节

判断比较数据,我用了计数法,取得是不同时间点的帧图片上的点的位置并记录下来,然后和初始值做比较,所以如果判断不符合要求,需要清除数据,并重新开始记录并判定。
另外Demo里给出了两种记录动作的方式,一种是有声音的拍照,一种是无声音的截图,可以为人脸的对比做铺垫。

文件目录截图

尾声

Demo的gitHub欢迎大家下载、参考、指正、交流,如果对您有帮助,感谢star,另外建立了一个活体识别交流群:498197808,欢迎同道中人加入,大家一起交流学习。

iOS活体人脸识别的Demo和一些思路

代码地址如下:
http://www.demodashi.com/demo/12011.html

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

iOS活体人脸识别的Demo和一些思路相关推荐

  1. android 人脸识别demo,Android Camera 内置人脸识别的Demo

    CameraFace Android Camera 内置人脸识别的Demo 通过Android源生API支持的人脸识别FaceDetection,获取到脸部矩形坐标,左右眼坐标,嘴坐标通过View动态 ...

  2. java基于安卓的人脸识别_基于android studio开发的 opencv关于android人脸识别的DEMO

    (2018年11月23日 在 链接 补充了一个新的BUG) 一个新项目的导入 可能会遇到多个问题,就这些问题 做个 解决集合,以便日后回顾, 版本 : android studio3.1.4 ,ope ...

  3. android拍照识别人脸,Android 人脸识别拍照demo

    1.活体与照片.效果,捕获人脸 2.活体人脸识别:https://blog.csdn.net/meixi_android/article/details/88690445 运行效果: 自定义获取人脸v ...

  4. Android 人脸识别拍照demo

    1.活体与照片.效果,捕获人脸 2.活体人脸识别:https://blog.csdn.net/meixi_android/article/details/88690445 运行效果: 自定义获取人脸v ...

  5. android检测张嘴眨眼,Android/IOS 活体检测(眨眼,摇头,点头,张嘴,远近)

    更新记录 1.1.2(2021-05-24) ios优化活体算法 1.1.1(2021-05-17) v1.1.1_release(2020.05.14) 添加框的绘制 在计算人脸关键点变化的过程上加 ...

  6. matlab做pca人脸识别,[转载]一个修改后的PCA进行人脸识别的Matlab代码,识

    一个修改后的PCA进行人脸识别的Matlab代码,识别率达到88% % calc xmean,sigma and its eigen decomposition allsamples=[];%所有训练 ...

  7. 技术详解:基于人脸识别的 AI 弹幕

    --------点击屏幕右侧或者屏幕底部"+订阅",关注我,随时分享机器智能最新行业动态及技术干货---------- 有时候,弹幕比剧情还精彩,那些脑洞大开.观点鲜明的弹幕,可以 ...

  8. OpenCV学习笔记(五十四)——概述FaceRecognizer人脸识别类contrib

    在最新版的2.4.2中,文档的更新也是一大亮点,refrence manual扩充了200多页的内容,添加了contrib部分的文档.contrib就是指OpenCV中新添加的模块,但又不是很稳定,可 ...

  9. 2dpca的matlab代码,2DPCA人脸识别的matlab代码

    [实例简介] 很好用的2DPCA人脸识别的matlab代码 [实例截图] [核心代码] 2dpcamatlab └── 2dpcamatlab ├── CreateDatabase.m ├── orl ...

  10. 基于人脸识别的web展示

    基于人脸识别的web展示 一.本课题实现目的是一个基于web的人脸识别系统,该系统主要分为人脸检测和人脸识别两大功能模块. 用户在人脸识别模块上先通过人脸注册采用摄像头注册的方式或者照片注册的方式先行 ...

最新文章

  1. linux 推荐硬件配置,2012最受欢迎的Linux用户硬件配置
  2. 我关注的编程Up主,竟然是新晋IOI第一人:18岁高中生,玩起《我的世界》来不能打扰...
  3. 【信息抽取】如何使用卷积神经网络进行关系抽取
  4. C语言找出4个最大和4个最小数,济南大学C语言程序设计教案:C语言实验课程第四课.doc...
  5. 数学--数论-多重集排列组合与母函数
  6. PHP设计模式练习——制作简单的投诉页面
  7. 加速深度学习在线部署,TensorRT安装及使用教程
  8. linux下用tcpdump抓包
  9. MAgent安装及初步试验
  10. Oracle数据库的优化--索引
  11. java人民币大写金额_java简单题:一组金额数据,用人民币大写显示出来
  12. Windows自带远程连接Ubuntu桌面
  13. Elasticsearch的DSL搜索
  14. ylbtech-公司-滴滴出行:滴滴出行
  15. 手把手教你打通车载蓝牙与手机app的音频信息传输车载反向控制手机app
  16. armbian打印服务器恩山无线,刷了armbian后用cups共享打印非常爽
  17. java 实现 公式计算
  18. Android8.1 MTK平台 Dialer修改(通话常亮、按钮接听)
  19. 如何让微信公众号具备查询功能?试试这个方法
  20. 克里金插值详细步骤_暖气片怎么放气?暖气片怎样排空气?步骤和方法,规范详细!...

热门文章

  1. Airbnb短租房源数据可视化
  2. sql服务器字段顺序怎么修改,你可能不知道SQL Server索引列的升序和降序带来的性能问题...
  3. 网上商城系统支付方式如何配置?支付方式有哪些
  4. 小程序中wx-if使用方法
  5. OneHotEncoder简单用法
  6. 计算机卡死后自动关机,电脑经常卡住自动关机怎么办
  7. “快解析”动态域名解析工具使用教程
  8. 免费的易语言网络验证系统
  9. python社团宣传语_宣传语_Python语言及其应用_红黑联盟读书频道
  10. 聚合数据API接口测试详细步骤