双葉幼稚園 A Layman's Repository

GPUImage

(翻译自 NSHispter,原文链接:http://nshipster.com/gpuimage/

在 NSHipster,我们一直在研究 Objective-C 不为人知的一面来了解我们每天面对的系统。一般来说,这意味着仔细研究 Apple 的框架和语言特性(毕竟每天要用 Obective-C 工作)。不过,有些时候,看看成堆的第三方库和框架也蛮好的(而且里面有些真的很好),还可以看一下 Cupertino 外面有什么新东西。

本周我们来看一下你能找到的最厉害的一个开源项目:GPUImage。系好安全带,NSHipster 们,一不小心你读完这篇文章就造出一个相机 app 了。


GPUImage 作者是 Brad Larson,以 BSD 协议放出,能够在图像、实时摄像头影像和视频上使用 GPU 加速的滤镜和其他效果。

GPU vs. CPU

每只 iPhone 都有两个处理器:一个 CPU,也就是中央处理器,和一个 GPU,也就是图形处理器。每个处理器都有它自己的优势,现代芯片架构(例如 Apple A4)把 CPU 和 GPU 集成在一个物理封装里。

在 Xcode 里面写 C 和 Objective-C 的时候,产生的指令绝大部分会被 CPU 执行。相对地,GPU 是一枚专用芯片,专门用来做独立的小操作,例如图形渲染。GPU 执行的指令和 CPU 是有很大区别的,因此用特殊的语言来编写:OpenGL(特别地,在 iPhone 和 iPad 上使用 OpenGL ES

如果想学习 OpenGL ES 和渲染管线相关的知识,可以参考 Jeff LaMarche's GLProgram OpenGL ES 2.0 book

比较一下 GPU 渲染和 CPU 渲染的性能,区别还是蛮大的:

CPU vs. GPU 帧率对比 (FPS 越高越好)
Calculation GPU FPS CPU FPS Δ
Thresholding ⨉ 1 60.00 4.21 14.3⨉
Thresholding ⨉ 2 33.63 2.36 14.3⨉
Thresholding ⨉ 100 1.45 0.05 28.7⨉

"哦,这货是 Instagram?"

好吧,我们这么说:

Instagram : GPUImage :: 拍立得 : NASA 空间光学制造中心

换种说法,用 GPUImage 的 API 可以做出数千种相机 app,只需要把滤镜正确地组合起来,外加一小点想象力。

这张表包含了 GPUImage 内置的 125 种滤镜:(译者:你想翻译死我吗?)

Color Adjustments Image Processing Blending Modes Visual Effects
  • Brightness Filter
  • Exposure Filter
  • Contrast Filter
  • Saturation Filter
  • Gamma Filter
  • Levels Filter
  • Color Matrix Filter
  • RGB Filter
  • Hue Filter
  • Tone Curve Filter
  • Highlight Shadow Filter
  • Lookup Filter
  • Amatorka Filter
  • Miss Etikate Filter
  • Soft Elegance Filter
  • Color Invert Filter
  • Grayscale Filter
  • Monochrome Filter
  • False Color Filter
  • Haze Filter
  • Sepia Filter
  • Opacity Filter
  • Solid Color Generator
  • Luminance Threshold Filter
  • Adaptive Threshold Filter
  • Average Luminance Threshold Filter
  • Histogram Filter
  • Histogram Generator
  • Average Color
  • Luminosity
  • Chroma Key Filter
  • Transform Filter
  • Crop Filter
  • Lanczos Resampling Filter
  • Sharpen Filter
  • Unsharp Mask Filter
  • Fast Blur Filter
  • Single Component Fast Blur Filter
  • Gaussian Blur Filter
  • Single Component Gaussian Blur Filter
  • Gaussian Selective Blur Filter
  • Gaussian Blur Position Filter
  • Median Filter
  • Bilateral Filter
  • Tilt Shift Filter
  • Box Blur Filter
  • 3x3 Convolution Filter
  • Sobel Edge Detection Filter
  • Threshold Edge Detection Filter
  • Canny Edge Detection Filter
  • Harris Corner Detection Filter
  • Noble Corner Detection Filter
  • Shi-Tomasi Corner Detection Filter
  • Non Maximum Suppression Filter
  • X/Y Derivative Filter
  • Crosshair Generator
  • Dilation Filter
  • RGB Dilation Filter
  • Erosion Filter
  • RGB Erosion Filter
  • Opening Filter
  • RGB Opening Filter
  • Closing Filter
  • RGB Closing Filter
  • Local Binary Pattern Filter
  • Low Pass Filter
  • High Pass Filter
  • Motion Detector
  • Hough Transform Line Detector
  • Line Generator
  • Motion Blur Filter
  • Zoom Blur Filter
  • Chroma Key Blend Filter
  • Dissolve Blend Filter
  • Multiply Blend Filter
  • Add Blend Filter
  • Subtract Blend Filter
  • Divide Blend Filter
  • Overlay Blend Filter
  • Darken Blend Filter
  • Lighten Blend Filter
  • Color Burn Blend Filter
  • Color Dodge Blend Filter
  • Screen Blend Filter
  • Exclusion Blend Filter
  • Difference Blend Filter
  • Hard Light Blend Filter
  • Soft Light Blend Filter
  • Alpha Blend Filter
  • Source Over Blend Filter
  • Color Burn Blend Filter
  • Color Dodge Blend Filter
  • Normal Blend Filter
  • Color Blend Filter
  • Hue Blend Filter
  • Saturation Blend Filter
  • Luminosity Blend Filter
  • Linear Burn Blend Filter
  • Poisson Blend Filter
  • Mask Filter
  • Pixellate Filter
  • Polar Pixellate Filter
  • Polka Dot Filter
  • Halftone Filter
  • Crosshatch Filter
  • Sketch Filter
  • Threshold Sketch Filter
  • Toon Filter
  • Smooth Toon Filter
  • Emboss Filter
  • Posterize Filter
  • Swirl Filter
  • Bulge Distortion Filter
  • Pinch Distortion Filter
  • Stretch Distortion Filter
  • Sphere Refraction Filter
  • Glass Sphere Filter
  • Vignette Filter
  • Kuwahara Filter
  • Kuwahara Radius 3 Filter
  • Perlin Noise Filter
  • CGAColorspace Filter
  • Mosaic Filter
  • JFAVoronoi Filter
  • Voronoi Consumer Filter

认真说,GPUImage 代码里带的这个 滤镜展示示例 app 能在 AppStore 卖 3.99 刀。要是再加上 twitter 集成和一些声音效果,卖个 6.99 刀不成问题。

渲染管线

GPUImage 从本质上来说是一个渲染管线的 Objective-C 抽象。从相机、网络或者磁盘上加载的源图像,在经过一系列滤镜处理后,最终输出到了 view、graphics context 或是数据流中。

例如说,摄像头中的图像可以应用一个 Color Levels 滤镜,来模拟各种色盲效果,然后实时显示在一个 view 中。

GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc]
    initWithSessionPreset:AVCaptureSessionPreset640x480
           cameraPosition:AVCaptureDevicePositionBack];
videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;

GPUImageFilter *filter = [[GPUImageLevelsFilter alloc] initWithFragmentShaderFromFile:@"CustomShader"];
[filter setRedMin:0.299 gamma:1.0 max:1.0 minOut:0.0 maxOut:1.0];
[filter setGreenMin:0.587 gamma:1.0 max:1.0 minOut:0.0 maxOut:1.0];
[filter setBlueMin:0.114 gamma:1.0 max:1.0 minOut:0.0 maxOut:1.0];
[videoCamera addTarget:filter];

GPUImageView *filteredVideoView = [[GPUImageView alloc] initWithFrame:self.view.bounds)];
[filter addTarget:filteredVideoView];
[self.view addSubView:filteredVideoView];

[videoCamera startCameraCapture];

或者,结合不同的颜色混合模式,图像效果和一些调整,你可以把静止图像转变成可以分享给你时髦的朋友们看看的精美图像(例子来自基于 GPUImage 的 FilterKit)。

GPUImageFilterGroup *filter = [[FKGPUFilterGroup alloc] init];

GPUImageSaturationFilter *saturationFilter = [[GPUImageSaturationFilter alloc] init];
[saturationFilter setSaturation:0.5];

GPUImageMonochromeFilter *monochromeFilter = [[GPUImageMonochromeFilter alloc] init];
[monochromeFilter setColor:(GPUVector4){0.0f, 0.0f, 1.0f, 1.0f}];
[monochromeFilter setIntensity:0.2];

GPUImageVignetteFilter *vignetteFilter = [[GPUImageVignetteFilter alloc] init];
[vignetteFilter setVignetteEnd:0.7];

GPUImageExposureFilter *exposureFilter = [[GPUImageExposureFilter alloc] init];
[exposureFilter setExposure:0.3];

[filter addGPUFilter:exposureFilter];
[filter addGPUFilter:monochromeFilter];
[filter addGPUFilter:saturationFilter];
[filter addGPUFilter:vignetteFilter];

看完了 GPUImage 的功能,一定很兴奋吧。GPUImage 非常简单,可以马上开始使用(不需要了解 OpenGL),性能上也足够完成你想要的一切。不止是这样,它还自带了非常多的积木一样的部件 -- 色彩调整,混合模式,你能想到的想不到的一切视觉效果。

GPUImage 是开源社区少有的好东西,我们 Mac 和 iOS 开发者非常幸运的能拥有它。用 GPUImage 做些牛逼的东西,向其他人展示一个崭新的世界。


译者吐槽时间

我自己也用过一点 GPUImage,方便是很方便,不光是省掉了 AVFoundation 的许多烦人的 setup 代码,还内置了许多滤镜效果。不过它也有不少坑,我遇到的一个就是占用太多内存,一段时间后就 crash 掉了,毕竟是处理视频,需要不少内存,iPhone 的内存又不太多,就要更加注意。我当时是加了一个 @autoreleasepool 就好多了。