iPhone 摄影中的深度捕捉 ( WWDC2017-Session 507 ) 上篇

导语

iPhone 7 Plus上的人像模式展现了摄影深度的强大功能。 在iOS 11中,驱动此功能的深度数据现在开放使用。 了解如何利用深度信息为创意成像开辟新的可能性。 获得对高层次深度概念的更广泛的了解,并学习如何从相机中捕获流式传输和静态图像深度数据。

视频地址,只能用safari观看

前言

507是深度媒体相关的概念层面的内容。主要为下面4个部分:

  • Depth and disparity on iPhone 7 Plus
  • Streaming depth data from the camera
  • Capturing photos with depth data
  • Dual photo capture

Depth and disparity on iPhone 7 Plus

7 Plus 有两个摄像头,28毫米的广角摄像头,56毫米的长焦镜头。它们都是1200万像素,分享同样的配置项、格式。可以单独使用它们,也可以用一个虚拟的第三方摄像头来共同使用它们,使它们配合。它以同步的方式运行,相同的帧速率,并且一起运行它们可以实现两个选框功能。

Dual Camera Zoom 双摄变焦

  • Switches between wide and tele automatically
  • Matches exposure, focus, and frame rate
  • Compensates for parallax shift to smooth the transition
  • 在缩放时,会自动切换广角与长焦;
  • 适配曝光、对焦和帧速率;
  • 对视差偏移进行补偿,使其在广角和长焦之间来回切换时平滑过渡。

Portrait Mode

人像模式锁定在长焦摄像头,但是会同时使用广角和长焦来生成一副浅景深效果的图像。聚焦的前景清晰,背景则会逐渐模糊。

iOS11 上改进了对焦区域的渲染。更准确的展现了一个自由度高的快速镜头,例如上图中清晰明亮的花束圈。还改进了前景和背景边缘的渲染。

为了生成这样效果的图片,就要有能力区分前景和背景,也就是需要depth。在iOS10,depth信息还只是包含在苹果自己相机的人像模式中。iOS11,苹果正在向第三方应用开放depth map。

上面这幅图中内嵌了下面这样一个灰度可视化的深度图:

深度信息有了对图像编辑更多的可能性,例如上图对前景和背景应用不同的滤光器;将黑白滤光器应用到背景,Fade Filter应用到前景。

也可以像上图,将前景的范围缩小到手和花。

还可以对前景和背景应用不同的曝光

Deep Learning

Depth Map

首先定义depth map。真实世界中depth 意思是你和观察物体之间的距离。深度图是将三维场景转化为二维表示,并将深度设置为恒定距离。

下面对针孔相机做一点研究:

针孔相机是一个没有镜头的简单的防光盒,观察物体通过一个孔映射到传感器上。

光线通过的孔被称为焦点,聚焦到成像平面的距离就是焦距,物体在成像平面上的缩放程度就取决于焦距。较短的焦距意味着更宽的视野;而更长的焦距,较长的盒子意味着较窄的视野。

简单来说,深度图是将3D深度转换为2D,单通道图像,其中每个像素值是不同的深度,如五米,四米,三米。

为了真正测量深度,需要一个专用的摄像头,比如飞行时间相机。例如,一个系统,它从物体反射光信号,然后测量返回到传感器所需的时间。

iPhone 7双摄像头不是飞行时间相机。相反,它是一个基于Disparity的系统。

Disparity

Disparity 是从两个不同的摄像机(如眼球)观测到的物体的偏移量的量度。Disparity 是视差的另一个名称。

你可以通过稳定头部并将目光固定在靠近的位置上观察此效果,然后不移动您的头部,闭上一只眼睛,然后闭上另一只眼睛。而且你可以看到彩色的铅笔看起来比后面的标记更多,因为它们更接近。这就是 Disparity效果,或者说视差效果。

现在我已经拍摄了两台被认为是立体纠正相机的鸟瞰图。意思是说,它们彼此平行,它们指向同一个方向,而且焦距是相同的,这个很重要。

每个相机将具有测量的光学中心或主要点,并且如果从针孔到图像平面绘制垂直线,则光学中心是其与图像平面相交的点。

baseline基线

基线是指立体纠正系统中透镜的两个光学中心之间的距离。 下面是它的工作原理:

来自被观察物体的光穿过光学中心,或者说穿过两个照相机的图像平面上的不同点的孔径和平台。

Z

Z是深度或者真实世界深度的规范术语

现在看看当观察点越远,图像平面上的点更加接近,同理观察点越近,图像平面上的点间隔越远。

所以当相机是立体纠正时,这些偏移只能在一个方向上移动。他们要么靠近要么远离彼此,要么在同一条线上,要么是对极线。

有了基线,可以沿着它们的光学中心排列相机,并减去图像平面上的观察点之间的距离来获得视差。一般用像素单位来表示。

但是现在对于编辑并不是很方便,如果将图像缩小,实际是改变了像素大小,然后必须在深度图中缩放每个值。

Removing Despair from Disparity

苹果选择使用对缩放操作有弹性的归一化值来表示Disparity。

这里有两个相似三角形,高亮:

现实世界的三角形边是Z,单位是米,而基线是两个光学中心之间的距离。在防光盒内,同一个三角形表示为像素中的焦距和以像素为单位的Disparity。

数学表示,并化简得到1 / z。当物体移动得更远时,视差会缩小。基线现在绑定在Disparity中了,当处理深度图时,不需要单独携带该信息。

Disparity单位1/米,它可以承受缩放操作,并且从深度到Disparity的转换很简单,只需要 1除以 这样一个操作。

Disparity vs. Depth

  • iPhone 7 Plus双摄像头系统是基于Disparity的
  • Disparity是深度的代理
  • 归一化Disparity是深度的倒数

New Term: Depth Data

Depth Data是通用术语,对于任何depthy,都可以叫depth data。可以指深度图或者视差图,因为都是深度相关的。

Introducing AVDepthData

  • 苹果的平台( iOS, macOS, and tvOS)对于深度的规范表示叫做AVDepthData。
  • 它是AVFoundation框架中的一个类。
  • 它代表深度或差异图。
  • 它还提供了一些方法,可以在深度和差异之间进行转换。
public var kCVPixelFormatType_DisparityFloat16: OSType { get } /* 'hdis' */
public var kCVPixelFormatType_DisparityFloat32: OSType { get } /* 'hdis' */
public var kCVPixelFormatType_DepthFloat16: OSType { get } /* 'hdep' */
public var kCVPixelFormatType_DepthFloat32: OSType { get } /* 'fdep' */

像RGB图像一样,除了是单通道,但它们仍然可以表示为CV像素缓冲区,现在 CoreVideo 定义了在上一张幻灯片中看到类型的四个新像素格式。因为如果是在GPU上,会要求16位的值,而在CPU上,就都是32位的值。

AVDepthData的核心属性:

@available(iOS 11.0, *)
open class AVDepthData: NSObject {
    open var depthDataType: OSType { get }
    open var depthDataMap: CVPixelBuffer { get }
    open var isDepthDataFiltered: Bool { get }
    open var depthDataAccuracy: AVDepthDataAccuracy { get }
}

Holes

由于光线,或者边缘难以分清等因素,可能会出现无法得到Disparity的点,这种点叫做holes。深度图也可能被处理来填补这些点。 可以通过基于周围深度数据进行内插,或者通过使用RGB图像中存在的元数据来实现。 AVDepthData 的 isDepthDataFiltered 属性告诉是否以这种方式处理了map。

Calibration Errors 校准错误

比如基线计算错误。

iPhone相机不是针孔,iPhone有透镜,并且它的透镜都不是固定的。

  • Optical Image Stabilization
  • Gravity
  • Focus Coil

如果使用OIS,则透镜可以横向移动来抵消手抖动。重力可以发挥作用,因为它会导致镜头下垂。聚焦致动器实际上是施加电流的弹簧。所以这些原因可能会导致它横向移动一点,而光学中心位置的这些非常小的误差可能导致Disparity的巨大误差。当发生这种情况时,结果是map中每个像素的误差是一个恒定的。 Disparity 值相对于彼此仍然可用,但它们不再反映真实世界的距离。

Depth Data Accuracy

extension AVDepthData {
    public enum Accuracy: Int {
        case relative
        case absolute 
    }
}

因此 AVDepthData 有一个精度的概念。绝对值的精度值意味着单位确实反映了现实世界的距离,没有校准问题。相对精度意味着Z排序仍然保留,但是现实世界的尺度已经丢失。从第三方摄像机获取的深度数据可以报告为绝对或相对,但由于刚刚提到的校准错误,iPhone 7 Plus总是报告相对精度。

相对精度并不是坏的精度。双摄像头的depth完全可以使用。

Streaming Depth Data

AVCamPhotoFilter

Introducing AVCaptureDepthDataOutput

AVFoundation 框架相机捕获类分为三大部分。第一个是 AVCaptureSession,仅仅是个控制对象。你可以告诉它开始或者停止运行,它不做任何事情,除非给它一个输入,比如 AVCaptureDeviceInput ,这里与双摄像头的设备关联,并且给session提供输入。然后需要一个输出,这里是一个新的输出类型 AVCaptureDepthDataOutput,它的功能类似于 VideoDataOutput,除了提供 CoreMedia 示例缓冲区之外,它提供了 AVDepthData 对象。

  • 只有双摄像头才能支持 AVCaptureDepthDataOutput。
  • 将 DepthDataOutput 附加到会话中时,双摄像机自动缩放到2倍,即长焦的全部视野,这是因为为了计算视差,焦距必须相同,而在2倍变焦下,广角摄像机的焦距与长焦相匹配。在计算深度时缩放是被禁用的。
  • 苹果已经向 AVCaptureDevice 添加了一些新的访问器。在双摄像头上,您可以通过查询 supportedDepthDataFormats 属性来发现哪些视频格式支持深度。
  • 还有一个新的 activeDepthDataFormat 属性,可以让您看到 activeDepthDataFormat 是什么或选择一个新的 DepthDataFormat。

Supported Depth Resolutions for Streaming

第一个是受欢迎的照片预设。 在照片预设中,可以从 VideoDataOutput 中获得屏幕尺寸的预览,还可以从photoOutput中获得1200万像素的完整图像。所以在这里 VideoDataOutput提供了1440x1080,这是屏幕尺寸。如果使用DepthDataOutput,可以获得24 fps,最大320x240的depthData。这么小的原因是每秒处理24次视差图已经消耗很多性能了。也可以以较低的分辨率得到它,160x120。

第二个是16x9的格式,这是今年的新格式。去年有一个720p 16x9的格式,帧率高达60 fps。今年这个新格式只有30 fps,但是支持depth。同样支持两种分辨率。

最后,有一个非常小的VGA大小的预设或活动格式,如果只是想要非常小非常快,可以使用它。

Depth Frame Rate Examples

AVCaptureDevice允许设置最小和最大视频帧速率,但不允许独立于视频帧速率设置深度帧速率。因为深度需要和视频帧率一致,或者小于视频帧率。例如,如果选择最大视频帧率为24,深度可以跟上这一点,所以得到24 fps的深度。但是,如果选择30 fps视频,则深度跟不上,不过不会选择24,而是15,倍数是比较好的选择。

DepthDataOutput支持过滤深度数据。这样就可以填满空洞,并且随着你的移动也可以比较平滑,这样就不会看到从帧到帧的时间跳跃。

open var isFilteringEnabled: Bool

非同步数据输出

现在有四种数据输出:

第一个是 VideoDataOutput ,从iOS 4开始,它是以30 fps或60 fps的流媒体方式一次给出视频帧。 还有一个 AudioDataOutput,通常会以44.1的速度一次推送1024个PCM帧。 还有一个 MetadataOutput 可以提供面部,检测到的面孔或条形码,并且这些都偶尔出现。 他们可能会有一些延迟,寻找面孔多达四帧延迟。

第四个就是 DepthDataOutput ,是以视频的帧速率或以视频均匀分割的速率传送。

如果关心同时处理所有这些数据,或者处理一定的演示时间。为了处理所有这些数据输出,您必须拥有一个非常复杂的缓冲机制,以便跟踪所有进入的时间,

Synchronized Data Output

在iOS 11中,苹果添加了一个名为 AVCaptureDataOutputSynchronizer 的新同步对象。它可以在单个统一回调中为给定呈现时间,提供所有可用数据,并传递一个称为AVCaptureSynchronizedDataCollection 的集合对象。

所以这样就可以指定一个主输出,一个最重要的输出,一个希望所有其他东西要同步的输出,然后只要它需要,就可以做这个工作, 以确保给定演示时间的所有数据在可用之前提供给单独的统一回调。它将为你提供输出的所有数据,或者如果确保没有特定输出的数据,它将继续提供与它有关的集合。

下面一个代码示例:

func dataOutputSynchronizer(_ synchronizer: AVCaptureDataOutputSynchronizer, didOutput synchronizedDataCollection: AVCaptureSynchronizedDataCollection) {
    // Iterate through an AVCaptureSynchronizedDataCollection using fast enumeration
    for syncedData in synchronizedDataCollection {
        if let syncedDepthData = syncedData as? AVCaptureSynchronizedDepthData {
            // ...
        }
    }
}

可以像数组一样使用它,也可以像字典那样使用它,具体取决于要做什么。

func dataOutputSynchronizer(_ synchronizer: AVCaptureDataOutputSynchronizer, didOutput synchronizedDataCollection: AVCaptureSynchronizedDataCollection) {
    // Use dictionary-esque subscripting to find a particular data
    if let synDepth = synchronizedDataCollection[self.ddo] as? AVCaptureSynchronizedDepthData {
        // ...
    }
}

Streaming Camera Intrinsics

iOS 11中还有一个新的流式传输功能,当使用 VideoDataOutput 时,支持每个视频帧的相机内在功能。

上面讲到针孔相机,为了将3D空间中的点转换为2D空间,需要两个信息,光学中心和焦距。在计算机视觉中,可以使用这些属性通过使用逆变换将2D图像重新投影回3D空间,这在新的AR kit中是重点。

iOS 11中的新功能,可以选择在每个视频帧中收到这样一组内在函数,通过调用 AVCaptureConnection 的 isCameraIntrinsicMatrixDeliveryEnabled 来选择。

相机内在函数是描述相机几何属性的3x3矩阵。fx和fy是像素焦距。它们是分开的x值和y值,因为有时相机具有变形镜头或变形像素。

在iOS设备上,我们的相机总是具有一致的像素,所以fx和fy总是相同的值。

x0和y0是透镜光学中心的像素坐标。

这些都是像素值,它们是以提供它们的视频缓冲区的分辨率给出的。

所以,一旦你选择了,可以期望以流式方式获取样本缓冲区,可以获得这个附件,有效载荷是一个C/F数据,它包装一个矩阵3x3浮点数,这是一个SIMD数据类型。

接《 iPhone 摄影中的深度捕捉 ( WWDC2017-Session 507 ) 下篇

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ml

HDUOJ--------1420Prepared for New Acmer

Prepared for New Acmer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 6...

2346
来自专栏量子位

AI框架之战继续:TensorFlow也用上了动态计算图

量子位 李林 | 见到“动态”有点激动 Google今天发布了TensorFlow Fold,利用动态计算图来解决因多个输入大小结构不同无法自然地批处理到一起,...

2637
来自专栏大数据文摘

如何用Python在10分钟内建立一个预测模型

1989
来自专栏AI研习社

手把手教你入门使用 tf-slim 库 | 回顾

tf-slim 是基于 tensorflow 的高层封装库,包含了目前最新的 reset-net,Google-Inception 等网络的实现及图像处理算法,...

3674
来自专栏ATYUN订阅号

告别Python,用神经网络编写的软件走向2.0时代

有时人们把神经网络称为“机器学习工具箱中的另一种工具”。有时你可以用它们来赢得Kaggle的比赛。但是,这种解释完全见木不见林。神经网络不只是另一种分类器,它们...

3555
来自专栏算法+

音频增益响度分析 ReplayGain 附完整C代码示例

人们所熟知的图像方面的3A算法有: AF自动对焦(Automatic Focus) 自动对焦即调节摄像头焦距自动得到清晰的图像的过程 AE自动曝光(Automa...

4418
来自专栏大数据文摘

确定不收藏?十张机器学习和深度学习工程师必备速查表!

1832
来自专栏专知

【下载】NLP绝佳入门经典图书《NLTK-Python自然语言处理》中英文版, 教程+代码手把手带你实践NLP算法

【导读】作为自然语言处理的经典图书教程,从输入法联想提示(predictive text)、email 过滤到自动文本摘要、机器翻译,大量的语言相关的技术都离不...

3425
来自专栏AI科技大本营的专栏

AI 技术讲座精选:利用深度学习分析医学图像

【AI100 导读】当下深度学习的研究领域仍然停留在通用图像的层面上,但我们的目标是将这些研究应用于医学图像,提升医疗保健行业的服务水平。在这篇文章中,作者会从...

2687
来自专栏专知

命名实体识别从数据集到算法实现

命名实体识别(Named Entity Recognition, NER)是 NLP 的基础任务,指从文本中识别出命名性指称项,为关系抽取等任务做铺垫。狭义上,...

1987

扫码关注云+社区