摘要: 相信绝大多数iOS开发者对CoreImage都不陌生,作为系统标配的、异常强大的图像处理库,在绝大多数场景下都能满足App的图像处理需求。加上目前CoreImage已经支持在iOS上也能做自定义filter,使得其已经成为流行的图像 ...
相信绝大多数 iOS 开发者对 Core Image 都不陌生,作为系统标配的、异常强大的图像处理库,在绝大多数场景下都能满足 App 的图像处理需求。加上目前 Core Image 已经支持在 iOS 上也能做自定义 filter,使得其已经成为流行的图像处理框架 GPUImage 最强大的竞争对手。加上 iOS12 苹果打算 deprecate OpenGL 和 OpenGL ES, 推广 Metal。那和 Metal 联系紧密的 Core Image 无疑更有胜算。 这个 Session 讲的内容主要包括三个部分:
1. Core Image 新的性能 API 中间缓存 在讲中间缓存之前,需要先复习一下 Core Image。在 Core Image 中,我们能够对图像链式的执行 Filter,如下图所示: ![]() 通过 Filter 的组合,我们可以实现一些复杂的图像处理效果。建立 Filter 链的方法可以参考如下代码( 节选自 Core Image Programming Guide ): func applyFilterChain(to image: CIImage) -> CIImage { // The CIPhotoEffectInstant filter takes only an input image let colorFilter = CIFilter(name: "CIPhotoEffectProcess", withInputParameters: [kCIInputImageKey: image])! // Pass the result of the color filter into the Bloom filter // and set its parameters for a glowy effect. let bloomImage = colorFilter.outputImage!.applyingFilter("CIBloom", withInputParameters: [ kCIInputRadiusKey: 10.0, kCIInputIntensityKey: 1.0 ]) // imageByCroppingToRect is a convenience method for // creating the CICrop filter and accessing its outputImage. let cropRect = CGRect(x: 350, y: 350, width: 150, height: 150) let croppedImage = bloomImage.cropping(to: cropRect) return croppedImage} 整个过程很直观,我们将图片喂到第一个 Filter,然后得到第一个 Filter 的 outputImage ,然后再把该对象喂到第二个 Filter……以此类推建立 Filter 链。 Core Image 的 Lazy 值得注意的一点是,当上述代码执行时,图像处理并没有发生,只是 Core Image 内部进行了一些关系的建立,只有当图像需要被渲染的时候,才会实际去执行各个 Filter 的图像处理过程。 因为有 Lazy 的特性,所以 Core Image 上最重要的一个优化就是 "自动连接(Filter Concatenation)", 因为最终图像处理的过程都发生在所有 Filter 成链之后。所以 Core Image 可以将链式的多个 Filter 合并 成一个来执行,省去不必要的开销。如下图所示: ![]() 中间缓存 现在回过头来看这样一个场景: ![]() 三个 Filter,第一个计算很耗时,而第三个的参数可以让用户手动调节。这意味着每次用户调节后都需要重新计算这三个 Filter。但其实前两份 Filter 的参数是不变的,也就是说前两个 Filter 的运算过程和结果都是不随着用户调整第三个 Filter 的参数改变而改变的。这里重复的计算是否有可能进行优化呢? 我们很容易就想到,我们只需要把前两次运算的结果 cache 下来就可以了,如下图所示: ![]() 但是上文提到,Core Image 会把 Filter 链自动合并为一个 Filter,我们如何访问中间结果呢? 苹果在 iOS12的 Core Image 中,给 CIImage 新增了一个中间缓存的属性( insertingIntermediate ), 来解决这个问题,如下图所示: ![]() 我们希望保存第二个 Filter 的结果,只需要在第二个 Filter 的 outputImage 调用 insertingIntermediate() 来生成一个新的 CIImage 传到后面的流程即可。这样第三个 Filter 的参数调整就不会导致前两个 Filter 的重复计算。 怎么做的呢? 其实就是自动合并的逻辑会根据 insertingIntermediate 进行调整。如下图所示: ![]() Core Image 的 CIContext 可以设置是否要打开 cacheIntermediate , 但这次新增的 insertingIntermediate 有更高的优先级。具体一些使用上的建议可以参考下图: ![]() Kernal 语言的新特性 两种模式 iOS 上支持自定义 Filter,自定义 Filter 使用 Kernal 语言进行开发(一种类似 GLSL 的脚本语言)。目前一共有两种开发 CIKernel 程序的模式: ![]() 第一种是传统的基于 CIKernal 开发语言进行编写,然后编译成 Metal 或者 GLSL 的方式,第二种是直接使用 Metal Shading 语言进行开发,然后在 build 期间就生成二进制的库,执行阶段 load 之后直接转换为 GPU 的指令。 目前因为苹果主推 MPS(Metal Performance Shader), 所以方式一已经被标记为 deprecated 按组读写 使用 Metal 来开发 CIKernel 的优势:
半精度浮点是纯运算性质方面的优化,在 A11芯片上运算更快,而且因为用到的寄存器小所以也有较大的优化空间。 接下来重点介绍一个按组读写。 假设我们对左图红框像素做一个3x3的卷积运算,结果为存入右边的绿色框。显而易见,对于每个新的像素,都需要读取输入图像9次像素值。 ![]() 但如果是按组读写,如下图所示。我们一次性读取16个像素来计算并写入右边的四个像素,那我们整个过程中写了4次,读取了16次。每个新像素平均需读取的数量为4,比上述的单像素需要9次显著降低。 ![]() 按组读写的原理是很简单的,接下来介绍一下如果我们有一个之前使用 CIKernal Language 开发的 kernal,如果修改使其能够使用按组读写这样高速的优化。 假设我们的 kernal 如下图所示: ![]() 第一步,转换为 metal: ![]() 第二步, 改造为按组读写的模式。核心就是使用了 s.gatherX 来实现。 ![]() 在使用了按组读写和半浮点经典的优化后,基本都可以得到 2倍 的性能提升。 2. 在 Core Image 体系上快速搭建滤镜原型 一般来讲,一个滤镜典型的研发流程是首先在电脑上进行快速原型的测试,之后再移植到生产环境,电脑上有大量的工具(OpenCV,SciPy,Numpy,Tensorflow,等等)来进行原型,而生产环境的技术栈却是 Core Image, vImage,Metal等完全不同的技术架构栈,这往往会导致一个问题:在电脑上原型测得好好的,结果到手机上效果却扑街了。 苹果为了解决这个问题,发布了一个神器 —— PyCoreImage。 ![]() 初次看到这个名词是不是感到非常穿越? 但其实很明显,就是可以在 Python 中调用 Core Image 的接口 。 我们在 prototype 的时候使用 Python + PyCoreImage 这样的方式,那就最大程度的模拟了真实的运行环境,基本上移植到手机上效果也不会打折。而且最关键的是, 只要学一个框架就好了啊,多的学不完啊!!!! 在使用 PyCoreImage 时,最关键是要了解 PyObjc 的用法,PyObjc 在 OS X 10.5 发布,实现了在 Python 可以调用 Objective-C 的代码,其中最主要的转换规则就是冒号变下划线,具体可以参考图中的例子。 ![]() 说回 PyCoreImage,其中的原理其实大概也可以想到,如下图所示,PyCoreImage 通过 PyObjC 和 macOS 的 Core Image 进行交互,并将结果输出回 NumPy。 ![]() 下图中的代码首先导入了一个图片,然后对其应用高斯模糊的 Filter,然后将结果输出到变量 bar 中。 ![]() 剩下的更多关于 PyCoreImage 的用法可以参考 Session 的 ppt,这里不再赘述。 3. 在 Core Image 体系上应用机器学习 图像处理和计算机发展至今,已经大量通过使用机器学习和深度学习来提升算法的效果。Core Image 也对机器学习提供了非常有好的支持。 CoreML Filter Core Image 现在可以直接将图片 apply 到一个 CoreML 的模型里,相对于给 Core Image 的 Filter 链接上了深度学习的能力。 iOS12 中的 Core Image 提供了 CICoreMLModelFilter 类来将 CoreML 的 model 封装成 Core Image 能够识别的 Filter 格式。 下图是一个 ML 领域的经典应用的例子(风格迁移) ![]() 不过现在在网上还完全搜不到 CICoreMLModelFilter ,(大雾 数据填补 对于机器学习而言,训练集的完整性、覆盖度能够很大程度上决定最后模型的精确程度。但是现实情况是,我们往往没有那么多训练集,在这样的情况下,学术界一般都采用对现有训练集的图片进行相应的变化来起到扩充数据集的作用。这类技术统称 数据填补(Data Augmentation Core Image 对于这类任务天生支持的很好,支持包括以下几种类型的变化:
以下是几种使用 Core Image 的不同 Filter 来将一张图变多多张训练图片的例子: ![]() 小结 这个 Session 带来的内容总体来说还是激动人心的,虽然有的同学可能觉得比较小,没有那种颠覆式的创新,但对于从事图像领域工作的同学而言,毫无疑问这几个工作都给人一种 mind opener 的感觉,切实的反应了苹果对于多媒体、用户体验这两个领域非常超前的思考。 私信小编01即可领取神秘大礼包 洛阳网站seo优化排名推广1、洛阳做网站优化上首页|网站seo优化排名推广|洛阳网站搭建公司|C987网络公司唯一地址(www.cha987.com)。 2、不知道如何做网站seo?如何低成本搭建网站?如何网站如何排名?优化?上首页?如何维护?不知道就上c987网。 3、如何定制网站?给你提供最专业的搭建网站seo维护和排名,pc端,移动端,微信端,APP-4网合一。 4、对不遵守本声明或其他违法、恶意使用本网站内容者,本网站保留追究其法律责任的权利。 |
我们坚持以优秀的创意设计、领先的软件编程技术、出其不意的电子商务战略,鼎力为国内外知名企业提供全方位网站设计、网站优化服务。
我们一直都专研此道,从视觉出发,颜色、版式、材质、载体每一个都寄托了它的灵魂,我们精于此道:品牌策划、平面设计。
我们一如既往地根据用户的需求、市场环境、企业状况等进行综合分析并提供真实可靠的WEB解决方案,有效提升企业形象及品牌知名度。
我们将致力于品牌视觉设计与商业模式传播的完美结合,长期及时地在线售后服务和免费升级更新,为企业提供一站式服务。