前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iPhone 摄影中的深度捕捉 ( WWDC2017-Session 507 ) 下篇

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

原创
作者头像
张耀琦
修改2017-09-20 09:29:11
3.4K0
修改2017-09-20 09:29:11
举报
文章被收录于专栏:张耀琦的专栏

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

Capturing Photos with Depth

[1505703122380_384_1505703122504.jpg]
[1505703122380_384_1505703122504.jpg]

AVCam是显示如何使用 AVFoundation 拍摄照片和电影的示范代码。

[1505703133113_1319_1505703133258.jpg]
[1505703133113_1319_1505703133258.jpg]

注意,虽然已经添加了深入支持,但是你看不到任何depth相关的东西。因为当能够拍摄这些铅笔时,实际上并没有看到深度的表现,而是存储在照片中。

[1505703142703_5375_1505703142963.jpg]
[1505703142703_5375_1505703142963.jpg]

照相结束后,打开相册后编辑,上面有了景深的按钮,可以对景深做效果处理。在iOS 11中,以人像模式拍摄的所有照片现在都会在照片中存储深度信息,因此它们会为您的新创意应用程序添加素材。

Photos with Depth

当拍摄深度照片时,支持很多的捕获选项。

[1505703156593_5404_1505703156718.jpg]
[1505703156593_5404_1505703156718.jpg]

可以使用深度进行闪光拍摄,可以静态图像稳定带深度信息。 甚至可以自动曝光括号,例如加2,减2 EV。 可以使Live Photos带有深度信息。

Capturing Photos with Depth

[1505703167678_9015_1505703167800.jpg]
[1505703167678_9015_1505703167800.jpg]

AVCapturePhotoOutput,这是去年推出的一个类,它是 AVCaptureStillImageOutput 的继承者。它处理复杂的照片请求非常出色。

编程模型是填写一个称为 AVCapturePhotoSettings 的请求,通过传递请求和稍后再调用的代理来启动照片捕获。而且photoOutput是捕获实时照片,裸RAW图像和Apple P3宽色图像的唯一界面。此外,在iOS 11中,它是捕获HEIF文件格式的唯一方法。AVCapturePhotoOutput 需要进行许多更改以支持HEIF,因此在iOS 11中,为了适应这些许多变化,添加了新的委托回调。

一个简单示例:

代码语言:txt
复制
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto
, error: Error?)

这是替代将获得示例缓冲区的回调。现在得到一个名为 AVCapturePhoto 的新对象。AVCapturePhoto 是深度唯一的传递媒介,所以如果想要深度,需要通过实现这个新的代理回调来操作。

Requesting Depth with Photos

[1505703189667_2390_1505703189808.jpg]
[1505703189667_2390_1505703189808.jpg]

此外,在开始会话之前需要明确地选择 DepthDataDelivery。它需要放大到2倍,使焦距匹配,并且需要锁定自己,禁止缩放。

开始运行会话之前,告诉photoOutput我想要 DepthDataDeliveryEnabled(photoOutput.isDepthDataDeliveryEnabled),然后在每个照片请求的基础上,这里是当你实际拍摄照片,你会填写一个设置对象,并且再一次我想在这张照片中深度(photoSettings.isDepthDataDeliveryEnabled)。

然后,可以使用产生的AVCapturePhoto,它具有一个名为 AVDepthData 的访问器。

High Res Photo Depth Maps

[1505703200689_6781_1505703200829.jpg]
[1505703200689_6781_1505703200829.jpg]

在iOS上,大多数AVCaptureDevice格式都具有比流式分辨率更高的静态图像分辨率。depth也是同理。

如果是流式深度,用实时的方式来满足24 fps,有很多工作需要做,但是如果是照片,有一点额外的时间,因为它不需要实时发送,所以可以达到非常高品质的map,超过流分辨率的两倍。

长宽比与视频的长宽比一致。

Rectilinear vs. Lens Distorted Images

捕获和嵌入照片的深度图都是畸变的。

之前展示的所有相机图是针孔相机。 针孔相机没有镜头,因此图像是直线的; 也就是说,光以直线穿过小孔,并在图像平面上呈现几何完美的复制倒置物体。

[1505703213371_810_1505703213506.jpg]
[1505703213371_810_1505703213506.jpg]

如果有一个这样的完美的正方形网格,并用针孔相机拍摄它,它将在图像平面上看起来像这样,但是颠倒的。直线会保持直线。

但是在现实世界中,需要让更多的光线进入,所以需要镜头,镜头有径向变形。这些失真也存在于捕获的图像中,因为它们以稍微奇怪的方式弯曲成图像传感器。

在极端情况下,通过不良镜头捕获的直线可能看起来像这样:

[1505703254765_3802_1505703254905.jpg]
[1505703254765_3802_1505703254905.jpg]

在比较广角和长焦图像之前,必须做一个额外的步骤:

必须使那些扭曲的图像直线化; 也就是说,使用校准的系数集合来解决它们,并且这些系数表征了镜头的失真。

Depth Map Distortions

[1505703268229_8974_1505703268368.jpg]
[1505703268229_8974_1505703268368.jpg]

现在可以确定地比较两个图像中的点,并找到一个完美的,真实的,直线的视差图,看起来像这样:

[1505703283847_1707_1505703284077.jpg]
[1505703283847_1707_1505703284077.jpg]

差距图匹配物理世界,但它与刚刚拍摄的图像不符,因为镜头有扭曲,所以现在必须做另一个步骤,就是将视差图重新映射回图像,使用一组逆透镜系数来做到这一点,最后的视差图具有与其伴随图像相同的几何失真。

[1505703300296_9288_1505703300422.jpg]
[1505703300296_9288_1505703300422.jpg]
[1505703310291_4620_1505703310424.jpg]
[1505703310291_4620_1505703310424.jpg]

这意味着开箱即用的depthDataMaps附带的照片适用于过滤器,适用于效果。不完美的是重建3D场景。 如果想这样做,应该使它们是直线的:

Depth in Image Files

简单地介绍图像文件中的深度数据的物理结构。

[1505703325363_4368_1505703325489.jpg]
[1505703325363_4368_1505703325489.jpg]

iOS 11苹果有两种图像支持深度。第一个是HEIF HEVC,新格式,也称为HEIC文件,对深度的支持是最好的。文件内有一个称为辅助图像的区域,可以存储视差或深度或透明度map,这就是存储的地方。

我们将其编码为单色HEVC,还存储对于深度工作非常重要的元数据,例如有关滤光器的信息,精度,相机校准信息(如镜头失真)以及一些渲染指令。所有这些都与辅助图像一起编码为XMP。

[1505703336415_9373_1505703336544.jpg]
[1505703336415_9373_1505703336544.jpg]

第二个就是JPEG,虽然这并不是很好的方法,但还是支持了。map是8位有损JPEG,如果它被过滤,或者如果它没有一个数字,使用16位无损JPEG编码来保存所有非数字,苹果将它作为第二个图像存储在JPEG的底部,如果你熟悉的话,它就像一个多画面对象。同样编码是XMP。

Dual Photo Capture

对于双摄像机最需要的开发者功能,双重照片捕获。

到目前为止,当使用双相机拍照时,仍然只能获得一张图像。 它是来自广角还是来自长焦,取决于缩放的位置,或者如果在1和2X之间的区域,可能会获得两者的一部分,因为苹果进行了一些混合,使得到更好的图片,但仍然只有一个。

[1505703350544_8724_1505703350696.jpg]
[1505703350544_8724_1505703350696.jpg]

现在,苹果两张图片都给了:通过单一请求,可以获得广角和长焦的全部1200万像素的照片。

Requesting Dual Photo Delivery

[1505703363286_2122_1505703363465.jpg]
[1505703363286_2122_1505703363465.jpg]

与上述的深度操作非常相似。设置两个属性 photoOutput.isDualCameraDualPhotoDeliveryEnabled , photoSettings.isDualCameraDualPhotoDeliveryEnabled 为ture。照片的回调就会给两份。

假设你要求RAW 和 HEIF双照。 那么会得到4份,因为将得到两个广角和两个长焦的RAW和HEIF。

Dual Photo Capture

[1505703376042_6610_1505703376165.jpg]
[1505703376042_6610_1505703376165.jpg]

现在,我们支持与深度相关的所有功能,可以使用双摄照片,自动SIS,曝光等级,可以根据需要选择深度。

Dual Photo Capture + Zoom

[1505703387768_9452_1505703387897.jpg]
[1505703387768_9452_1505703387897.jpg]

假设你的应用程序只显示长焦的视野。 那么广角摄像机有更多的信息,所以如果你拍照,实际上给人的可见区域以外的东西,这可能是一个隐私的关注。所以如果是缩放,苹果提供双重照片,但外部变黑,使它们与预览中看到的视野相匹配。

如果您想要完整的图像,可以不要设置缩放。

怎么知道外面是否有黑色区域?在图像内部,存储一个纯净的孔径矩形,它定义了有效像素的区域。

[1505703398167_2262_1505703398287.jpg]
[1505703398167_2262_1505703398287.jpg]

也可以使用相机校准数据传送双重照片。相机校准数据是进行增强现实,虚拟现实,镜头失真校正等需要的数据。 因此,无论是广角的还是长焦和相机校准数据,都可以制作自己的深度图。

Introducing AVCameraCalibrationData

[1505703411463_6368_1505703411617.jpg]
[1505703411463_6368_1505703411617.jpg]

相机校准的属性。AVCameraCalibrationData 是相机校准的model类。如果要求深度,可以得到一个 AVDepthData。 这就是 AVDepthData 的属性。 如果从AVCapturePhoto中选择了此功能,也可以获得该功能。 所以选择加入这个照片来说,我想用相机进行相机校准,这个照片效果很好。

如果正在进行双重照片拍摄,需要双面照片,并要求相机校准,将获得两张照片回调,并且可以获得具有广角效果的广角校准,和具有长焦效果的长焦校准。

intrinsicMatrix

[1505703423573_6268_1505703423701.jpg]
[1505703423573_6268_1505703423701.jpg]

和之前的streaming VideoDataOutput情况很相似。但是仅仅是这样深度数据的分辨率可能非常低,所以苹果又提供了一套单独的维度。通常,它们是传感器的完整尺寸,因此,您以获得很多精度,在 intrinsicMatrix 中有很高的分辨率。

extrinsicMatrix

[1505703436310_2762_1505703436430.jpg]
[1505703436310_2762_1505703436430.jpg]

extrinsicMatrix:这是描述相机在真实世界中姿势的属性。当使用从立体矫正摄像机得到的图像进行三角测量时,需要将其与另一个相比较。而外在特征被表现为一个单一的矩阵,但是两种矩阵被挤压在一起。

左边是旋转矩阵。这是一个3x3,它描述了相机相对于真实世界如何旋转。

[1505703447080_4855_1505703447191.jpg]
[1505703447080_4855_1505703447191.jpg]

还有一个1x3矩阵,描述了相机的翻转,或与世界边缘的距离。注意,当使用双摄像头时,长焦摄像机是世界的边缘,这使得它非常容易。

如果只是得到一个长焦图像,你得到的矩阵将是一个单位矩阵。 如果正在使用广角和长焦,广角将不是单位矩阵,因为它描述了与长焦镜头的姿态和距离。 但是,使用extrinsics,可以计算广角与长焦之间的基线。

[1505703458104_572_1505703458235.jpg]
[1505703458104_572_1505703458235.jpg]

这里有两个属性需要注意。一个是 lensDistortionCenter。这描述了传感器上与镜头失真中心重合的点。这通常与镜头的光学中心不同。

就像上图的扭曲,透镜上的径向扭曲像树环一样,这将是树环的中心。

同时还有一个属性是lensDistortionLookupTable,可以将其视为将 lensDistortionCenter 连接到最长半径的多个浮点数。lensDistortionLookupTable 是包含在数据中的C浮点数组。如果沿着这些虚线的每个点都是0,那么就拥有了世界上唯一一个完美的镜头,因为这就根本没有径向畸变了。

如果是正值,则表示半径有延长。如果是负值,则表示有压缩。

将整个表格整合在一起,就可以了解镜头的颠簸情况。

要对图像应用失真校正,需要以一个空目标缓冲区开始,然后逐行迭代,并且对于每个点,都使用 lensDistortionLookupTable 在失真的图像中找到相应的值,然后将该值写入到输出缓冲区中的正确位置。

[1505703471865_4160_1505703471999.jpg]
[1505703471865_4160_1505703471999.jpg]

这个是比较难实现的代码,苹果在 AVCameraCalibrationData.h 中提供了一个参考实现。实际是把代码放到了头文件里面。全都有注释。是个很大的objective C函数。它描述了如何纠正图像或如何反扭曲图像,具体取决于传给它的表格。还有一个表格的逆,它描述了如何从扭曲回到非扭曲。

Summary

[1505703484767_5601_1505703484920.jpg]
[1505703484767_5601_1505703484920.jpg]
  • iPhone 7 Plus双摄像头不是飞行时间相机系统,是Disparity系统。
  • 此外,苹果平台上对深度的规范表示是 AVDepthData。
  • 了解了intrinsics、extrinsics、lens distortion的信息。都是 AVCameraCalibrationData 的属性。
  • 了解了AVCaptureDepthDataOutput,它提供了可以过滤的流式深度。
  • 可以使用 AVCapturePhotoOutput 捕获带有深度信息的照片。
  • 最后讲到了双摄像头,双照片,对于某些计算机视觉可以单独用到广角和长焦的照片。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Capturing Photos with Depth
  • Photos with Depth
  • Capturing Photos with Depth
  • Requesting Depth with Photos
  • High Res Photo Depth Maps
  • Rectilinear vs. Lens Distorted Images
  • Depth Map Distortions
  • Depth in Image Files
  • Dual Photo Capture
  • Requesting Dual Photo Delivery
  • Dual Photo Capture
  • Dual Photo Capture + Zoom
  • Introducing AVCameraCalibrationData
  • intrinsicMatrix
  • extrinsicMatrix
  • Summary
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档