iOS GPUImage实时美颜滤镜

作者: 路漫漫其修远兮Wzt | 来源:发表于2018-05-08 11:42 被阅读169次

    转载自:实战分享:实时美颜滤镜是怎样炼成的

    1.背景

    前段时间由于项目需求,做了一个基于GPUImage的实时美颜滤镜。现在各种各样的直播、视频App层出不穷,美颜滤镜的需求也越来越多。为了回馈开源,现在我把它放到了GitHub上面,感兴趣的朋友可以去下载。下面将主要介绍实现美颜滤镜的原理和思路。

    2. GPUImage

    GPUImage是一个开源的基于GPU的图片或视频的处理框架,其本身内置了多达120多种常见的滤镜效果。有了它,添加实时的滤镜只需要简单地添加几行代码。下面的例子是以摄像头的数据为源,对其实时地进行反色的操作(类似相片底片的效果):

    self.videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionFront];
    
    self.videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
    
    self.videoCamera.horizontallyMirrorFrontFacingCamera = YES;
    
    GPUImageColorInvertFilter *invert = [[GPUImageColorInvertFilter alloc] init];
    
    [self.videoCamera addTarget:invert];
    
    self.filterView = [[GPUImageView alloc] initWithFrame:self.view.frame];
    
    self.filterView.center = self.view.center;
    
    [self.view addSubview:self.filterView];
    
    [invert addTarget:self.filterView];
    
    [self.videoCamera startCameraCapture];
    

    其实美颜也是一样,如果有这么一个美颜的滤镜(姑且叫做GPUImageBeautifyFilter),那么只需要把上面代码中的GPUImageColorInvertFilter替换成GPUImageBeautifyFilter即可。我们只需要做一个GPUImageBeautifyFilter就能实现实时美颜了,问题来了,到底什么算是美颜呢?我的理解是,大家对于美颜比较常见的需求就是磨皮、美白。当然提高饱和度、提亮之类的就根据需求而定。本文将着重介绍磨皮的实现(实际上GPUImageBeautifyFilter也实现了美白、提亮等效果)。

    3. 磨皮

    磨皮的本质实际上是模糊。而在图像处理领域,模糊就是将像素点的取值与周边的像素点取值相关联。而我们常见的高斯模糊 ,它的像素点取值则是由周边像素点求加权平均所得,而权重系数则是像素间的距离的高斯函数,大致关系是距离越小、权重系数越大。下图3.1是高斯模糊效果的示例:

    高斯模糊效果图3.1

    2031820-fdd32650fdf06567.png

    如果单单使用高斯模糊来磨皮,得到的效果是不尽人意的。原因在于,高斯模糊只考虑了像素间的距离关系,没有考虑到像素值本身之间的差异。举个例子来讲,头发与人脸分界处(颜色差异很大,黑色与人皮肤的颜色),如果采用高斯模糊则这个边缘也会模糊掉,这显然不是我们希望看到的。而双边滤波(Bilateral Filter) 则考虑到了颜色的差异,它的像素点取值也是周边像素点的加权平均,而且权重也是高斯函数。不同的是,这个权重不仅与像素间距离有关,还与像素值本身的差异有关,具体讲是,像素值差异越小,权重越大,也是这个特性让它具有了保持边缘的特性,因此它是一个很好的磨皮工具。下图3.2是双边滤波的效果示例:

    双边滤波效果图3.2

    2031820-b71a296c14de8ab8.png

    对比3.1和3.2,双边滤波效果确实在人脸细节部分保留得更好,因此我采用了双边滤波作为磨皮的基础算法。双边滤波在GPUImage中也有实现,是GPUImageBilateralFilter。
    根据图3.2,可以看到图中仍有部分人脸的细节保护得不够,还有我们并不希望将人的头发也模糊掉(我们只需要对皮肤进行处理)。由此延伸出来的改进思路是结合双边滤波,边缘检测以及肤色检测。整体逻辑如下:

    2031820-bd560df591a6b26e.png

    Combination Filter是我们自己定义的三输入的滤波器。三个输入分别是原图像A(x, y),双边滤波后的图像B(x, y),边缘图像C(x, y)。其中A,B,C可以看成是图像矩阵,(x,y)可以看成其中某一像素的坐标。Combination Filter的处理逻辑如下图:

    2031820-558663036aa5e18f.png

    下面是主要的shader代码:

    NSString *const kGPUImageBeautifyFragmentShaderString = SHADER_STRING
    
    (
    
    varying highp vec2 textureCoordinate;
    
    varying highp vec2 textureCoordinate2;
    
    varying highp vec2 textureCoordinate3;
    
    uniform sampler2D inputImageTexture;
    
    uniform sampler2D inputImageTexture2;
    
    uniform sampler2D inputImageTexture3;
    
    uniform mediump float smoothDegree;
    
    void main()
    
    {
    
    highp vec4 bilateral = texture2D(inputImageTexture, textureCoordinate);
    
    highp vec4 canny = texture2D(inputImageTexture2, textureCoordinate2);
    
    highp vec4 origin = texture2D(inputImageTexture3,textureCoordinate3);
    
    highp vec4 smooth;
    
    lowp float r = origin.r;
    
    lowp float g = origin.g;
    
    lowp float b = origin.b;
    
    if (canny.r < 0.2 && r > 0.3725 && g > 0.1568 && b > 0.0784 && r > b && (max(max(r, g), b) - min(min(r, g), b)) > 0.0588 && abs(r-g) > 0.0588) {
    
    smooth = (1.0 - smoothDegree) * (origin - bilateral) + bilateral;
    
    }
    
    else {
    
    smooth = origin;
    
    }
    
    gl_FragColor = smooth;
    
    }
    
    );
    

    Combination Filter通过肤色检测和边缘检测,只对皮肤和非边缘部分进行处理。下面是采用这种方式进行磨皮之后的效果图:

    最终磨皮效果图3.3

    2031820-7320d9b7d2c9809d.png

    对比3.3与3.2,可以看到3.3对人脸细节的保护更好,同时对于面部磨皮效果也很好,给人感觉更加真实。

    4.延伸

    我所采用的磨皮算法是基于双边滤波的,主要是考虑到它同时结合了像素间空间距离以及像素值本身的差异。当然也不一定要采用双边滤波,也有通过改进高斯模糊(结合像素值差异)来实现磨皮的,甚至能取得更好的效果。另外GPUImageBeautifyFilter不仅仅具有磨皮功能,也实现了log曲线调色,亮度、饱和度的调整,具体详情可以参见demo

    其他相关GPUImage的研究:

    图像处理之GPUImage图片滤镜
    http://blog.csdn.net/xoxo_x/article/details/53507016

    图像处理之CPU图片滤镜
    http://blog.csdn.net/xoxo_x/article/details/53518322

    图像处理之CoreImage图片滤镜
    http://blog.csdn.net/xoxo_x/article/details/53518529

    iOS GPUImage研究序一:内置滤镜:
    http://blog.csdn.net/Xoxo_x/article/details/57082804

    iOS GPUImage研究二:捕获图像stillCamera写入相册
    http://blog.csdn.net/Xoxo_x/article/details/57086446

    iOS GPUImage研究三:视频采集并添加实时滤镜
    http://blog.csdn.net/xoxo_x/article/details/58357978

    iOS GPUImage研究四:为视频文件添加滤镜
    http://blog.csdn.net/Xoxo_x/article/details/58818703

    iOS GPUImage研究五:短视频拍摄(滤镜、文件写入)
    http://blog.csdn.net/Xoxo_x/article/details/70198469

    iOS GPUImage研究六:为视频添加图片水印
    http://blog.csdn.net/xoxo_x/article/details/71055867

    iOS GPUImage研究七:动态相册初探(水印)
    http://blog.csdn.net/xoxo_x/article/details/71076584

    将图片保存到本地
    http://blog.csdn.net/xoxo_x/article/details/53517878

    基于IM实现直播礼物效果
    http://blog.csdn.net/xoxo_x/article/details/52044388

    GPUImage之为视频添加10种原生滤镜
    http://blog.csdn.net/xoxo_x/article/details/52749033

    GPUImage–流行的美颜滤镜GPUImageBeautifyFilter
    http://blog.csdn.net/xoxo_x/article/details/52743107

    GPUImage基于OpenGL ES 2.0,比基于CPU的图形和视频处理更快速.
    GPUImage把OpenGL ES封装为简洁的Objective-C接口.

    学习资料

    GPUImage详细解析(一)
    http://url.cn/2FwjqIr
    GPUImage详细解析(二)
    http://url.cn/2GsW2qg
    GPUImage详细解析(三)- 实时美颜滤镜
    http://url.cn/2F0SKgR
    GPUImage详细解析(四)模糊图片处理
    http://url.cn/2GX6JEQ
    GPUImage详细解析(五)滤镜视频录制
    http://url.cn/2GHCo71
    GPUImage详细解析(六)-用视频做视频水印
    http://url.cn/2JrhR7V
    GPUImage详细解析(七)文字水印和动态图像水印
    http://url.cn/2IzRshs
    GPUImage详细解析(八)视频合并混音
    http://url.cn/2DmUYiA
    GPUImage详细解析(九)图像的输入输出和滤镜通道
    http://url.cn/2EFjlGp 收起

    下载GPUImage,地址:https://github.com/BradLarson/GPUImage
    共125个滤镜, 分为四类

        1、Color adjustments: 31 filters, 颜色处理相关
        2、Image processing: 40 filters, 图像处理相关.
        3、Blending modes: 29 filters, 混合模式相关.
        4、Visual effects: 25 filters, 视觉效果相关.
    
    #import <Foundation/Foundation.h>
    #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"               //通常用于创建两个图像之间的动画变暗模糊效果
    

    相关文章

      网友评论

      • 滴答大:集成美颜之后,AVCaptureVideoDataOutputSampleBufferDelegate 代理方法中存在内存泄漏, [self.delegate willOutputSampleBuffer:sampleBuffer];这行代码,遇到过吗?我改成weakSelf 还是说block_invoke

      本文标题:iOS GPUImage实时美颜滤镜

      本文链接:https://www.haomeiwen.com/subject/eimirftx.html