FaceRecognition

之前公司项目需要,研究了一下人脸识别和活体识别,并运用免费的讯飞人脸识别,在其基础上做了二次开发,添加了活体识别。项目需要就开发了张嘴和摇头两个活体动作的识别。 这里简单介绍一下当时的开发思路和一些个人拙见,欢迎大神指点。

首先说一下讯飞第三方的人脸识别的几个缺点: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) {

//延时操作

// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

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里给出了两种记录动作的方式,一种是有声音的拍照,一种是无声音的截图,可以为人脸的对比做铺垫。

尾声

ios识别人脸自动拍照_GitHub - qingweiiOS/FaceRecognition: 活体人脸识别,识别人脸,识别张嘴和摇头动作,并拍照...相关推荐

  1. ios识别人脸自动拍照_真的逆天?iOS 10相册识别人脸的秘密

    在今年的WWDC大会上,苹果正式发布了iOS 10系统,虽然其中诸多"新特性"我们早已在安卓系统中见识过了,但作为苹果用户依旧还是非常期待这些细节上的变化.根据大会上的演示,在iO ...

  2. ios识别人脸自动拍照_求助,使用APP开发自动拍照及标记脸部,可以付费

    自动拍照并标记需求说明: 背景:由于需要做一个人脸识别功能,需要打开摄像头自动拍照,并且用方框标记出人脸的位置,采用uni app后发现目前还不支持这个功能,需要开发第三方插件.人脸识别的功能类似与钉 ...

  3. ios识别人脸自动拍照_iOS12人脸识别测颜值捷径安装使用教程 iPhone怎么测颜值

    iPhone怎么测颜值?要实现这个功能,以往我们一般需要借助一些相机APP或在线工具来实现,不过今天小编发现了一个很有意思的捷径,通过"人脸识别测颜值"捷径,可以一键人脸识别测照片 ...

  4. 使用OpenCV进行人脸识别和自动拍照

    为了满足人们不同的需求,市面上出现了各种各样的APP,随着这些年移动互联网的发展,我想再也没有人能有精力或者有必要去统计出所有应用的个数了吧.当无数种具有个性的产品百花齐放时,一些共性的需求也逐渐被人 ...

  5. android实现基于表情识别和敲击识别的认证系统,表情识别支持自动的连续隐藏式拍照

    一个演示用的基于表情识别和敲击识别的App 演示用app,表情识别基于微软人脸识别API,可以在点击表情后自动多次拍照,拍照界面已经做了隐藏处理,当与预定义的表情序列匹配后人之成功. 敲击识别的功能上 ...

  6. 中兴智能视觉大数据报道:进小区1秒人脸识别,自动打开道闸放行

    中兴智能视觉大数据报:进小区1秒人脸识别,自动打开道闸放行,业主不用再为忘记带门禁卡而烦恼:有人到访只需按智能门禁,主人通过手机.IPAD就能看到是谁,不仅可以视频通话,一点击就可以开门--" ...

  7. AI人脸自动签到识别系统使用教程

    AI人脸自动签到识别系统是由未来自主研究中心研发一款名副其实的AI应用,也是互联网首款可离线操作人脸识别和人脸比对系统,本软件采用深度学习技术,是融合录像+人脸识别+人脸录入+人脸比对一体的可视化操作 ...

  8. Python网络爬虫实战:利用 Python ADB 人脸识别实现自动给抖音漂亮小姐姐视频点赞

    这只爬虫做了些什么事儿呢? 通过 ADB 控制你的手机,帮你自动刷抖音 调用百度人脸识别的接口,给视频画面中出现的小姐姐打分 自动给颜值 70 以上的小姐姐的视频点赞 有趣的是,根据抖音的推荐算法,连 ...

  9. 金行健:进门就被抓拍人脸自动注册会员,杭州一大学生将商场告上法庭

    10月29日,杭州市上城区人民法院受理了一起消费者诉商场人脸抓拍的案件.2021年8月1日,浙江理工大学学生小涛在杭州湖滨银泰in77商场购物时,发现MCM门店外安装了人脸识别抓拍摄像头.他进一步了解 ...

  10. 苹果手机人脸识别不了是什么原因_iPhone和安卓手机的人脸识别有什么区别?

    文/极客修小编 iPhone怎么识别人脸 今天一则新闻引起了我的注意 苹果供应商AMS宣布,推出全新的"behind OLED"红外接近传感器.刘海中的红外传感器TCS3701,能 ...

最新文章

  1. cmd做个定时弹窗_揭秘200元山寨苹果耳机!一颗耳边的“定时炸弹”...
  2. 论文笔记之:Multiple Feature Fusion via Weighted Entropy for Visual Tracking
  3. 大数据实效_全流程监督 让大数据督查取得实效
  4. chi-squared检验_每位数据科学家都必须具备Chi-S方检验统计量:客户流失中的案例研究
  5. asp.net core集成CAP(分布式事务总线)
  6. C#面向对象设计模式第二讲:Singleton Pattern单件模式(创建型模式)
  7. 网络产品用户体验优化系列[一]概要
  8. 通讯录获取源码_[源码和文档分享]基于Java语言的C/S模式通讯录备份和查询软件...
  9. 《离散数学及其应用》章节总结与github地址
  10. C++黑客编程——初识(1)
  11. 最新最全的 SQL 入门教程,老少皆宜,强烈推荐!
  12. 软考数据库工程师2020下午题@故障恢复解析
  13. cmd 实用快捷键。。
  14. hadoop原理示意图
  15. 可视化常用效果,js+css 实现人物百分比、象形图
  16. 偏倚方差分解——R code
  17. 西门子数控系统变量刀补输入——使用$TC_DP函数
  18. LiveCharts
  19. 关于Linux和Windows一个对比
  20. python结合mitmproxy抓包实践

热门文章

  1. 计算机信息安全技术分为两个层次,李某将玉佩以合理价格转让给善意第三人朱某时,下列说法正确的是?()。...
  2. E45: ‘readonly‘ option is set (add to override) 解决方法
  3. c语言编程 甲乙丙丁谁是罪犯的题,犯罪大师第二届推理大赛有甲乙丙丁四人答案是什么...
  4. Ubuntu下vscode配置OpenGL(使用glfw+glad)
  5. 数学----第一个重要极限证明
  6. win8计算机无法安装打印机驱动程序,win8系统安装打印机驱动失败怎么办|win8系统安装打印机驱动失败的解决方法...
  7. VM虚拟机中 localhost login_虚拟机VM VirtualBox的安装和使用
  8. 将ipone项目转到ipad平台以及开发同时支持这两个平台的项目
  9. RAW图片转换JPEG图片工具(免费)
  10. “扣哒杯” AI世青赛公布2021-2022年度全国决赛个人获奖名单