天天看點

GPUImage--美顔濾鏡GPUImageBeautifyFilter

關于GPUimage的介紹請看這裡GPUImage:濾鏡、美顔、視訊流處理

美顔隻是不同濾鏡組合起來的效果,實際上美顔也是一種濾鏡,它的需求較多,于是自稱一派。

GPUImageBeautifyFilter

/*
GPUImageBeautifyFilter是基于GPUImage的實時美顔濾鏡中的美顔濾鏡,包括GPUImageBilateralFilter、GPUImageCannyEdgeDetectionFilter、GPUImageCombinationFilter、GPUImageHSBFilter。
*/
           

在GPUImageBeautifyFilter.h中有:分别建立對應上面的對象

#import "GPUImage.h"

@class GPUImageCombinationFilter;

@interface GPUImageBeautifyFilter : GPUImageFilterGroup {
    GPUImageBilateralFilter *bilateralFilter;
    GPUImageCannyEdgeDetectionFilter *cannyEdgeFilter;
    GPUImageCombinationFilter *combinationFilter;
    GPUImageHSBFilter *hsbFilter;
}

@end
           

繪制流程分為:

  1. 準備紋理
  2. 繪制紋理
  3. 顯示處理後的紋理

一、 準備紋理:這裡用到的類

[GPUImageVideoCamera] -

[GPUImageBeautifyFilter] -

[GPUImageBilateralFliter] -

[GPUImageCombinationFilter] -

[GPUImageCannyEdgeDetectionFilter] -

準備 過程:

第一個紋理:

1、GPUImageVideoCamera捕獲攝像頭圖像

調用newFrameReadyAtTime: atIndex:通知GPUImageBeautifyFilter;

2、GPUImageBeautifyFilter調用newFrameReadyAtTime: atIndex:

通知GPUImageBilateralFliter輸入紋理已經準備好;

第二個紋理:

3、GPUImageBilateralFliter 繪制圖像後,

informTargetsAboutNewFrameAtTime(),

調用setInputFramebufferForTarget: atIndex:

把繪制的圖像設定為GPUImageCombinationFilter輸入紋理,

并通知GPUImageCombinationFilter紋理已經繪制完畢;

4、GPUImageBeautifyFilter調用newFrameReadyAtTime: atIndex:

通知 GPUImageCannyEdgeDetectionFilter輸入紋理已經準備好;

第三個紋理:

5、同3,GPUImageCannyEdgeDetectionFilter 繪制圖像後,

把圖像設定為GPUImageCombinationFilter輸入紋理;

6、GPUImageBeautifyFilter調用newFrameReadyAtTime: atIndex:

通知 GPUImageCombinationFilter輸入紋理已經準備好;

原文:http://blog.sina.com.cn/s/blog_61bc01360102wpl2.html

二、繪制紋理:

7、判斷紋理數量

GPUImageCombinationFilter判斷是否有三個紋理,三個紋理都已經準備好後

調用GPUImageThreeInputFilter的繪制函數renderToTextureWithVertices: textureCoordinates:,

圖像繪制完後,把圖像設定為GPUImageHSBFilter的輸入紋理,

通知GPUImageHSBFilter紋理已經繪制完畢;

8、繪制紋理

GPUImageHSBFilter調用renderToTextureWithVertices:

textureCoordinates:繪制圖像,

完成後把圖像設定為GPUImageView的輸入紋理,并通知GPUImageView輸入紋理已經繪制完畢;

顯示紋理

9、GPUImageView把輸入紋理繪制到自己的幀緩存,然後通過

[self.context presentRenderbuffer:GL_RENDERBUFFER];顯示到UIView上。

GPUImageBeautifyFilter.m檔案是這樣的

//
//  GPUImageBeautifyFilter.m
//  BeautifyFaceDemo
//
//  Created by guikz on 16/4/28.
//  Copyright © 2016年 guikz. All rights reserved.
//

#import "GPUImageBeautifyFilter.h"

// Internal CombinationFilter(It should not be used outside)
@interface GPUImageCombinationFilter : GPUImageThreeInputFilter
{
    GLint smoothDegreeUniform;
}

@property (nonatomic, assign) CGFloat intensity;

@end

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 <  && r >  && g >  && b >  && r > b && (max(max(r, g), b) - min(min(r, g), b)) >  && abs(r-g) > ) {
         smooth = ( - smoothDegree) * (origin - bilateral) + bilateral;
     }
     else {
         smooth = origin;
     }
     smooth.r = log( +  * smooth.r)/log();
     smooth.g = log( +  * smooth.g)/log();
     smooth.b = log( +  * smooth.b)/log();
     gl_FragColor = smooth;
 }
 );

@implementation GPUImageCombinationFilter

- (id)init {
    if (self = [super initWithFragmentShaderFromString:kGPUImageBeautifyFragmentShaderString]) {
        smoothDegreeUniform = [filterProgram uniformIndex:@"smoothDegree"];
    }
    self.intensity = ;
    return self;
}

- (void)setIntensity:(CGFloat)intensity {
    _intensity = intensity;
    [self setFloat:intensity forUniform:smoothDegreeUniform program:filterProgram];
}

@end

@implementation GPUImageBeautifyFilter

- (id)init;
{
    if (!(self = [super init]))
    {
        return nil;
    }

    // First pass: face smoothing filter
    bilateralFilter = [[GPUImageBilateralFilter alloc] init];
    bilateralFilter.distanceNormalizationFactor = ;
    [self addFilter:bilateralFilter];

    // Second pass: edge detection
    cannyEdgeFilter = [[GPUImageCannyEdgeDetectionFilter alloc] init];
    [self addFilter:cannyEdgeFilter];

    // Third pass: combination bilateral, edge detection and origin
    combinationFilter = [[GPUImageCombinationFilter alloc] init];
    [self addFilter:combinationFilter];

    // Adjust HSB
    hsbFilter = [[GPUImageHSBFilter alloc] init];
    [hsbFilter adjustBrightness:];
    [hsbFilter adjustSaturation:];

    [bilateralFilter addTarget:combinationFilter];
    [cannyEdgeFilter addTarget:combinationFilter];

    [combinationFilter addTarget:hsbFilter];

    self.initialFilters = [NSArray arrayWithObjects:bilateralFilter,cannyEdgeFilter,combinationFilter,nil];
    self.terminalFilter = hsbFilter;

    return self;
}


#pragma mark 繪制第一個紋理

- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
{
    for (GPUImageOutput<GPUImageInput> *currentFilter in self.initialFilters)
    {
        if (currentFilter != self.inputFilterToIgnoreForUpdates)
        {
            if (currentFilter == combinationFilter) {
                textureIndex = ;
            }
            [currentFilter newFrameReadyAtTime:frameTime atIndex:textureIndex];
        }
    }
}

- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;
{
    for (GPUImageOutput<GPUImageInput> *currentFilter in self.initialFilters)
    {
        if (currentFilter == combinationFilter) {
            textureIndex = ;
        }
        [currentFilter setInputFramebuffer:newInputFramebuffer atIndex:textureIndex];
    }
}

@end