windorz9 / Blog-Getting-Started-with-Vision-OC

在 iOS 11 上使用 Vision

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Blog-Getting-Started-with-Vision-OC

在 iOS 11 上使用 Vision 什么是 Vision? Vision 是一个 APPLE 为 iOS 11 和其它的 APPLE 平台提供的一个新的框架. Vision 是 Core ML 框架的一部分. Core ML 是一个新的框架, 它让机械学习模型变得非常容易, 通过 Core ML 来运行你的数据甚至可以获得数据预测. Vison 框架帮助你来通过机器学习模式来处理图片. 使用 Vision 框架, 使用内置的和外部的机器学习模型, 可以很容易的从摄像机当中进行实时的处理并从每一帧当中提取信息.

内置功能: Vision 有许多的内置功能. 其中的一些功能可以为静态的图片进行处理, 其他的一些可以直接为视频进行处理, 大多数功能可以对两者都进行处理. 人脸检测 个体特征检测, 例如鼻子, 嘴巴, 左眼等等. 水平检测 矩形检测 角色检测 物体追踪 - 物体识别 通过外部机器学习模型.

开始物体追踪 我们将构建一个简单的项目, 用户在屏幕上点击一个对象, 然后 Vision 系统将跟踪该对象. 当用户移动手机时, 我们会将视频帧当中的物体追踪到. 另外如果对象进行移动, 它肯定会被 Vision 控件追踪到. 请注意, 下面的代码并不代表着是能降低视图控制器复杂性的最佳写法, 这只是为了让我们上手简单一点, 在理想情况下, 你应该将大部分的代码抽出为视图控制器自定义的对象. 另外请注意, 本教程假设你已经熟悉 StoryBoards 连接基本视图和手势.

项目概况:

  1. 启动 AVCaptureSession.
  2. 配置 AVCaptureSession.
  3. 配置 Vison 系统.
  4. 当用户点击屏幕时, 为 Vison 系统植入一个”观察”.
  5. 更新屏幕上的矩形当 Vision 系统返回新的”观察”时.

1.启动 AVCaptureSession 这算不上特别新鲜的代码, 所以我不打算详细的说明, 我们将添加一些懒加载属性到我们的视图控制器. 它们只是为了让我们访问 AVCaptureSession 和 AVCaptureVideoPreviewlayer, 以便用户可以看到视频源. 这里的 IBOutlet 只是一个和视图控制器的 view 等大的一个视图, 这样做得目的是简单的将高光视图放在视频源的最上层. 此时你应该可以启动 app 然后可以看到屏幕上的视频输出.

2.配置 AVCaptureSession 为了从 AVCaptureSession 获取视频缓冲区到 Vision 系统, 我们需要告诉 AVCaptureSession 我们想成为它的视频源的代理. 在 viewDidLoad: 当中添加如下代码.

为了接收视频帧, 我们需要遵循AVCaptureVideoDataOutputSampleBufferDelegate 并实现适当的方法. 将打印语句添加到下面的方法当中并运行该应用程序, 你应该可以看到控制台不停的返回 AVCaptureSession 的数据.

3.配置 Vison 系统 在这个项目当中, 我们将视频数据传输到 Vision 系统当中, 这意味着 Vision 对象是一个长时间存活的对象在我们的视图控制器当中. 所以我们要为 VNSequenceRequestHandler 添加另一个属性.

Vison 系统按顺序执行在一个事件循环当中, 你提供一个源观察对象, 然后将其输入 Vision 系统, 然后 Vision 系统输出一个新的观察对象. 当相机获取到新的数据时, 需要将新的观察对象结果反馈给 Vision 系统. 为了做到这一点, 我们需要为视图控制器添加一个新的属性. 这个属性将会存储源观察对象, 也同样会存储 Vision 系统返回的观察对象. 请记住 AVCaptureSession 通过反复调用代理方法来为我们创建整个循环.

在 captureOutput:didOutput:from: 方法里, 我们需要做一些其他的事.

  1. 我们需要将 CVPixelBuffer 从传入的 CMSampleBuffer 中取出.
  2. 我们需要确定我们已经保存了一个观察对象在上述的步骤创建的属性当中.
  3. 然后我们需要创建并配置一个 VNTrackObjectRequest.
  4. 最后, 我们需要请求 VNSequenceRequestHandle 执行请求. 注意, 该请求需要一个完整的操作, 但是我们传入了一个 nil, 这没什么影响, 我们将会在该教程之后完成编写完成处理程序.

4.当用户点击屏幕的时候, 为 Vision 植入一个观察对象. 当用户点击屏幕, 我们想要找出用户点击的位置, 然后将它当中源观察对象传入到 Vision 系统. 我们还想在点击的物体周围创建一个红色框, 以便用户可以观察到我们正在跟踪物体. 为此, 我们需要给视图控制器添加一个 @IBOutlet 属性的高亮视图, 直接在 StoryBoard 拖一个视图, 然后我们不要为其设置自动布局, 因为会在代码里面进行手动的管理它的 frame.

为了接收到点击, 我们需要在控制器的 view 上添加 UITapGestureRecognizer. 在 StoryBoard 当中添加一个 UITapGestureRecognizer 并拖入UITapGestureRecognizer 的 @IBAction 到视图控制器当中. 下面的代码就是响应点击然后用高亮视图在点击的物体周围显示出红色的边框. 注意, 当前点击想要追踪的物体显示出来的追踪边框尺寸是随意给的, 需要知道的是, Vision 系统对我们对追踪物体圈出的矩形的宽高非常的敏感, 圈出的矩形越接近物体, Vision 系统就能更好的进行追踪.

不幸的是, 我们不能直接将这个 CGRect 传给 Vision 系统, 这里有3个不同的坐标系我们必须进行转换.

  1. UIKit 坐标空间 原点在左上角 以像素点为单位, 屏幕的宽高最为其最大值.
  2. AVFoundation 坐标空间 原点在左上角 最大的宽高都为 1.
  3. Vision 坐标空间 原点在左下角 最大的宽高都为 1. 幸运的是, AVCaptureVideoPreviewLayer 有方法来帮助我们在 UIKit 坐标系和 AVFoundation 坐标系进行转换. 只要我们有了 AVFoundation 的值, 我们就可以通过反转原点 Y 来转换到 Vision 坐标系.

一旦我们获取到了正确的 CGrect 并传入到 Vision 系统, 那么我们就可以创建源观察对象并将其保存在我们之前创建的属性当中.

现在如果你运行程序并点击屏幕, 你会看到一个红色的边框出现在你点击的地方, 与此同时, 我们可能还不知道 Vision 正在运行并且正在执行图像跟踪. 因为我们还没有将完成处理的程序添加到我们的请求当中, 所以对象跟踪的结果没有做任何事情.

5.当 Vision 系统返回新的观察对象时, 更新屏幕上面的矩形. 我们将要添加一个新的方法到视图控制器当中, 我们将使用这个方法作为我们对象跟踪请求的完成程序.

确保调整请求对象将此方法最为一个完成处理操作.

在完成操作里, 我们需要做三件事

  1. 检查观察对象是否是正确的观察对象.
  2. 用新的观察对象替换 lastObservation 属性 这样的话, 下次就会有新的视频帧反馈给我们
  3. 更新 UI 将红色边框显示到新的观察对象. 这样的话用户就会看到持续的跟踪了. 继续, 这里是一个保护声明, 允许我们检查我们是否持有正确的观察类型, 并将它下次保存在我们的属性当中.

现在我们需要获取边界框并将其从 Vision 坐标空间转换为 UIKit 空间, 为此我们需要做于之前的点击事件相反的事, 我们拿到原点, 翻转 Y 坐标转换成 AVFoundation 的坐标, 然后我们使用 AVCapturePreviewLayer 将 AVFoundation 坐标转换为 UIKit 坐标. 如果我们在 HigtLightView 设置以新的坐标来设置 frame.

现在当你运行应用程序时, 你可以点击屏幕显示的某些物体, 并且应该可以慢慢平移手机并查看保留在该对象上的红色突出显示视图. 但是还需要添加一些改动, 我们可以检查观察对象的置信度. 置信度告诉我们该模型与我们正在跟踪的对象有多像. 置信度介于 0 和 1 之间, 在测试当中 0.3这个值应该是个临界值, 置信度低于 0.3 的话 跟踪情况就不容乐观了, 所以我们需要最后完成处理过程.

概要: 现在你就有了一个追踪实时视频的对象跟踪器了, 我们这里使用的技术几乎适用于所有的 Vision 框架请求类型. 可以使用 AVCaptureSession 委托回调将新的 CVPixelBuffers 和新请求提供给 VNSequenceRequestHandler. 另外需要注意, 请求处理程序的时候可以同时执行多个请求, 请求处理程序接受一个请求对象数组. 所以你可以让其中的几个做不同的事情并将它们传递到请求处理程序. 下面是两个主要的用例:

  1. 使用 VNDetectFaceRectanglesRequest 对象来检查面部. 找到人脸后, 为每张人脸创建一个新的 VNTrackObjectRequest, 以便跟踪在相机的周围移动的脸部.
  2. 使用 VNTrackObjectRequest 来跟踪用户感兴趣的对象, 然后创建一个 VNCoreMLRequest 以使用机器学习模块来尝试识别 VNDetectedObjectObservation 的边界框中的内容. 请注意, 所有 VNRequest 对象及其子类都有一个 regionOfInterest 属性. 设置它来告诉处理程序它应该看哪个部分的 CVPixelBuffer. 这就是你可以轻松地从观察的边界转到检测图像内部的内容.

About

在 iOS 11 上使用 Vision

License:MIT License


Languages

Language:Objective-C 100.0%