当前位置: 首页 > news >正文

人脸识别,并生成包含所有人脸的合适UIImage

#import <QuartzCore/QuartzCore.h>

+(UIImage*)betterFaceWithImage:(UIImage*)image showSize:(CGSize)showSize
{
    //低精度的探测:CIDetectorAccuracyLow已足够用。高精度的耗费时间。
    CIDetector* detector = [CIDetector detectorOfType:CIDetectorTypeFace
                                              context:nil
                                              options:@{CIDetectorAccuracyLow:CIDetectorAccuracy}];
    
    NSArray* features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];
    
    CGSize imageSize = image.size;
    
    CGRect fixedRect = CGRectMake(MAXFLOAT, MAXFLOAT, 0, 0);
    CGFloat rightBorder = 0, bottomBorder = 0;
    for (CIFaceFeature *f in features){
        CGRect oneRect = f.bounds;
        oneRect.origin.y = imageSize.height - oneRect.origin.y - oneRect.size.height;
        
        fixedRect.origin.x = MIN(oneRect.origin.x, fixedRect.origin.x);
        fixedRect.origin.y = MIN(oneRect.origin.y, fixedRect.origin.y);
        
        rightBorder = MAX(oneRect.origin.x + oneRect.size.width, rightBorder);
        bottomBorder = MAX(oneRect.origin.y + oneRect.size.height, bottomBorder);
    }
    
    fixedRect.size.width = rightBorder - fixedRect.origin.x;
    fixedRect.size.height = bottomBorder - fixedRect.origin.y;
    
    CGPoint fixedCenter = CGPointMake(fixedRect.origin.x + fixedRect.size.width / 2.0,
                                      fixedRect.origin.y + fixedRect.size.height / 2.0);
    CGPoint offset = CGPointZero;
    CGSize finalSize = imageSize;
    if (imageSize.width / imageSize.height > showSize.width / showSize.height) {
        //move horizonal
        finalSize.height = showSize.height;
        finalSize.width = imageSize.width/imageSize.height * finalSize.height;
        fixedCenter.x = finalSize.width / imageSize.width * fixedCenter.x;
        fixedCenter.y = finalSize.width / imageSize.width * fixedCenter.y;
        
        offset.x = fixedCenter.x - showSize.width * 0.5;
        if (offset.x < 0) {
            offset.x = 0;
        } else if (offset.x + showSize.width > finalSize.width) {
            offset.x = finalSize.width - showSize.width;
        }
        offset.x = - offset.x;
    } else {
        //move vertical
        finalSize.width = showSize.width;
        finalSize.height = imageSize.height/imageSize.width * finalSize.width;
        fixedCenter.x = finalSize.width / imageSize.width * fixedCenter.x;
        fixedCenter.y = finalSize.width / imageSize.width * fixedCenter.y;
        
        //0.618 黄金分割
        offset.y = fixedCenter.y - showSize.height * (1-0.618);
        if (offset.y < 0) {
            offset.y = 0;
        } else if (offset.y + showSize.height > finalSize.height){
            offset.y = finalSize.height = showSize.height;
        }
        offset.y = - offset.y;
    }
    
    CALayer *layer = [CALayer layer];
    layer.frame = CGRectMake(offset.x,
                             offset.y,
                             finalSize.width,
                             finalSize.height);
    layer.contents = (id)image.CGImage;
    
    UIGraphicsBeginImageContextWithOptions(showSize, NO, 0);
    [layer renderInContext:UIGraphicsGetCurrentContext()];
    // 返回 一个基于当前图形上下文的图片
    UIImage* betterFace = UIGraphicsGetImageFromCurrentImageContext();
    // 移除栈顶 的基于当前位图的图形上下文
    UIGraphicsEndImageContext();
    
    return betterFace;
    
}

相关文章:

  • 9月22日培训日记(下)
  • 我认为二氧化碳排放是好事
  • iOS7的UITableViewCell的clipsToBounds默认是YES
  • 发现Hibernate的bug与对Properties的深入认识
  • NSNumber、NSData、NSValue的使用场景
  • Blog小技巧之二-让朋友在Blog上也能QQ到自己
  • 高尔夫实际和弹玻璃珠是一回事
  • 兰德酷路泽原来就是陆地巡洋舰啊
  • 市场上咋没有好的关于嵌入式项目管理的书呢?
  • 比较日期精确到日
  • 一个感人的真事
  • 为什么《Visual Basic 2005程序开发与界面设计秘诀》和《Visual C# 2005程序开发与界面设计秘诀》值得买?...
  • 父亲的一个同学
  • appfuse配置文件解读
  • 使CBIntrospect支持在设备上使用
  • 网络传输文件的问题
  • [PHP内核探索]PHP中的哈希表
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • codis proxy处理流程
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • JavaScript HTML DOM
  • javascript 哈希表
  • JavaScript标准库系列——Math对象和Date对象(二)
  • node和express搭建代理服务器(源码)
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • TypeScript实现数据结构(一)栈,队列,链表
  • 从零开始的无人驾驶 1
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 在Unity中实现一个简单的消息管理器
  • 《码出高效》学习笔记与书中错误记录
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • ​configparser --- 配置文件解析器​
  • ​Linux·i2c驱动架构​
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • (175)FPGA门控时钟技术
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (C语言)fread与fwrite详解
  • (Forward) Music Player: From UI Proposal to Code
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (三)uboot源码分析
  • (转)winform之ListView
  • (转)创业家杂志:UCWEB天使第一步
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化