iOS 开发者的 Metal 养成计划「7」 —— Metal Performance Shaders 和滤镜原理

发布于:2018-03-11 18:46,阅读数:1065,点赞数:0


# 引言 本文是本系列的最后一篇文章,来简单讲一讲苹果提供的另一个官方工具库:`Metal Performance Shaders(MPS)`。 由于 MPS 本身除了应用于图形处理处理外,由于官方提供了卷积神经网络的内核,因此还被广泛用于机器学习中。 # Metal Performance Shaders > Add low-level and high-performance kernels to your Metal app. Optimize graphics and compute performance with kernels that are fine-tuned for the unique characteristics of each Metal GPU family. 这是一个经过优化的着色器程序库。 ## 图像处理 在之前的文章中,我们并没有用着色器去处理像素,只用它来读取像素并显示在屏幕上。那么对于图像处理,最基础的就是将纹理的颜色读出来,然后什么都不处理就返回。其实在这一步,可以实现许多图像处理环节。 接下来将以滤镜这一常见的图像处理为例简单地介绍下图像处理的概念。 滤镜是一种颜色变换的处理方式。 ![](//cdn.blog.yuusann.com/img/corpus/18011_1.jpg) 滤镜常见的有两种实现方式:**矩阵变换**和**核卷积**。 #### 矩阵变换 图像的颜色值是一个四维的向量,那么滤镜的实现可以看做是一个四维矩阵。四维向量乘上这个变换矩阵,最后的结果也是一个四维向量,看做是输出颜色。 ![](//cdn.blog.yuusann.com/img/corpus/18011_2.jpg) 而在 Metal 的着色器程序中是支持向量运算的,因此可以像做整数乘法一样,直接使用采样器中取得的颜色值乘上一个滤镜矩阵,将结果返回即可。 具体实现大概是这样的: ```cpp fragment half4 fragment_texture(VertexOut fragmentIn [[stage_in]], texture2d<float, access::sample> tex2d [[texture(0)]], sampler sampler2d [[sampler(0)]]) { float2 texCoords = fragmentIn.texCoords; float4x4 mat = { /* 定义变换矩阵 */ }; float4 texColor = tex2d.sample(sampler2d, texCoords); return half4(texColor * mat); } ``` 在视频相关的项目中,由于视频硬解码返回的数据一般是`YUV`颜色格式的,而无论是图像显示还是图像处理,一般使用`RGB`格式。那么`YUV`转`RGB`这一步操作可以使用着色器去实现。转换矩阵可以在网上查到,直接使用着色器进行转换,效率上可以超过 CPU 转换几个数量级。 #### 核卷积 笔者第一次接触`卷积`这个词是在信号相关课程中,卷积也广泛应用在图像处理领域。如果读者对这个词感到陌生,也无大碍,我们举个具体的例子讲。 `高斯模糊`是一种常见的平滑算法。那么它的原理就是用一个指定的`高斯卷积核`,对原始图像进行卷积。高斯卷积核是一个十字形结构,其中每个数代表了这个像素点的权重。 ![](//cdn.blog.yuusann.com/img/corpus/18011_3.jpg) 在输入图像中创建一个滑动窗口,对每一个窗口中的像素点以高斯核的权重进行`加权平均`后的结果就是该像素点的颜色值。由于每个点的颜色值是周围几个像素的加权平均数,因此起到了高斯模糊起到了平滑的作用,在图像上最直观的感受就是图像变模糊了。 #### MPS 能为我们做些什么 以滤镜的例子来说,其实常规的滤镜就那么几种,算法也大同小异,因此 MPS 为我们准备好了一系列滤镜的着色器供开发者直接使用。MPS 中所有核函数有一个共同的基类`MPSKernel`,根据算法需要一个输入还是两个输入,从中再派生出两个子类:`MPSUnaryImageKernel`和`MPSBinaryImageKernel`。 例子中的高斯模糊,MPS 给开发者提供了`MPSImageGaussianBlur`,由于高斯模糊只有一个输入图像,因此它继承于`MPSUnaryImageKernel`。使用方法很简单: ```swift let filter = MPSImageGaussianBlur.init() filter.encode(commandBuffer: ..., sourceImage: ..., destinationImage: ...) ``` 直接将核函数与一个 `MTLCommandBuffer` 编码即可。 ## 神经网络 在 MPS 中存在着`卷积神经网络`(以`MPSCNN`开头)和`循环神经网络`(以`MPSRNN`开头)的工具类。 由于本系列主要讲图像相关的内容,因此 Metal 在神经网络方面的应用暂时不做展开,有兴趣的读者可以自己查阅官方文档。 # 小结 MPS 中内置的工具类可以进一步减少开发者重复开发常用着色器函数的工作,从而更加专注地进行业务开发。 至此,本系列文章就将暂时告一段落了,欢迎在评论中留下微信号,加入读者群交流。


评论:0条


返回列表

返回主页