iOS Vision的使用

学习需要持之以恒,不做记录的学习就和不以结婚为目的去谈恋爱一样。

感觉自己学习的路途就是一路在耍流氓,没有做笔记的好习惯是不行的!不光是要留有代码,还要抒发己见多多与人讨论,才能真正的掌握和理解。

Vision与Core ML简介

17年WWDC大会又给我们带来了许多新玩意儿,今天要说的是其中一个时下比较热门的库---Vision。从名字就可以看出是视觉方面的功能。具体来说就是基于Core ML封装的图像识别库,整体层次是这样的。

image

苹果从 iOS 5 开始引入 NSLinguisticTagger 用于分析神经语言。在 iOS 8 中又出现了 Metal,Metal 提供了对 GPU 底层进行访问的能力。

去年,苹果在 Accelerate 框架中加入了基本神经网络子例程(BNNS),使得开发者能够创建用于推断(不是训练)的神经网络。

今年,苹果推出了 Core ML 和 Vision!

Core ML 使得在你的 app 中使用训练模型更加容易。

Vision 允许你轻松访问到苹果的面部识别、面部特征、文本、矩形、条形码和对象模型。

这两个框架是内置在 Metal 中的,它们高效运行在设备上,因此你并不需要将用户数据发送给服务器。

性能对比

image

从苹果给的对比图可知相对于已有框架Core Image和AVFoundation,Vision的准确度是最好的,同时和Core Image支持平台数量是一样的,但是需要较多的处理时间及电源消耗。Vision又是苹果封装过的库,相较于Core Image这种底层库,API会友好太多,减少了我们的开发量,只要专心处理图像就可以了。

开始使用Vision

环境

Xcode 9 + ios 11

Vision的结构体系:

image

Vision使用中的角色有:

Request,RequestHandler,results和results中的Observation数组。

我们在使用过程中是给各种功能的 Request 提供给一个 RequestHandler,Handler 持有需要识别的图片信息,并将处理结果分发给每个 Request 的 completion Block 中。可以从 results 属性中得到 Observation 数组。

observations数组中的内容根据不同的request请求返回了不同的observation,如:VNFaceObservation、VNTextObservation、VNBarcodeObservation、VNHorizonObservation,不同的Observation都继承于VNDetectedObjectObservation,而VNDetectedObjectObservation则是继承于VNObservation。每种Observation有boundingBox,landmarks等属性,存储的是识别后物体的坐标,点位等,我们拿到坐标后,就可以进行一些UI绘制。

Vision 支持的图片数据类型:

* CVPixelBufferRef

- CGImageRef

- CIImage

- NSURL

NSData

可以说几乎涵盖了iOS中图片相关的API,很实用很强大。

Vision 人脸检测实现


__weak typeof(self) weakSelf = self;

    // 转换为CIImage

    CIImage *convertImage = [[CIImage alloc] initWithImage:tempImage];

    // 创建图像处理request (携带要处理的对象)

    VNImageRequestHandler *detectRequestHandler = [[VNImageRequestHandler alloc] initWithCIImage:convertImage options:@{}];

    // 创建图像处理完成的回调 (处理完成的回调block)

    VNRequestCompletionHandler completionHandler = ^(VNRequest *request, NSError *error) {

        NSArray *observations = request.results;

        // 监测到所有的对象的点位,对每一个检测到的对象创建一个boxView

        for (VNFaceObservation *observation  in observations) {

            CGFloat w = observation.boundingBox.size.width * tempImage.size.width;

            CGFloat h = observation.boundingBox.size.height * tempImage.size.height;

            CGFloat x = observation.boundingBox.origin.x * tempImage.size.width;

            CGFloat y = tempImage.size.height - (observation.boundingBox.origin.y * tempImage.size.height) - h;

            CGRect facePointRect = CGRectMake(x, y, w, h);①

            UIView *boxView = [[UIView alloc]initWithFrame:facePointRect];

            boxView.backgroundColor = [UIColor clearColor];

            boxView.layer.borderColor = [UIColor redColor].CGColor;

            boxView.layer.borderWidth = 2;

            [weakSelf.detectCompleteView addSubview:boxView];

        }

    };

    // 创建侦测人脸识别请求 (要怎样处理request handler携带的对象)

    // 这里使用的是识别人脸

    VNDetectFaceRectanglesRequest *detectRequest = [[VNDetectFaceRectanglesRequest alloc] initWithCompletionHandler:completionHandler];

    // 执行

    [detectRequestHandler performRequests:@[detectRequest] error:nil];

代码就是整个创建及回调处理过程,是不是很简单~。

可以看到我们首先要对图片做处理,要把输入的图片转成Vision需要类型。我这里是通过UIImagePickerController的代理imagePickerController:didFinishPickingImage:editingInfo:拿到的相册图片,并把处理完的图片放到已有的detectCompleteView中。需要注意的是图片转换及处理点位生成boxView的时候,一定要使用你在View中做好的detectCompleteView的frame,使从代理方法中接受到的图片和detectCompleteView的frame一样。

** 看到有人说performRequests 是在子线程做的处理,而且VNRequestCompletionHandler是和perform在一个线程中,但我在使用过程中发现回调的block其实是在主线程中的。所以对UI操作不会有阻塞的影响,我会继续跟进,如果有清楚具体原因的也可以留言,谢谢~ **

VNRequestCompletionHandler回调的处理


(lldb) po request.results

<__NSSingleObjectArrayI 0x1c40185f0> (

 <VNFaceObservation: 0x1c419f210>E4A411F7-1E97-4262-9090-88831DB02219 1 [0.238984 0.354707 0.428141 0.321106] ID=0

)

①:可以看到处理完返回的VNFaceObservation给的值都是0-1,而且Vision使用的坐标原点是左下角,所以拿到值以后我们不能直接使用,而是要对它做处理匹配UIKit坐标系。PS:算出来的脸部是MAX Y值而不是min Y值。(2,4象限y值为相反数)

感想

本来打算一次把所有识别方式都放上来,但发现其实实现都是一样的,都是通过创建requestHandler,imageRequest 然后performe,最后等待VNRequestCompletionHandler的回调带回results和results中的Observation数组,只是相应的点位不同。比如VNDetectFaceLandmarksRequest带回的是

VNFaceLandmarks2D *landmarks = observation.landmarks;

如果需要显示,那么就根据给定的特征点进行绘制线条,同样的也是要对特征点做转换,区别于面部矩形识别在于得到的结果以point为准。也可以直接根据返回的点位做响应的识别,比如面部识别。
Vision 更像是一个工具库,对一些高频场景进行了封装,比如人脸、条形码、矩形和文字等。可以说Vision是基于底层 API 封装的高级功能可以帮我们减少很大的开发量。

Vision还可以很好的支持CoreML的创建,虽然苹果爸爸把预测模型整理的很好,只需要通过coremltools来转换模型为Xcode可识别的CoreML model,然后通过Xcode生成对接Model类我们就可以直接使用。但是因为每个模型的Input对图像的要求不一样,导致使用的时候我们还要针对模型来匹配尺寸。Vison在这个时候就可以发挥大作用!欲知详情,带下回分解~

↓↓↓当然你也可以参考这里↓↓↓
WWDC 2017 会议视频 506 :Vision Framework
WWDC 2017 会议视频 703:介绍 Core ML
Vision Framework: Building on Core ML
Advances in Core Image: Filters, Metal, Vision, and More


参考链接
Core ML 和 Vision: iOS 机器学习教程
iOS Core ML与Vision初识

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容