iOS:GPUImage 简介及滤镜

郭兴平
2023-12-01

GPUImage 是一个开元的基于 GPU 的图片或视频的处理框架,其本身内置了多达 120 多种常见的滤镜效果,并且支持照相机和摄像机的实时滤镜,并且能够自定义图像滤镜。

美颜的基本概念

OpenGL ES: 开源嵌入式系统图形的处理框架,一套图形与硬件接口,创造了软件与图形加速间灵活强大的底层交互接口。用于把处理好的图片显示到屏幕上。

GPU: (图形处理单元)手机或者电脑用于图像处理和渲染的硬件。

GPU 工作原理: CPU 指定显示器工作,显示控制器根据 CPU 的控制到指定的地方去取数据和指令,目前的数据一般是从显存里取,如果显存里存不下,则从内存里取,内存也放不下,则从硬盘里取。

滤镜处理的原理: 就是把静态图片或者视频的每一帧进行图形变化后在显示到屏幕上,其本质就是像素点的坐标和颜色的变化。

OpenGL ES 程序处理图片的步骤:

  1. 初始化 OpenGL ES 环境,编译、链接顶点着色器和片元着色器。
  2. 缓存顶点、纹理坐标数据,传送图像数据到 GPU。
  3. 绘制图元到特定的帧缓存。
  4. 在帧缓存去除绘制的图像。

GPUImage 基本概念

GPUImage 是采用链式方法来处理画面,通过 addTarget 方法添加对象到链中,处理完一个 target,就会把上一个环节处理好的图像数据传递到下一个 target 处理,成为 GPUImage 处理链。

GPUImage 的四大输入基础类,都可以作为响应链的起点,这些基础类会把图像作为纹理传给 OpenGL ES 处理,然后把纹理传递给响应链的下一个 target 对象。

GPUImage 的处理环节

source(视频,图片源) —> filter(滤镜) —> final target(处理后的视频、图片)

source:

GPUImageVideoCamera 摄像头——用于实时拍摄视频

GPUImageStillCamera 摄像头——用于实时拍摄照片

GPUImagePicture 用于处理已经拍摄好的图片

GPUImageMovie 用于处理已经拍摄好的视频

filter

GPUImageFilter: 就是用来接收源图像,通过自定义的顶点,片元着色器来渲染新的图像,并在绘制完成后通知响应链的下一个对象。

GPUImageFramebuffer: 就是用来管理纹理缓存的格式与读写帧缓存的 buffer。

GPUImage 的 filter: GPUImageFilter 类或者子类,这个类继承自 GPUImageOutput,遵循 GPUImageInput 协议,既可以流进数据,又可以流出 GPUImage 的 final target:GPUImageView,GPUImageMovieWriter 最终输入目标,显示图片或者视频。

解析

GPUImageVideoCamera

GPUImageVideoCamera 是 GPUImageOutput 的子类,提供来自摄像头的图像数据作为源数据,一般是响应链的源头。

1.视频图像采集:AVCaptureSession

GPUImage 使用 AVFoundation 框架来获取视频。AVCaptureSession 类从 AV 输入设备的采集数据到指定的输出。

2.颜色空间:YUV

YUV 是被欧洲电视系统所采用的一种颜色编码方法。采用 YUV 色彩空间的重要性是它的亮度信号 Y 和色度信号 U、V 是分离的。如果只有 Y 信号分量而没有 U、V 分量,那么这样表示的图像就是黑白灰度图像,彩色电视采用 YUV 空间正是为了用亮度信号 Y 解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。

YUV 主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与 RGB 视频信号传输相比,它最大的优点在于只需占用极少的频宽。

GPUImage 中的 YUV

*GLProgram yuvConversionProgram: 将 YUV 颜色空间转换成 RGB 颜色空间的 GLSL。
CVPixelBufferGetPlaneCount: 返回缓冲区的平面数。

CVOpenGLESTextureCacheCreateTextureFromImage():
创建两个纹理 luminanceTextureRef(亮度纹理) 和 chrominanceTextureRef(色度纹理)。
convertYUVToRGBOutput(): 把 YUV 颜色空间的纹理转换成 RGB 颜色空间的纹理。

顶点着色器-通用 kGPUImageVertexShaderString

片元着色器:
  • kGPUImageYUVFullRangeConversionForLAFragmentShaderString
    kGPUImageYUVVideoRangeConversionForLAFragmentShaderString

纹理绘制

  1. glActiveTexture(GL_TEXTURE1);
  2. glGenTextures(1, &_texture);
  3. glBindTexture(GL_TEXTURE_2D, _texture);

GPUImageView 是响应链的终点,用于显示 GPUImage 图像

1.填充模式

GPUImageFillModeType: fillMode 图像的填充模式。

sizeInPixels: 像素区域的大小

recalculateViewGeometry: 重新计算图像顶点位置数据

AVMakeRectWithAspectRatioInsideRece: 在保证宽高比不变的前提下,得到一个尽可能大的矩形。

如果是 kGPUImageFillModeStretch

图像拉伸,直接使宽高等于 1.0 即可,原图像会直接铺满整个屏幕。

如果是 kGPUImageFillModePreserveAspectRatio

保持原宽高比,并且图像不超过屏幕。以当前屏幕大小为准。
widthScaling = insetRect.size.width / currentViewSize.width;

如果是 kGPUImageFillModePreserveAspectRatioAndFill

保持原宽高比,并且图像要铺满整个屏幕。以图像大小为准。
widthScaling = currentViewSize.height / insetRect.size.height;

imageVertices: 存放着顶点数据,上面的修改都会存放在这个数组。

2、OpenGL ES 绘制

  • (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
  • 源图像已经准备好,开始绘制。
    setDisplayFramebuffer() 会绑定 GPUImageView 的帧缓存,同时调试视图大小为 view 的大小。
    glActiveTexture 上面已经介绍过,是选择一个纹理单元。先选择纹理单元 4,然后把源图像数据绑定到 GL_TEXTURE_2D 的位置上。最后告诉片元着色器,纹理单元是 4。
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, [inputFramebufferForDisplay texture]);
glUniform1i(displayInputTextureUniform, 4);

这两行是分别绑定顶点坐标数据和纹理坐标数据。

glVertexAttribPointer(displayPositionAttribute, 2, GL_FLOAT, 0, 0, imageVertices);
glVertexAttribPointer(displayTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [GPUImageView textureCoordinatesForRotation:inputRotation]);

这两行是设定输入的源图像数据缓存,并且对缓存加锁。

inputFramebufferForDisplay = newInputFramebuffer;
[inputFramebufferForDisplay lock];

在准备好着色器、纹理 data、顶点位置坐标和纹理坐标后,就可以调用
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 绘制图像。

滤镜

    #pragma mark - 调整颜色 Handle Color

    #import "GPUImageBrightnessFilter.h"                //亮度
    #import "GPUImageExposureFilter.h"                  //曝光
    #import "GPUImageContrastFilter.h"                  //对比度
    #import "GPUImageSaturationFilter.h"                //饱和度
    #import "GPUImageGammaFilter.h"                     //伽马线
    #import "GPUImageColorInvertFilter.h"               //反色
    #import "GPUImageSepiaFilter.h"                     //褐色(怀旧)
    #import "GPUImageLevelsFilter.h"                    //色阶
    #import "GPUImageGrayscaleFilter.h"                 //灰度
    #import "GPUImageHistogramFilter.h"                 //色彩直方图,显示在图片上
    #import "GPUImageHistogramGenerator.h"              //色彩直方图
    #import "GPUImageRGBFilter.h"                       //RGB
    #import "GPUImageToneCurveFilter.h"                 //色调曲线
    #import "GPUImageMonochromeFilter.h"                //单色
    #import "GPUImageOpacityFilter.h"                   //不透明度
    #import "GPUImageHighlightShadowFilter.h"           //提亮阴影
    #import "GPUImageFalseColorFilter.h"                //色彩替换(替换亮部和暗部色彩)
    #import "GPUImageHueFilter.h"                       //色度
    #import "GPUImageChromaKeyFilter.h"                 //色度键
    #import "GPUImageWhiteBalanceFilter.h"              //白平横
    #import "GPUImageAverageColor.h"                    //像素平均色值
    #import "GPUImageSolidColorGenerator.h"             //纯色
    #import "GPUImageLuminosity.h"                      //亮度平均
    #import "GPUImageAverageLuminanceThresholdFilter.h" //像素色值亮度平均,图像黑白(有类似漫画效果)

    #import "GPUImageLookupFilter.h"                    //lookup 色彩调整
    #import "GPUImageAmatorkaFilter.h"                  //Amatorka lookup
    #import "GPUImageMissEtikateFilter.h"               //MissEtikate lookup
    #import "GPUImageSoftEleganceFilter.h"              //SoftElegance lookup

    #pragma mark - 图像处理 Handle Image

    #import "GPUImageCrosshairGenerator.h"              //十字
    #import "GPUImageLineGenerator.h"                   //线条

    #import "GPUImageTransformFilter.h"                 //形状变化
    #import "GPUImageCropFilter.h"                      //剪裁
    #import "GPUImageSharpenFilter.h"                   //锐化
    #import "GPUImageUnsharpMaskFilter.h"               //反遮罩锐化

    #import "GPUImageFastBlurFilter.h"                  //模糊
    #import "GPUImageGaussianBlurFilter.h"              //高斯模糊
    #import "GPUImageGaussianSelectiveBlurFilter.h"     //高斯模糊,选择部分清晰
    #import "GPUImageBoxBlurFilter.h"                   //盒状模糊
    #import "GPUImageTiltShiftFilter.h"                 //条纹模糊,中间清晰,上下两端模糊
    #import "GPUImageMedianFilter.h"                    //中间值,有种稍微模糊边缘的效果
    #import "GPUImageBilateralFilter.h"                 //双边模糊
    #import "GPUImageErosionFilter.h"                   //侵蚀边缘模糊,变黑白
    #import "GPUImageRGBErosionFilter.h"                //RGB侵蚀边缘模糊,有色彩
    #import "GPUImageDilationFilter.h"                  //扩展边缘模糊,变黑白
    #import "GPUImageRGBDilationFilter.h"               //RGB扩展边缘模糊,有色彩
    #import "GPUImageOpeningFilter.h"                   //黑白色调模糊
    #import "GPUImageRGBOpeningFilter.h"                //彩色模糊
    #import "GPUImageClosingFilter.h"                   //黑白色调模糊,暗色会被提亮
    #import "GPUImageRGBClosingFilter.h"                //彩色模糊,暗色会被提亮
    #import "GPUImageLanczosResamplingFilter.h"         //Lanczos重取样,模糊效果
    #import "GPUImageNonMaximumSuppressionFilter.h"     //非最大抑制,只显示亮度最高的像素,其他为黑
    #import "GPUImageThresholdedNonMaximumSuppressionFilter.h" //与上相比,像素丢失更多

    #import "GPUImageSobelEdgeDetectionFilter.h"        //Sobel边缘检测算法(白边,黑内容,有点漫画的反色效果)
    #import "GPUImageCannyEdgeDetectionFilter.h"        //Canny边缘检测算法(比上更强烈的黑白对比度)
    #import "GPUImageThresholdEdgeDetectionFilter.h"    //阈值边缘检测(效果与上差别不大)
    #import "GPUImagePrewittEdgeDetectionFilter.h"      //普瑞维特(Prewitt)边缘检测(效果与Sobel差不多,貌似更平滑)
    #import "GPUImageXYDerivativeFilter.h"              //XYDerivative边缘检测,画面以蓝色为主,绿色为边缘,带彩色
    #import "GPUImageHarrisCornerDetectionFilter.h"     //Harris角点检测,会有绿色小十字显示在图片角点处
    #import "GPUImageNobleCornerDetectionFilter.h"      //Noble角点检测,检测点更多
    #import "GPUImageShiTomasiFeatureDetectionFilter.h" //ShiTomasi角点检测,与上差别不大
    #import "GPUImageMotionDetector.h"                  //动作检测
    #import "GPUImageHoughTransformLineDetector.h"      //线条检测
    #import "GPUImageParallelCoordinateLineTransformFilter.h" //平行线检测

    #import "GPUImageLocalBinaryPatternFilter.h"        //图像黑白化,并有大量噪点

    #import "GPUImageLowPassFilter.h"                   //用于图像加亮
    #import "GPUImageHighPassFilter.h"                  //图像低于某值时显示为黑

    #pragma mark - 视觉效果 Visual Effect

    #import "GPUImageSketchFilter.h"                    //素描
    #import "GPUImageThresholdSketchFilter.h"           //阀值素描,形成有噪点的素描
    #import "GPUImageToonFilter.h"                      //卡通效果(黑色粗线描边)
    #import "GPUImageSmoothToonFilter.h"                //相比上面的效果更细腻,上面是粗旷的画风
    #import "GPUImageKuwaharaFilter.h"                  //桑原(Kuwahara)滤波,水粉画的模糊效果;处理时间比较长,慎用

    #import "GPUImageMosaicFilter.h"                    //黑白马赛克
    #import "GPUImagePixellateFilter.h"                 //像素化
    #import "GPUImagePolarPixellateFilter.h"            //同心圆像素化
    #import "GPUImageCrosshatchFilter.h"                //交叉线阴影,形成黑白网状画面
    #import "GPUImageColorPackingFilter.h"              //色彩丢失,模糊(类似监控摄像效果)

    #import "GPUImageVignetteFilter.h"                  //晕影,形成黑色圆形边缘,突出中间图像的效果
    #import "GPUImageSwirlFilter.h"                     //漩涡,中间形成卷曲的画面
    #import "GPUImageBulgeDistortionFilter.h"           //凸起失真,鱼眼效果
    #import "GPUImagePinchDistortionFilter.h"           //收缩失真,凹面镜
    #import "GPUImageStretchDistortionFilter.h"         //伸展失真,哈哈镜
    #import "GPUImageGlassSphereFilter.h"               //水晶球效果
    #import "GPUImageSphereRefractionFilter.h"          //球形折射,图形倒立

    #import "GPUImagePosterizeFilter.h"                 //色调分离,形成噪点效果
    #import "GPUImageCGAColorspaceFilter.h"             //CGA色彩滤镜,形成黑、浅蓝、紫色块的画面
    #import "GPUImagePerlinNoiseFilter.h"               //柏林噪点,花边噪点
    #import "GPUImage3x3ConvolutionFilter.h"            //3x3卷积,高亮大色块变黑,加亮边缘、线条等
    #import "GPUImageEmbossFilter.h"                    //浮雕效果,带有点3d的感觉
    #import "GPUImagePolkaDotFilter.h"                  //像素圆点花样
    #import "GPUImageHalftoneFilter.h"                  //点染,图像黑白化,由黑点构成原图的大致图形

    #pragma mark - 混合模式 Blend

    #import "GPUImageMultiplyBlendFilter.h"             //通常用于创建阴影和深度效果
    #import "GPUImageNormalBlendFilter.h"               //正常
    #import "GPUImageAlphaBlendFilter.h"                //透明混合,通常用于在背景上应用前景的透明度
    #import "GPUImageDissolveBlendFilter.h"             //溶解
    #import "GPUImageOverlayBlendFilter.h"              //叠加,通常用于创建阴影效果
    #import "GPUImageDarkenBlendFilter.h"               //加深混合,通常用于重叠类型
    #import "GPUImageLightenBlendFilter.h"              //减淡混合,通常用于重叠类型
    #import "GPUImageSourceOverBlendFilter.h"           //源混合
    #import "GPUImageColorBurnBlendFilter.h"            //色彩加深混合
    #import "GPUImageColorDodgeBlendFilter.h"           //色彩减淡混合
    #import "GPUImageScreenBlendFilter.h"               //屏幕包裹,通常用于创建亮点和镜头眩光
    #import "GPUImageExclusionBlendFilter.h"            //排除混合
    #import "GPUImageDifferenceBlendFilter.h"           //差异混合,通常用于创建更多变动的颜色
    #import "GPUImageSubtractBlendFilter.h"             //差值混合,通常用于创建两个图像之间的动画变暗模糊效果
    #import "GPUImageHardLightBlendFilter.h"            //强光混合,通常用于创建阴影效果
    #import "GPUImageSoftLightBlendFilter.h"            //柔光混合
    #import "GPUImageChromaKeyBlendFilter.h"            //色度键混合
    #import "GPUImageMaskFilter.h"                      //遮罩混合
    #import "GPUImageHazeFilter.h"                      //朦胧加暗
    #import "GPUImageLuminanceThresholdFilter.h"        //亮度阈
    #import "GPUImageAdaptiveThresholdFilter.h"         //自适应阈值
    #import "GPUImageAddBlendFilter.h"                  //通常用于创建两个图像之间的动画变亮模糊效果
    #import "GPUImageDivideBlendFilter.h"               //通常用于创建两个图像之间的动画变暗模糊效果
 类似资料: