关于GPUImage

本文内容参考自以下文章:KM文章一张图教你看懂GPUImageiOS 图像处理系列 - GPUImage源码解读(一),博文GPUImage文集。文中不再详细标注引用来源。

关于GPUImage

GPUImage框架是一个开源iOS类库,基于OpenGL进行图像和视频处理,借助GPU加速实现各种滤镜效果,并支持摄像头拍摄实时渲染。

它具有以下特性:

·             对OpenGL资源创建和滤镜做统一封装,接口简单易用,内置cache模块进行framebuffer管理。

·             框架设计灵活,支持上下级滤镜的串联、并联,以实现复杂的滤镜响应链。

·             有丰富的输入、输出组件及封装好的内置滤镜,可满足大多数场景的应用。

·             可继承GPUImageFilter实现自定义滤镜效果,扩展非常方便。

GPUImage框架

GPUImage功能的实现依赖四个部分:资源管理、Sources、Filters、Outputs。核心架构用下图概括:

1.     资源管理

GLProgram是GPUImage对OpenGL ES中的program的封装,可用vertexShader和fragmentShader创建GLProgram对象,实现自定义滤镜效果。

GPUImageContext是GPUImage对OpenGL ES上下文的封装,并添加GPUImge相关的上下文,如上下文队列(contextQueue,解决OpenGLContext不是多线程安全的问题)、CV纹理缓存(coreVideoTexttureCache)、framebuffer缓存、program使用的缓存等。

GPUImageFramebuffer是管理纹理缓存格式、帧缓存的buffer,完成缓存创建、指定渲染目标、调整视口、解锁等。其中,newCGImageFromFramebufferContents函数从缓存中获取图像数据,创建CGImageRef并返回。

GPUImageFramebufferCache是GPUImageFramebuffer的管理类。

2.    Sources

Sources目录结构如上图所示。GPUImageOutput是其他输入源的基类,输入组件将图像或视频帧数据转换成OpenGL纹理传递给滤镜组件。下面以滤镜视频拍摄这一场景下使用的GPUImageVideoCamera为例进行介绍。

GUPImagVideoCamera利用AVCaptureSession从AV输入设备采集数据。

流程概述如下:

1) 找到摄像头设备_inoutCamera、麦克风_microphone,创建摄像头输入videoInput和麦克风输入audioInput,设置为_captureSession的输入。

2) 创建摄像头输出videoOutput和麦克风输出audioOutput,设置为_captureSession的输出,设置二者的输出delegate。

3)     调用[_captureSessionstartRunning]开始获取音视频数据。

4)      音频数据到达后发送给设置的audioEncordingTarget处理。

5)     视频数据到达后利用下面的函数处理回调:

摄像头默认采样格式为YUV420,Y通道数据和UV通道数据分别存放在两个plane中,processVideoSampleBuffer:函数将两个plane的数据取出,处理后在convertYUVToRGBOutput函数中通过颜色转换的shader,得到了RGB格式的GPU纹理提供给下一级滤镜组件,完成数据输入工作。

3.     Filters

GPUImageFilter是各滤镜类的基类。它实现了GPUImageInput协议,可以作为输出对象。GPUImageInput定义了组件作为响应链中的target(上一级组件的输出对象)需要实现的接口。

另一方面GPUImageFilter继承自Sources中的GPUImageOutput,因此一个滤镜组件也可以作为输入对象。基于这种设计,输入组件、滤镜组件、输出组件可以链式串联起来,推动输入数据的处理与传递。

GPUImageFilter及子类接受一个或多个输入,调用关联的GLProgram进行渲染,将结果输出到targets属性保存的对象列表中的每一个对象。输入、输出的纹理由GPUImageFrameBuffer管理。

输入数据通过setInputFramebuffer:接口传入,由响应链中的上一级组件调用。

读入输入数据后,下图接口实现了渲染和数据向下级组件的传递。

其中,renderToTextureWithVertices:函数实现滤镜渲染,将渲染结果输出到outputframebuffer指定的缓存。

informTargetsAboutNewFrameAtTime:将自己获得的渲染结果数据传递给下一级组件,并推动其处理数据。

4.     Outputs

Outputs组件是响应链的终点,负责将处理结果输出。这组组件同样实现GPUImageInput协议,处理上一级组件的输出结果。GPUImageView是UIView的子类,用于实时将滤波结果显示在屏幕上,GPUImageMovieWriter将滤镜视频保存在本地,GPUImageTextureOutput输出GPU纹理,GPUImageRawDataOutput提供输出完成的delegate回调和读区像素数据的接口。录制滤镜视频时需要用到GPUImageView和GPUImageMovieWriter。

GPUImageMovieWriter将视频输出到磁盘,通过设置、使用AVAssetWriter,在newFrameReadyAtTime:中实现功能。

GPUImageView内部将自己的CALayer申明为CAEAGLayer,在初始化后调用createDisplayFramebuffer方法:

将renderBuffer和CALayer关联,newFrameReadyAtTime:渲染后图像会输出至CALayer上。

录制滤镜视频

下面的例子利用GPUImage录制视频、实现实时的滤镜效果渲染并将视频文件保存到本地。

通过GPUImageVideoCamera采集视频和音频数据,音频直接传递至GPUImageMovieWriter;视频传入滤镜链,经过滤镜处理后,输出的渲染结果传递给GPUImageMovieWriter准备写入本地文件,并通过GPUImageView显示在屏幕上。

下图是视频录制页面,使用内置滤镜GPUImageSwirlFilter,屏幕下方滑动条可以调整滤波核参数,实时的改变滤镜渲染的效果(本例表现为螺旋形的角度)。点击左上方按钮启动/结束录制,结束录制后视频文件保存在本地相册。

录制界面

设置响应链:

点击录制按钮开始录制视频,用NSURL及尺寸初始化_movieWriter:

结束录制:

其他滤镜效果:

玻璃球                                       阴影边框

泊松图像融合                            左图中的水印原图

 形态学开运算                               形态学闭运算

风格化之素描画                                卡通

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏walterlv - 吕毅的博客

如何精准地用打印机在贺卡或邀请函上打字

2018-08-26 07:35

3.8K10
来自专栏Google Dart

Flutter中构建布局 顶

然后本指南回过头来解释Flutter的布局方法,并说明如何在屏幕上放置一个小部件。 在讨论如何水平和垂直放置小部件之后,会介绍一些最常见的布局小部件。

73010
来自专栏数据小魔方

绩效管理工具(一)——仪表盘风格图表!

今天教大家制作用于绩效管理的仪表盘风格图表! ▽ 看惯了普通的图表,偶尔换换口味,用类似汽车仪表盘(量表)风格的图表来展示数据,也能起到新人瞩目,令人印象深刻的...

41350
来自专栏GIS讲堂

OpenLayers3基础教程——OL3基本概念

从本节开始,我会陆陆续续的更新有关OL3的相关文章——OpenLayers3基础教程,欢迎大家关注我的博客,同时也希望我的博客能够给大家带来一点帮助。

18230
来自专栏数据小魔方

ggplot2多维分面多图层对应规则

今天只给大家讲一个知识点,是属于ggplot2高阶用法中的分面与多图层关系如何对应,这个用法之前困扰我很久,也是最近帮朋友做东西才发现这个漏洞,于是感觉分享给大...

36940
来自专栏阮一峰的网络日志

关于Lorem ipsum

Wikipedia上的解释是,这只是一段用来测试排版效果的占位文字,没有实际的含义。据说,16世纪的时候就有人开始用了。当时的某个印刷工人,从古罗马政治家西塞罗...

21910
来自专栏君赏技术博客

想要漂亮的蒙版指引吗?跟着我手把手的教你写出来

既然接到了这个需求,那么就需要做出来,第一眼看上去确实有点难。当时安卓已经找到了对应的库,十分容易的做这个需求了。

14320
来自专栏小灰灰

zxing二维码生成服务之深度定制

二维码生成服务之深度定制 之前写了一篇二维码服务定制的博文,现在则在之前的基础上,再进一步,花样的实现深度定制的需求,我们的目标是二维码上的一切都是可以由用户...

59060
来自专栏向治洪

Android硬件加速介绍与实现

概述 在手机客户端尤其是Android应用的开发过程中,我们经常会接触到“硬件加速”这个词。由于操作系统对底层软硬件封装非常完善,上层软件开发者往往对硬件加速的...

27660
来自专栏老司机的简书

CoreText实现图文混排之尺寸估算及文本选择

回头看看,距离CoreText系列首发过去一年也多了,看到第一篇文章即将超越1.3W的点击量老司机也是压力越来越大,毕竟作为瞎逼逼杰出代表的老司机偶尔也要正经一...

13520

扫码关注云+社区

领取腾讯云代金券