metal的基础知识入门,首推Metal By Example系列:http://metalbyexample.com/。博主的相关文章,主要给出工程实际遇到的典型问题及其解决方案。

本节源码:https://github.com/sjy234sjy234/Learn-Metal/tree/master/TrueDepthStreaming。从第7节开始,渲染统一采用该节介绍的工程化渲染框架:https://blog.csdn.net/sjy234sjy234/article/details/82497799。

这一次,主要介绍两个内容:1)iphone X的真实感深度相机调用,获取实时深度帧;2)利用metal的通用计算kernel核函数将深度帧可视化为纹理。如图所示,是实时获取的彩色帧和深度帧的可视化效果。注意这个项目只能在iphone X平台上才可以运行,目前只有iphone X支持真实感深度相机。

1、iphone X的真实感深度相机调用:

参考博主封装的FrontCamera类,要获取最高的深度图像帧率,需要设置如下:

    if(isDepthEnabled){[self.avCaptureSession setSessionPreset: AVCaptureSessionPreset640x480];self.videoDevice=[AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInTrueDepthCamera mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionFront];}

这里的preset,有一些支持深度,有一些不支持深度。但是只有AVCaptureSessionPreset640x480支持最高的帧率和最大的深度利用率。但是这个设置下,得到的彩色帧的分辨率也只有640x480,可以尝试用其他的preset。调用真实感深度相机的主要坑点是在AVCaptureDeviceTypeBuiltInTrueDepthCamera这个配置上,当时没有搜到demo,博主自己尝试出来的。其余的AVCaptureSession、AVCaptureVideoDataOutput、AVCaptureDepthDataOutput、AVCaptureDataOutputSynchronizer这些都非常常规,而且iphone双摄支持深度图像,官方有demo可以参考的。

2、metal通用计算GPGPU的kernel函数

对于从相机获取的彩色帧,直接调用VideoRenderer类进行纹理的渲染即可,里面封装了TextureRendererEncoder。而对于深度帧,是不能直接进行纹理渲染的,DepthRenderer类里面封装了DisparityToTextureEncoder和TextureRendererEncoder。首先,在DepthRenderer中,把深度帧转化为16进制的id<MTLBuffer>,作为kernel函数的输入:

id<MTLBuffer> inDisparityBuffer = [_metalContext bufferWithF16PixelBuffer: depthPixelBuffer];

然后调用DisparityToTextureEncoder类,把id<MTLBuffer>格式的深度帧转化为可视化的纹理id<MTLTexture>,这里实现了一个非常简单的GPGPU的kernel函数的封装,首先是encode函数:

- (void)encodeToCommandBuffer: (id<MTLCommandBuffer>) commandBuffer inDisparityBuffer:(const id<MTLBuffer>)inDisparityBuffer outTexture: (id<MTLTexture>) outTexture
{if(!commandBuffer){NSLog(@"invalid commandBuffer");return ;}if(!inDisparityBuffer){NSLog(@"invalid disparity buffer");return ;}if(!outTexture){NSLog(@"invalid out texture");return ;}const NSUInteger width = 8;const NSUInteger height = 8;const NSUInteger depth = 1;_threadgroupSize = MTLSizeMake((width), (height), depth);_threadgroupCount.width  = (outTexture.width  + _threadgroupSize.width -  1) / _threadgroupSize.width;_threadgroupCount.height = (outTexture.height + _threadgroupSize.height - 1) / _threadgroupSize.height;_threadgroupCount.depth = depth;id<MTLComputeCommandEncoder> computeEncoder = [commandBuffer computeCommandEncoder];[computeEncoder setComputePipelineState:_computePipeline];[computeEncoder setBuffer: inDisparityBuffer offset:0 atIndex:0];[computeEncoder setTexture: outTexture atIndex:0];[computeEncoder dispatchThreadgroups:_threadgroupCountthreadsPerThreadgroup:_threadgroupSize];[computeEncoder endEncoding];
}

encode函数中,首先根据纹理尺寸,配置kernel的thread group size和thread group count,然后分配computeEncoder(这里区别于渲染时分配的renderEncoder),并对其进行程序编码。然后是DisparityToTextureEncoder.metal文件中的kernel函数:

#include <metal_stdlib>
using namespace metal;// disparityToTexture compute kernel
kernel void
disparityToTexture(constant half*  currentDisparityBuffer  [[buffer(0)]],texture2d<float, access::write> outTexture [[texture(0)]],uint2  gid         [[thread_position_in_grid]],uint2  tspg        [[threads_per_grid]])
{uint invid = gid.y * tspg.x + gid.x;half inDisparity = currentDisparityBuffer[invid];half inDepth = 1.0 / inDisparity;float4 outColor = {inDepth, inDepth, inDepth, inDepth};outTexture.write(outColor, gid);
}

这里,tspg是整个kernel的size,等于输入帧的尺寸。gid是当前执行线程在kernel中的位置,用于数据的重定位。在这个kernel中,gid即纹理坐标,但是对于MTLBuffer来说,不能用纹理方式读取数据,只能用重新计算的方式定位,它们在内存中是行优先存储的,有重定位计算式 —— invid = gid.y * tspg.x + gid.x。

在调用完DisparityToTextureEncoder类得到可以渲染的可视化纹理以后,再调用TextureRendererEncoder类进行视图渲染即可。

PS:

(1)说tspg等于输入帧的尺寸是不准确的,只有输入帧的尺寸整除thread group size的时候这才是成立的,实际上tspg等于thread group size * thread group count。但在这个demo中是成立的,因为输入帧的尺寸是640x480,可以整除8。因此这个DisparityToTextureEncoder只支持分辨率尺寸能整除8的帧作为输入,否则需要修改kernel的重定位算式。

(2)iphone X获取的实时深度帧是以float16的格式存储的,并且存储的值叫做disparity,它的单位是(1/m),因此换算成深度值是:inDepth = 1.0 / inDisparity。

(3)metal的GPGPU计算,和其他语言的GPGPU是相似的,如Cuda,可以学习Cuda进行入门。Metal的学习资料比较有限,基本上只能靠查官方文档,并且官方文档也有一些过时,有时靠自己试错。

学习ios Metal(9)—iphone X真实感深度相机True Depth Camera的调用和metal GPGPU相关推荐

  1. 谈谈基于深度相机的三维重建

    三维重建(3D Reconstruction)技术一直是计算机图形学和计算机视觉领域的一个热点课题.早期的三维重建技术通常以二维图像作为输入,重建出场景中的三维模型.但是,受限于输入的数据,重建出的三 ...

  2. 基于深度相机的三维重建技术

    /*************************************************************************************************** ...

  3. 升级iOS 15后iPhone相机无法正常使用怎么办?

    iOS 15发布已经有一段时间了,相信不少果粉已经将设备更新到iOS 15.升级iOS 15后,iPhone相机是否无法正常工作? 如果你遇到相机无法正常打开.在加载时显示黑屏.镜头模糊或应用闪退等问 ...

  4. 【深度相机系列四】深度相机分类之结构光法

    说明:文中所举例的产品比较早,读者把重点放在学习原理上就好. 一.结构光法:为解决双目匹配问题而生 上一篇<[深度相机系列三]深度相机分类之双目立体视觉法>中提到基于双目立体视觉的深度相机 ...

  5. 大盘点!国内外深度相机汇总

    作者丨凳子花❀@CSDN 来源丨https://blog.csdn.net/qq_42759162/article/details/123519276 编辑丨3D视觉工坊 读前须知 本文只是学习笔记, ...

  6. 【深度相机系列五】深度相机分类:TOF、RGB双目、结构光比较

    说明:文中所举例的产品比较早,读者把重点放在学习原理上就好. 目前的深度相机根据其工作原理可以分为三种:TOF.RGB双目.结构光. 一.三种相机的参数对比 从分辨率.帧率.软件复杂度.功耗等方面来考 ...

  7. 深度相机原理和优势对比

    目前的深度相机根据其工作原理可以分为三种:TOF.RGB双目.结构光 TOF简介 TOF是Time of flight的简写,直译为飞行时间的意思.所谓飞行时间法3D成像,是通过给目标连续发送光脉冲, ...

  8. 深度相机分类:TOF、RGB双目、结构光 对比分析

    目前的深度相机根据其工作原理可以分为三种:TOF.RGB双目.结构光 一.RGB双目 RGB双目相机因为非常依赖纯图像特征匹配,所以在光照较暗或者过度曝光的情况下效果都非常差,另外如果被测场景本身缺乏 ...

  9. ROS进行深度相机的标定

    前言 自己使用标定板对深度相机进行标定. 参考:http://wiki.ros.org/camera_calibration/Tutorials/MonocularCalibration 一.准备标定 ...

最新文章

  1. TODO: ping和telnet
  2. VC6解决托盘菜单不消失
  3. 【视频】详解HDFS的HA高可用原理
  4. std::thread 不 join
  5. [团队项目3.0]Scrum团队成立
  6. 如何使用1Password,Authy和Privacy.com外包您的在线安全性
  7. mathematica在linux上运行,Mathematica在Ubuntu中的表现及修正
  8. LeetCode 1353. 最多可以参加的会议数目(排序+贪心,优先队列,难)
  9. js本页导出Excel,下载
  10. 自学python怎么转行_没有基础的想转行学习Python怎么学
  11. python 3.8.0版本的skimage库是什么_python的skimage库 图像读取显示
  12. 【IT】Asp.Net MVC
  13. windows和linux通过网线连接,用网线连接Windows和Linux台式机,并实现Linux共享Windows的WiFi网络...
  14. Mybatis原理解析(三)--getMapper动态获取接口实现类
  15. python简易病毒制作
  16. 中秋祝福代码,中秋快乐代码,采用H5制作的中秋动画祝福
  17. 2017河南省第四届互联网大会圆满落幕 云计算大数据创新成热点
  18. 实现JSON在线美化(格式化)、JSON转CSV、CSV转XML工具-toolfk程序员工具网
  19. 《雍正皇帝》文化专有词泰译研究(选题缘由)
  20. 阿里智能运维平台的演进:从自动化到无人化(附PPT)

热门文章

  1. 线性方程组在计算机方面的应用,在线性方程组的简单应用》(安顺学院数学和计算机科.doc...
  2. 超宽带 DW1000 API --- dwt_configure (频道,脉冲重复频率,数据速率等)
  3. Ubuntu 配置亚马逊 aws cli 上传文件文件夹至 亚马逊 AWS S3
  4. 图解在EXCEL中,通过身份证自动获得出生日期和性别。
  5. SC-Lego-LOAM解析(下)
  6. 麒麟电脑linux微信版本过低,Ubuntu安装微信,解决deepin“版本过低”或NO_PUBKEY问题...
  7. java性能调优(转载)
  8. 适合打游戏用的蓝牙耳机有哪些?吃鸡无延迟的蓝牙耳机推荐
  9. 二级计算机vf里的sql,计算机二级考试vf常用sql语句
  10. 树莓派sensehat画图游戏 Etch a sketch