iPhone摄影中的深度捕捉(WWDC2017-Session 507)
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 { http://www.wmyl11.com/ get } /* 'hdep' */
public var kCVPixelFormatType_DepthFloat32: OSType { get } /* 'fdep' */
1
2
3
4
1
2
3
4
像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 }
7
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 http://wanmeiyuele.cn AVDepthData {
public enum Accuracy: Int {
case relative
case absolute
因此 AVDepthData 有一个精度的概念。绝对值的精度值意味着单位确实反映了现实世界的距离,没有校准问题。相对精度意味着Z排序仍然保留,但是现实世界的尺度已经丢失。从第三方摄像机获取的深度数据可以报告为绝对或相对,但由于刚刚提到的校准错误,iPhone 7 Plus总是报告相对精度。
相对精度并不是坏的精度。双摄像头的depth完全可以使用。
Streaming Depth http://wmylpt.com Data
AVCamPhotoFilter
Introducing AVCaptureDepthDataOutput
AVFoundation 框架相机捕获类分为三大部分。第一个是 AVCaptureSession,仅仅是个控制对象。你可以告诉它开始或者停止运行,它不做任何事情,除非给它一个输入,比如 AVCaptureDeviceInput ,这里与双摄像头的设备关联,并且给session提供输入。然后需要一个输出,这里是一个新的输出类型 AVCaptureDepthDataOutput,它的功能类似于 VideoDataOutput,除了提供 CoreMedia 示例缓冲区之外,它提供了 AVDepthData 对象。
只有双摄像头才能支持 AVCaptureDepthDataOutput。
将 DepthDataOutput 附加到会话中时,双摄像机自动缩放到2倍,即长焦的全部视野,这是因为为了计算视差,焦距必须相同,而在2倍变焦下,广角摄像机的焦距与长焦相匹配。在计算深度时缩放是被禁用的。
苹果已经向 AVCaptureDevice 添加了一些新的访问器。在双摄像头上,您可以通过查询 supported www.caihonyule.com DepthDataFormats 属性来发现哪些视频格式支持深度。
还有一个新的 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
1
1
非同步数据输出
现在有四种数据输出:
第一个是 VideoDataOutput ,从iOS 4开始,它是以30 fps或60 fps的流媒体方式一次给出视频帧。 还有一个 AudioDataOutput,通常会以44.1的速度一次推送1024个PCM帧。 还有一个 Me www.yule8766.com tadataOutput 可以提供面部,检测到的面孔或条形码,并且这些都偶尔出现。 他们可能会有一些延迟,寻找面孔多达四帧延迟。
第四个就是 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 {
// ...
}
}
}
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
可以像数组一样使用它,也可以像字典那样使用它,具体取决于要做什么。
func dataOutputSynchronizer(_ synchronizer: AVCaptureDataOutputSynchronizer, didOutput synchronizedDataCollection: AVCaptureSynchronizedDataCollection) {
// Use dictionary-esque subscripting to find a particular data
if let synDepth = synchronizedDataCollection[self.ddo] as? AVCaptureSynchronizedDepthData {
// ...
}
}
1
2
3
4
5
6
1
2
3
4
5
6
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数据类型。
Capturing Photos with Depth
AVCam是显示如何使用 AVFoundation 拍摄照片和电影的示范代码。
注意,虽然已经添加了深入支持,但是你看不到任何depth相关的东西。因为当能够拍摄这些铅笔时,实际上并没有看到深度的表现,而是存储在照片中。
照相结束后,打开相册后编辑,上面有了景深的按钮,可以对景深做效果处理。在iOS 11中,以人像模式拍摄的所有照片现在都会在照片中存储深度信息,因此它们会为您的新创意应用程序添加素材。
Photos with Depth
当拍摄深度照片时,支持很多的捕获选项。
iPhone摄影中的深度捕捉(WWDC2017-Session 507)的更多相关文章
- ASP.NET MVC 项目中 一般处理程序ashx 获取Session
1-在 aspx和aspx.cs中,都是以Session["xxx"]="aaa"和aaa=Session["xxx"].ToString( ...
- 如何在视频处理控件TVideoGrabber中设置音频捕捉设备
TVideoGrabber不仅可以捕捉视频,还可以作为多媒体播放器,并支持包括C#..NET.VB.NET.C++.Delphi.C++Builder和ActiveX平台,本文将剖析TVideoGra ...
- 要在一般处理程序中获取其他页面的session值
1.要在一般处理程序中获取其他页面的session值,需要引用名空间: using System.Web.SessionState; 2.然后继承一个接口:IRequiresSessionState, ...
- iPhone开发中的技巧整理
1.NSCalendar用法 -(NSString *) getWeek:(NSDate *)d { NSCalendar *calendar = [[NSCalendar alloc] initWi ...
- Kakfa揭秘 Day4 Kafka中分区深度解析
Kakfa揭秘 Day4 Kafka中分区深度解析 今天主要谈Kafka中的分区数和consumer中的并行度.从使用Kafka的角度说,这些都是至关重要的. 分区原则 Partition代表一个to ...
- OpenGL中的深度、深度缓存、深度测试及保存成图片
1.深度 所谓深度,就是在openGL坐标系中,像素点Z坐标距离摄像机的距离.摄像机可能放在坐标系的任何位置,那么,就不能简单的说Z数值越大或越小,就是越靠近摄像机. 2.深度缓冲区 深度缓冲区原理就 ...
- iPhone应用中如何避免内存泄露?
如何有效控制iPhone内存管理的对象的所有权与引用计数和以及iPhone内存的自动释放与便捷方法.本文将介绍在iPhone应用中如何避免内存泄露.想了解“在iPhone应用中如何避免内存泄露”就必须 ...
- iphone开发中数据持久化之——属性列表序列化(一)
数据持久化是应用程序开发过程中的一个基本问题,对应用程序中的数据进行持久化存储,有多重不同的形式.本系列文章将介绍在iphone开发过程中数据持久化的三种主要形式,分别是属性列表序列号.对象归档化以及 ...
- android中全局异常捕捉
android中全局异常捕捉 只要写代码就会有bug,但是我们要想办法收集到客户的bug.有第三方bugly或者友盟等可以收集.但是,android原生就提供了有关收集异常的api,所以我们来学习一下 ...
随机推荐
- spring学习-1
spring框架的组件结构图 IOC(Inversion of Control):反转控制,思想是反转资源获取方向,传统的资源查找方向是组件向容器发起请求资源查找,作为回应,容器适时的返回资源,IOC ...
- codeforces 655D D. Robot Rapping Results Report(拓扑排序+拓扑序记录)
题目链接: D. Robot Rapping Results Report time limit per test 2 seconds memory limit per test 256 megaby ...
- codeforces 632B B. Alice, Bob, Two Teams(暴力)
B. Alice, Bob, Two Teams time limit per test 1.5 seconds memory limit per test 256 megabytes input s ...
- 08 - Django应用第五步
1 自动测试 自动测试与测试的不同在于, 自动测试的测试工作是交给系统完成的 测试也有分类和级别, 有的用于一些细微的细节, 有的是针对整个软件整体 测试会保证一些看起来正常运行的功能在实际的多种情况 ...
- H264 NALU 使用PS封装 RTP发送
最近由于项目平台需求,要将H264 NALU封装为PS再用RTP发送,PS封装按照ISO DEC-13818-1标准.一个PS包包含PS Header, PES Header, PS system h ...
- bzoj 3165: [Heoi2013]Segment 线段树
题目: Description 要求在平面直角坐标系下维护两个操作: 在平面上加入一条线段.记第i条被插入的线段的标号为i. 给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. ...
- Codeforces Round #402 (Div. 2) 阵亡记
好长时间没有打Codeforces了,今天被ysf拉过去打了一场. lrd也来参(nian)加(ya)比(zhong)赛(sheng) Problem A: 我去,这不SB题吗.. 用桶统计一下每个数 ...
- IDEA发布运行web项目(曾经遇到的项目启动报404)
问题: 配置: 配置 facets ,此步很重要,配置 web resource directories ,路径配错,就会报 404 ,一定要定位到项目根目录,也就是下面有整个项目源码的地方 下面是配 ...
- Access中复制表
很多时候在Access中需要复制表,或只复制结构,源表名:a: 新表名:b (经测试中Access可用) 法一:select * into b from a where 1<>1 ...
- 经过一年时间的沉淀 再次回首 TCP Socket服务器编程 (二)
------------------ 前言 ------------------ 发了第一篇文章后,有不少同志留言,看来socket编程仍然是软件系统里面一个比较难的部分. 第一篇文章主要介绍了传输协 ...