大多数浏览器和
Developer App 均支持流媒体播放。
-
利用 Core ML 和 ARKit 创建出色的 App
开始学习之旅,了解如何结合利用 Core ML、ARKit 及其他 app 框架来创建教育游戏。探索利用机器学习为您的 app 带来神奇互动的机会。更深入地了解棘手计算机视觉问题的解决方法。在互动编程讲座中,观看这一切如何实现。
资源
相关视频
WWDC19
-
下载
各位早上好 感谢各位来参加我们的会议
在 Apple 我们开发技术 我们开发的技术用于让各位 创造具有惊人体验的优质 App 我最喜爱的 App 是那些 无缝地融入技术 并且让我们能在使用时 沉浸其中的 App
今天我想与各位探讨的是 其中两个技术 Core ML 和 ARKit 这两个技术共同帮助 我们的设备更深入 认识周围的世界
它们帮助我们将虚拟世界 和现实世界融合在一起
今天我们将带各位 领略如何开发出 App 实现以上目的 在此过程中我们将探讨一些 将会遇到的挑战 以及怎样克服它们 并且我们还将探讨 在面对困难时 衍生的一些主题
首先我们的第一个问题是 机器学习是否有帮助
当然如果我说没有帮助的话 今天的会议将会非常短暂 但我不能简单地肯定这一观点 因为这一问题的答案 取决于你正在解决的问题 以及你必须去处理 的有关数据
因为机器学习的内容 就是理解你所拥有的信息 机器学习有关于 理解数据内部的模式 这些模式可能很难用 程序化的语言去描述 而且这些数据是存在于 你的 App 中的 你的用户每天都在输入数据 他们使用键盘 来输入文本信息 他们使用麦克风 来记录声音信息
他们使用摄像头 记录照片和视频 所以当我们遇到问题的时候 机器学习有帮助吗 这是一个很好的问题 所以你需要认真审视你所要 解决问题的类型 以及你目前可以用于 解决这个问题的数据有哪些
我们今天要了解的第二个主题 是去理解你的 模型具有的行为 这些模型被训练为接收 特定格式的输入 然后提供 特定格式的输出 也就是说如果你的输入并不是 模型预期的特定格式 那么它的输出也将是 你所无法预计的 而要说到输出 如果你不知道你的模型输出什么 那么要在你的应用中 实现神奇的用户体验 可能是会非常难的
我们将通过几种方式 来让你将某些模型的 输入和输出可视化 但是现在 先继续我们的旅程
我们说过我们将利用 一系列技术的组合 来融合虚拟世界和现实世界 那除了 App 之外 还有什么内容更适合完成这一目的呢 我们认为为儿童构建一个 教育类的游戏 来练习他们的数学技巧 像是计数和加减乘除 这个想法非常有趣 并且我们知道孩子们有时候 会利用骰子来练习这些技能 那现在我们就可以把 虚拟的骰子放进 App 中 让这些骰子在屏幕上滚动 但我们想更有趣的方式会是 如果能让孩子们在现实中 在桌面上投实体的骰子 并且让这些骰子能与 我们的 App 交互
所以这就是我们所做的 我们遇到的第一个挑战是 如何让我们的应用识别出骰子 这里有几种方法 让我们以编程方式开始 但这会有一些困难
如果我们将问题限制在 识别六面骰 我们就可以开始研究骰子的属性 比如看我身后的骰子 它的颜色是灰色的
但并非所有骰子都是灰色的 所以这并不一定有用
如果你在 2D 平面上观察它 它是一个六边形的形状 由三个斜矩形构成
但随着骰子在桌面上滚动 这些形状将会发生变化 如果我们仔细观察每一面 它们上面会有很多点 但是这也会因为 你所看的面的变化以及 观察角度变化 而有所改变
所以随着这些属性的改变 要编写程序来识别骰子 将会是一件困难的事情 所以让我们来看看 机器学习的方法
我们可以训练图像分类模型 来识别出图像中的骰子 但我们想知道图像中有多少骰子 而不仅仅是判断 图像中是否有骰子存在
因此我们考虑使用 对象检测模型 对象检测模型将告诉我们 图像中是否有骰子存在 并且还将告诉我们骰子的位置 如果我们知道骰子在图像中的位置 那我们就可以 计算图像里骰子的个数 要做到这一点 我们需要获取数据 所以我们将一堆骰子 放在桌面上滚动 接下来我们拍摄这些图片 然后用边界框标记他们 这些边界框标注出 骰子在图像中的位置 之后我们利用新的 Create ML 来训练我们的 对象检测模型
如果你想了解更多有关 训练的信息 可以参阅 Create ML for Object Detection and Sound Classification 这一会议 现在我想邀请 Scott 来实际展示
Scott 大家早上好 早上好
正如 Brent 讨论的那样 我们将探索使用被称为对象检测 的机器学习技术 来增加我们的 App 识别骰子能力的方法 而且我相信你们都想 看到这一方法可以奏效 所以让我们开始吧
在这里我们有一个简单的 App 这一 App 连接了实时摄像机视图 并且我们添加了 已经训练好的 对象检测器来对骰子计数 所以让我们来看看 当画面中增加骰子时会发生什么
一二三四 我们可以掷骰子来让这变得更有趣 所以这是很棒的 我们的 App 能够使用 对象检测器来识别骰子 但是我们今天要讨论的主题 之一是理解 你的模型的行为 因此让我们实际看一下 模型所看到内容的 通过调试可视化能得到什么 正如你所见的 我们在每个检测到的对象 周围都绘制了边界框 在这一场景下对象是桌上的骰子 如果我们移动它们 那么这些边界框也会随之移动 这对你来说非常重要 因为如果你正在训练一个 对象检测器模型 并且你没有在 你不想检测的其他物体 看到有边界框存在 或者你并没有看到 在你想要检测的物体上 出现你想要的边界框 这可能是你在这种 光照条件下收集更多数据的 一次很好的机会 你可能会想收集 不同背景下 不同光照以及 不同数量对象的更多数据 在这个场景下我们有四个 但你有可能想使用 五个或者六个甚至多达十个 或者更少甚至没有骰子 的图片来训练模型 使之不会识别错误
让我们来看看一些 实现这一目的的代码 当你处理使用 Create ML 在 Vision 框架下 训练过的对象检测器时 你得到的结果是 VNRecognizedObjectObeservation 列表 因此这里我们有一个函数 处理这些观测结果 并且完成一些功能 第一个也是最简单的 我们只计数骰子的个数 这就和观察结果的数量是一样的 因为每个骰子只计数 1 接下来我们有几个辅助函数 可以根据这些已经识别的对象 的观测结果来在图片上 绘制边界框 第一个函数的功能是 为每一个识别出来的对象观测结果 绘制需要的边界框 这一边界根据你提供给 Vision 的输入图像输出 标准化之后的坐标 以便该函数将这些 结果映射回我们的 视图控制器中的视图坐标系 这样我们就可以在 屏幕的正确位置绘制它们 将它们覆盖在 图像中的实际物体上方
接下来我们还有一个辅助函数 可以帮助我们在屏幕上 绘制精美的圆角矩形 这一圆角矩形被称为 CALayer 接下来我们将 CALayer 添加到 屏幕上需要渲染的叠加层上 所有这些代码都可以在 与这一会议相关的示例 App 中找到 大家可以去查看 到现在为止进展顺利 我们的 App 已经可以 利用对象检测来计数骰子 但你可能已经意识到或者想过 游戏通常并不依赖于 骰子的数量这一事实 它们通常依赖于 骰子上面显示的数值 所以我们还需要更进一步 弄清楚如何识别 这些在骰子上显示的数值 这是我们希望我们的 App 最终需要实现的功能 我们希望它可以告诉 右侧的骰子结果是 5 而左侧骰子的结果是 1 幸运的是 正如 Brent 所提到的 对象探测器不仅可以检测物体 它还能对物体进行分类 因为它被构建来识别 各种不同的物体和图像 接下来让我们更新我们的训练数据 将不同值的骰子视为不同类 就像你在屏幕上看到的那样
这听起来能够实现 所以我们在我们的 App 中 进行了尝试 让我们来看看 遇到的一些实例 在大多数情况下它运行得很好 正如你在我身后图片中 所看到的那样 我们的对象检测器可以 正确且准确地检测和分类 屏幕左侧出现的骰子 但如果我们关注另一边 我们将发现我们的对象检测器 将 6 和 4 这两个骰子 检测为一个骰子
如果我们仔细考虑一些 事情发生的原因 很明显模型不能将它们 分开识别成两个独立的骰子 并且这一情况 要归结于 4 这个骰子 被出现在前面的那个骰子遮住
所以考虑一下这件事情之后 我们意识到我们真正关心的 是这些骰子的顶部 并且骰子的顶部对于我们 来说总是可见的
所以我们将更进一步 给予我们的模型一点小帮助 我们更新了所有训练数据 关注这些骰子的顶部 所以我们现在训练的对象检测器 并不是为了检测骰子 而是去检测骰子的顶部
那么让我们来看看当我们这样做时 将会发生什么 正如你所看到的 我们的模型仍然能正确 识别和分类左边这些骰子 但现在这个模型还能够 正确地将右边的骰子 进行检测和分类
今天我们还想与你分享另外一个小插曲
在我们的探究过程中 我们注意到了这种情况 我们的模型一直在 检测骰子的左侧
在一开始这非常令人困惑 但如果我们旋转这一个图像 我们就能理解模型 是如何将这些识别成顶部的 这很容易理解 只要我们去关注 模型的输入是怎样的 我们没有根据设备的方向 调整图像的方向 这是视觉任务中 经常出现的一个问题 因此这里的关键教训是 如果你在模型的输出中 发现了奇怪的行为 看一下输入总没有什么坏处 它也许就和根据设备的方向 旋转你的图像一样简单 让我们看看这个新模型效果如何
还是同样的 App 但我们进行了更新 使得我们的模型可以对骰子 进行检测和分类 为了简单起见我将专注于 三个骰子的情况 我们可以看到我们的模型 检测到了 6 和 5 和 2
让我们掷一次骰子
4 和 6 和 5 棒极了 我们做的很好 我想请你关注一个 我认为非常重要的细节 如果我移动骰子 你可以看到列表更新了 我们实际上根据骰子 在桌面上的排列顺序 来显示值列表 这是一个次要的设计细节 但它确实带来了体验的一致性 因为我们的用户 能在桌面上看到 这些骰子的排布情况 所以既然我们已经将 物理和虚拟世界进行融合 我们实际上正在为
用户提供非常一致的显示结果
还有一件事情我们需要弄清楚 什么算掷一次骰子 与之前相同 游戏通常不依赖于掷骰子的过程 而是依赖掷骰子的结果 当你进行游戏时 你将会掷出一些骰子 并根据投掷结果来决定 棋子的移动或进行决策 在这种情况下 我们可能要为用户制作 动画效果或者提供反馈 你可能已经在之前的演示中注意到 直到掷骰子结束 画面上才显示数字 那么我们应该怎么做呢 首先我们需要问自己 我们观察到了什么
在这一情况下我们注意到 骰子停了下来并且 在不同的相机帧之间值是稳定的
机器学习能在这里帮助我们吗
或许我们可以构建一个 顺序模型接收帧数据 来决定掷骰子是否已经结束 但我们已经有了一个 能够理解桌上骰子 排布的模型 所以我们真正需要做的是 解读我们模型的输出
那么让我们来看看 如何在代码中执行这一操作 这里我们有一个函数 它接受两个对象观察列表 一个来自当前相机帧 另一个来自于 前一个相机帧
所以我们需要检查一些事情 来判断当前骰子 是否已经停止滚动 首先我们现在拥有 和之前一样多的骰子吗
如果没有那么也许有一个骰子进入 当前的相机帧里面 于是我们有了比之前多的骰子 如果数量比以前少了 也许其中一个还在滚动 所以我们的检测器 没有将它检测出来 因此如若我们没有和原来 一样多的骰子 那掷骰子过程没有结束 接下来我们将比较 先前的预测结果 和当前的预测结果
如果骰子顶部显示的值 并不相同那说明 掷骰子过程没有结束 我们还将检测这些预测结果 边界框之间的重叠度 是否超过 85% 如果我们当前的预测结果 和我们正在比较的预测结果 之间的边界框并不重叠 说明要么我们正在 看的是两个完全不同的骰子 要么这个骰子 发生了明显的移动
最后如果我们得到的 匹配结果与桌面上骰子数量一致的话 代表掷骰子过程结束 因此现在我们的 App 能够 查找计数并识别出桌面上的骰子 并且判定掷骰的动作已经结束 我们有了很好的基础 可以做更多的事情 接下来是时候谈谈我们 旅程的下一步了 为此我想欢迎 Brent 重返舞台
感谢 Scott 好的 正如 Scott 所说 我们的 App 能够识别桌上的骰子
下面我们需要关注的 是我们如何处理用户的输入 我们知道我们的用户将在 我们的 App 中输入数字 因为我们正在练习数学技能 我们可以在屏幕上显示 一个数字板 并让他们点按数字 但我们想要促进用户与 App 之间 更自然的交互 请记住我们的用户是孩子 而这些孩子也正在 练习书写数字 所以我们想为什么不让 他们直接在屏幕上画呢 要做到这一点 我们需要让我们的 App 能识别手写数字
幸运的是机器学习已经在 解决这一问题上 做得足够好 事实上这里有一个完整的 数据集可供你训练 自己的模型来 识别手写数字 这一模型被称为 MNIST
我们做到了这一点 我们将它放在 Core ML 模型页面上
那么让我们看看如何 在代码中使用这个模型 我们将使用 Vision 和 PencilKit 框架 设置 Vision 来使用 Core ML 模型 在这里的模型是 MNISTClassifier 接下来我们从 PencilKit canvasViiew 中获取图像 这样我们设置好 Vision 请求处理器 使用该图像
接下来我们执行请求 并得到结果 就是这么简单
所以我们将它集成到我们的模型中 它开始工作得非常好 我们识别了不少 手写的数字
但当我们书写的 数字变大时 我们发现了一些很有趣的东西 我们的模型有时候 会得到错误的预测结果 所以发生了什么 要理解这一点 我们需要查看输入到模型里面的图像 我们可以在 Xcode 里做到这一点
于是我们设置一个 从 PencilKit 中获取图像的断点 然后我们使用 Xcode 的快速预览 来查看实际图像到底是什么 当我们完成这些时 我们看到了一些有趣的东西 示例中的 7 对于模型来说 并不像 7 而是更像 1 那么这里发生了什么 我们需要考虑模型 对于输入的期望
这个模型期望一个 28 乘以 28 像素的图像 但我们在屏幕上 绘制的数字比这个大得多
所以要获得正确格式的图像 我们需要缩小输入 但当我们缩小它时 就丢失了屏幕上 绘制的笔画的信息 因此我们的 7 开始看起来 更像 1 当我们知道了这一点 修复这个问题就变得简单 我们需要用更粗的笔画 这样的话 我们输入到模型的图像 就更接近于我们在屏幕上 书写的图像 并且此时模型预测出来 的结果也变得更加正确
PencilKit 让这一点变得很容易
在这里我们将 allowsFingerDrawing 设置为真 因为我们用手指在屏幕上书写 然后我们将工具设置为 具有更粗笔画的马克笔
好了 我们的模型现在
可以很好地识别单个数字 但我们还有别的一些挑战 一些数字是以 多个笔画进行书写的 我们的模型提取数字 的静态图像信息 而不是关于该数字的笔画信息
那么我们如何知道何时 提取屏幕上书写的信息 并将信息输入到我们模型中 进行预测呢 此外由于我们要对骰子的示数 进行加法或乘法 我们可能要处理多位数字 而我们的模型只被训练 用于识别单个数字 而非多位数字 那么我们如何处理这样的情况 我们可以用机器学习 来解决这些问题 我们可以训练一个模型 来识别关于数字的笔画信息 或者我们可以训练 一个模型去识别 多位数字 但我们已经知道了 很多关于屏幕上书写内容的信息 所以我们不使用机器学习 而是使用程序的方法解决这一问题 让我来向你演示如何做到 我们来看看这个例子吧
有人在屏幕上绘制 1 的第一个笔画 我们把它作为一个图像 传递给我们的模型并得到预测结果 这个结果就是 1
接下来他们绘制 1 的底部横线 我们看看之后的笔画 是否与前一个笔画重叠 因为发生重叠 所以我们知道 这是同一个数字 于是我们扔掉第一次预测的结果 将第一画与第二画 结合成同一个图片 并将结合后的整张图片 输入给我们的模型 预测的结果为 1 接下来用户在屏幕上 书写了新的笔画
我们将关注第三个笔画 查看其是否与前两个笔画中的 任何一个重叠 因为没有重叠 我们知道它是一个单独的数字 所以我们将它单独传递给模型 并且预测它是 2 现在我想邀请 Scott 回来 在 App 中向你们展示 Scott 感谢 Brent 现在我们的 App 更新了 它仍然保留对象探测器 用来检测骰子 和分类骰子上的值 但我们还在上面添加了 如 Brent 前面所说的 识别手写输入的功能
所以我觉得是时候做一些计算了
在这里用户可以选择将 骰子的示数 相加或相乘 所以为了简单起见 我将从加法开始 那么让我们看看输入处理 是如何工作的 对了
那么如果我们将这些值相乘 我很确定会得到 24
这是一个有趣的数字 我希望你密切关注 当我在屏幕上画 4 时 发生了什么
如果你考虑使用 两个笔画书写 4 那我们的模型在只看到 第一个笔画时 将很难识别出 4 所以它可能会预测为其他数字 直到我书写第二个笔画
我们来看一下
你是否注意到了 这里的 4 的第一画被识别成 1 但当我书写了第二画时 预测的结果立即变成了 4 有一个答案被设置为 始终正确 我只是想向你们展示更多的 4 让我们一起来看看
很好 所以我们的 App 可以 识别桌面上的骰子 理解掷骰子行为 检查计算结果 我们可以在屏幕上 绘制数字作为输入 但我们谈论的是将现实世界 和虚拟世界进行融合 所以我们认为 如果孩子们在玩游戏的时候 可以以语音的形式 输入他们的答案 那将会很有趣并且交互性很强 那么让我们来看看 再一次我要将这两个数 运算来得到 24 然后让我们用语音来做
24 酷
使用 Speech 框架 让这一点变得非常容易 今年我们在语音方面 添加了离线语音识别 这意味着即使你的设备 未连接到互联网 语音识别也可以 在你的 App 中使用
如果你希望将用户的数据 保留在他们的设备上 你实际上可以通过 将语音识别器中的 requiresOnDeviceRecognition 设置为 true 来要求 在设备上进行语音识别
所以现在我们的 App 可以理解 掷骰子行为 并处理不同的输入形式 但我们需要继续我们的旅程 并完成任务 所以我想欢迎 Brent 重返舞台 感谢你 Scott
正如 Scott 所说 我们的 App 可以识别骰子 并且我们知道如何处理用户的输入 但我们说这是一个游戏 对吧 为了做到这一点 接下来我们将整合 ARKit 真正完成整个体验 当然任何游戏都需要规则 所以让我们先来看看规则
我们的比赛是在一个 分成九份的圆形板上进行的 每个玩家从第一部分开始 目标是围绕棋盘 顺时针移动 并刚好停在第九部分 掷的数太小 会让你走的不够远
掷的数太大 你就会越过你的目标 在每个玩家的回合中 他们掷骰子并且有两个选择 他们可以取 骰子的和 并沿顺时针方向移动该数字 或者他们可以取 骰子顶部数字的差 并沿顺时针方向移动该数字
那么 Scott 你想要来比一比吗
那么现在我们将 虚拟棋盘集成到 ARKit 游戏中 并且利用 Core ML 来识别骰子 由 Brent 你来开始怎么样 听上去不错 好的 5 我掷到的数是 5 和 2 很好 我认为我应该把这些数字加起来
很好 噢你已经接近终点了 很接近了
那么我掷了 6 和 1 我可以将数字相减得到 5 或者将其相加与 Brent 在 8 会合 让我们把这些数加起来
很好 我不认为 我会掷出 1 让我们来看看 这次我要做减法 得到的是 2
好吧我再次掷出 6 和 1 这一次我也做减法 然后用它们得到 5 Brent 认为
我画的 5 很好笑 你知道这个游戏可能 会持续非常长的时间 我认为 Scott 已经提到了 一个始终正确的数字 接下来让我们看看 这个数字在游戏里是否奏效
Brent 你发现了秘密 干得好 成功了
很好 我们将多种技术结合在一起 以将我们的物理 和虚拟世界融合
我们建立了超越 任何单一技术的体验 它让我们在这个增强的新世界中 玩这个有趣的游戏
我们使用对象检测 来识别桌子上的骰子 我们使用图像分类 来识别屏幕上的手写数字
我们使用语音识别作为 与我们的 App 互动的另一种方式 我们引入了 ARKit 来真正完成整个体验
如果你想了解更多信息 请参阅开发者网站上的 228 号会议 或明天在实验室与我们联系 感谢各位 并祝各位能够享受余下的会议 [鼓掌]
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。