近些年要给直播项目面临上加美颜的效应。实时美颜滤镜的需要吗愈发多。开发同慢直播app

近年内需让直播项目受到上加美颜的职能,调研了众多SDK和开源代码(视决,涂图,七牛,金山云,videoCore等),综合成本/效果/对项目侵入性,最后决定运用同一缓基于GPUImage实现的
BeautifyFaceDemo踌躇满志颜滤镜。

趁各种各样的直播app的爆火,实时美颜滤镜的需也更多。下面用主要介绍实现美颜滤镜的法则同笔触,原理可以活动看下GPUImage原理,本文主要是GPUImageBeautifyFilter美颜滤镜的落实。美颜只是不同滤镜组合起来的成效,实际上美颜呢是一样种滤镜,只不过它构成了各种需求的滤镜,例如磨皮、美白、提高饱和度、提亮之类的。

前言

在看即首之前,如果您还无打听直播原理,请查看这篇稿子安快速的支出一个完好无缺的iOS直播app(原理篇)

支出同款款直播app,美颜功能是坏重大之,如果没有美颜功能,可能分分钟钟掉粉千万,本篇主要讲解直播中美颜功能的实现原理,并且实现美颜功能。

假如爱自己之篇章,可以关心自己微博:袁峥Seemygo

关于滤镜代码和兑现思路好交BeautifyFace
Github和作者琨君的简书中查看。

GPUImageBeautifyFilter

GPUImageBeautifyFilter大凡因GPUImage的实时美颜滤镜,包括
GPUImageBilateralFilterGPUImageCombinationFilterGPUImageHSBFilter

GPUImageBeautifyFilter.h创建上面的靶子

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

绘制步骤如下:
备纹理
绘图纹理
展示处理后底纹理

下GPUImage处理直播过程遭到美颜的流程

  • 收集视频 => 获取每一样轴图片 => 滤镜处理 => GPUImageView展示

美颜原理.png

集成GPUImageBeautifyFilter和GPUImage Framework

率先用并好GPUImage,通过观察目前iOS平台,90%上述美颜方案都是基于这个框架来开的。
原来种中的AVCaptureDevice需要替换成GPUImageVideoCamera,删除诸如AVCaptureSession/AVCaptureDeviceInput/AVCaptureVideoDataOutput这种GPUImage实现了底片段。修改部分生命周期,摄像头切换,横竖屏旋转等息息相关逻辑,保证前后行为统一。

声明需要之性能

 @property (nonatomic, strong) GPUImageVideoCamera *videoCamera;  
 //屏幕上显示的View
 @property (nonatomic, strong) GPUImageView *filterView;
 //BeautifyFace美颜滤镜
 @property (nonatomic, strong) GPUImageBeautifyFilter *beautifyFilter;

接下来初始化

  self.sessionPreset = AVCaptureSessionPreset1280x720;
  self.videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:self.sessionPreset cameraPosition:AVCaptureDevicePositionBack];

  self.filterView = [[GPUImageView alloc] init];
  [self.view insertSubview:self.filterView atIndex:1]; //省略frame的相关设置

  //这里我在GPUImageBeautifyFilter中增加个了初始化方法用来设置美颜程度intensity
  self.beautifyFilter = [[GPUImageBeautifyFilter alloc] initWithIntensity:0.6];

啊filterView增加美颜滤镜

[self.videoCamera addTarget:self.beautifyFilter];
[self.beautifyFilter addTarget:self.filterView];

下一场调用startCameraCapture方法就可以看到职能了

[self.videoCamera startCameraCapture];

暨这边,仅仅是屏幕显示的情节包含滤镜效果,而当直播应用,还得输出带有美颜功能的视频流

同样、 准备纹理(将要以的好像)

[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、GPUImageCannyEdgeDetectionFilter 绘制图像后,
管图像设置也GPUImageCombinationFilter输入纹理;
6、GPUImageBeautifyFilter调用newFrameReadyAtTime: atIndex:
通报 GPUImageCombinationFilter输入纹理已经准备好;

纹理准备.png

美颜基本概念

GPU:(Graphic Processor
Unit图形处理单元)手机或电脑用于图像处理同渲染之硬件

GPU工作原理:采集数据-> 存入主内存(RAM) -> CPU(计算处理) ->
存入显存(VRAM) -> GPU(完成图像渲染) -> 帧缓冲区 -> 显示器

GPU工作原理.jpg

OpenGL ES:(Open Graphics Library For Embedded(嵌入的) Systems
开源嵌入式系统图形处理框架),一效仿图和硬件接口,用于把拍卖好之图纸显示到屏幕及。

GPUImage:是一个根据OpenGL ES
2.0图像以及视频拍卖的开源iOS框架,提供各种各样的图像处理滤镜,并且支持照相机和摄像机的实时滤镜,内置120多种滤镜效果,并且会打定义图像滤镜。

滤镜处理的原理:就是将静态图片或视频的各个一样帧进行图纸变换再显示出。它的精神就是像素点的坐标和颜色变化

输出带有美颜功效的视频流

碰巧开头并的下遇到一个坑,原本的逻辑是实现AVCaptureVideoDataOutputSampleBufferDelegate方法来得到原始帧

- (void) captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;

倘GPUImageVideoCamera也兑现了一个好像的代办:

@protocol GPUImageVideoCameraDelegate <NSObject>
@optional
- (void)willOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer;
@end

只要替换下发现输出的流依旧是未经美颜的图像,看了贯彻后发现果然,GPUImageVideoCameraDelegate还是经过AVCaptureVideoDataOutputSampleBufferDelegate直接回的多寡,所以想出口带有滤镜的流淌这里就是得依靠GPUImageRawDataOutput了

CGSize outputSize = {720, 1280};
GPUImageRawDataOutput *rawDataOutput = [[GPUImageRawDataOutput alloc] initWithImageSize:CGSizeMake(outputSize.width, outputSize.height) resultsInBGRAFormat:YES];
[self.beautifyFilter addTarget:rawDataOutput];

夫GPUImageRawDataOutput其实就是beautifyFilter的出口器,可于setNewFrameAvailableBlock方法的block中获得含滤镜效果的数量

__weak GPUImageRawDataOutput *weakOutput = rawDataOutput;
__weak typeof(self) weakSelf = self;

[rawDataOutput setNewFrameAvailableBlock:^{
    __strong GPUImageRawDataOutput *strongOutput = weakOutput;
    [strongOutput lockFramebufferForReading];

    // 这里就可以获取到添加滤镜的数据了
    GLubyte *outputBytes = [strongOutput rawBytesForImage];
    NSInteger bytesPerRow = [strongOutput bytesPerRowInOutput];
    CVPixelBufferRef pixelBuffer = NULL;
    CVPixelBufferCreateWithBytes(kCFAllocatorDefault, outputSize.width, outputSize.height, kCVPixelFormatType_32BGRA, outputBytes, bytesPerRow, nil, nil, nil, &pixelBuffer);

    // 之后可以利用VideoToolBox进行硬编码再结合rtmp协议传输视频流了
    [weakSelf encodeWithCVPixelBufferRef:pixelBuffer];

    [strongOutput unlockFramebufferAfterReading];
    CFRelease(pixelBuffer);

}];

其次、绘制纹理:

7、判断纹理数量
GPUImageCombinationFilter判断是否有三单纹理,三只纹理都早就准备好后
调用GPUImageThreeInputFilter的绘图函数renderToTextureWithVertices:
textureCoordinates:,
图像绘制了后,把图像设置也GPUImageHSBFilter的输入纹理,
通报GPUImageHSBFilter纹理已经绘制了;

8、绘制纹理
GPUImageHSBFilter调用renderToTextureWithVertices:
textureCoordinates:绘制图像,
形成后把图像设置也GPUImageView的输入纹理,并通报GPUImageView输入纹理已经绘制了;

GPUImage处理画面原理

  • GPUImage采用链式方式来处理画面,通过addTarget:方法为链条长每个环节的靶子,处理完毕一个target,就见面将上一个环节处理好之图像数据传递下一个target去处理,称为GPUImage处理链。
    • 照:墨镜原理,从外界传来光线,会经过墨镜过滤,在传给我们的眼睛,就能感受到大白天也是乌黑一片,哈哈
    • 诚如的target可分为两类
      • 中间环节的target, 一般是各种filter,
        是GPUImageFilter或者是子类.
      • 最终环节的target, GPUImageView:用于展示到屏幕及,
        或者GPUImageMovieWriter:写成视频文件。
  • GPUImage处理重大分为3独环节
    • source(视频、图片源) -> filter(滤镜) -> final target (处理后视频、图片)
    • GPUImaged的Source:都累GPUImageOutput的子类,作为GPUImage的数据源,就哼于外面的光明,作为眼睛的输出源
      • GPUImageVideoCamera:用于实时拍摄视频
      • GPUImageStillCamera:用于实时拍摄照
      • GPUImagePicture:用于拍卖已经拍照好之图纸,比如png,jpg图片
      • GPUImageMovie:用于拍卖已经拍摄好之视频,比如mp4文件
    • GPUImage的filter:GPUimageFilter类或者子类,这个仿佛继承自GPUImageOutput,并且遵守GPUImageInput协议,这样既会流进,又会流出,就哼于咱的墨镜,光线通过墨镜的拍卖,最终进我们肉眼
    • GPUImage的final target:GPUImageView,GPUImageMovieWriter就好于我们肉眼,最终输入目标。

GPUImage处理原理.png

时还是在的题材

经和其它产品比,GPUImageBeautifyFilter磨皮效果及花椒最为接近。这里以双边滤波,
花椒应该据此了高斯模糊实现。同印客对比,美白作用一般。

其三、显示纹理

9、GPUImageView把输入纹理绘制到温馨的帧缓存,然后经
[self.context presentRenderbuffer:GL_RENDERBUFFER];显示到UIView上。

GPUImageBeautifyFilter.m文件

@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 < 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;
 }
 smooth.r = log(1.0 + 0.2 * smooth.r)/log(1.2);
 smooth.g = log(1.0 + 0.2 * smooth.g)/log(1.2);
 smooth.b = log(1.0 + 0.2 * smooth.b)/log(1.2);
 gl_FragColor = smooth;
}
);

@implementation GPUImageCombinationFilter

-(id)init {
if (self = [super initWithFragmentShaderFromString:kGPUImageBeautifyFragmentShaderString]) {
    smoothDegreeUniform = [filterProgram uniformIndex:@"smoothDegree"];
}
self.intensity = 0.5;
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 = 4.0;
[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:1.1];
[hsbFilter adjustSaturation:1.1];

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

[combinationFilter addTarget:hsbFilter];

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

return self;
}

#pragma mark - GPUImageInput protocol

绘制纹理

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

安装绘制图像的输入纹理

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

GPUImage集成步骤:
自从定义成滤镜美颜

  1. 使用Cocoapods导入GPUImage;
  2. 创立视频源GPUImageVideoCamera;
  3. 开创最终目的源:GPUImageView;
  4. 创办GPUImageFilterGroup滤镜组合,需要结合亮度(GPUImageBrightnessFilter)和双面滤波(GPUImageBilateralFilter)这点儿独滤镜达到美颜功效;
  5. 安装滤镜组链;
  6. 设置GPUImage处理链,从数额源 -> 滤镜 -> 最终界面效果;
  7. 开采集视频。

-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"GPUImage美颜";

[self initBottomView];

//  1. 创建视频摄像头
// SessionPreset:屏幕分辨率,AVCaptureSessionPresetHigh会自适应高分辨率
// cameraPosition:摄像头方向
// 最好使用AVCaptureSessionPresetHigh,会自动识别,如果用太高分辨率,当前设备不支持会直接报错
GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPresetHigh cameraPosition:AVCaptureDevicePositionFront];

//  2. 设置摄像头输出视频的方向
videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
_videoCamera = videoCamera;

//  3. 创建用于展示视频的GPUImageView
GPUImageView *captureVideoPreview = [[GPUImageView alloc] initWithFrame:self.view.bounds];
[self.view insertSubview:captureVideoPreview atIndex:0];

//  4.创建磨皮、美白组合滤镜
GPUImageFilterGroup *groupFliter = [[GPUImageFilterGroup alloc] init];

//  5.磨皮滤镜
GPUImageBilateralFilter *bilateralFilter = [[GPUImageBilateralFilter alloc] init];
[groupFliter addFilter:bilateralFilter];
_bilateralFilter = bilateralFilter;

//  6.美白滤镜
GPUImageBrightnessFilter *brightnessFilter = [[GPUImageBrightnessFilter alloc] init];
[groupFliter addFilter:brightnessFilter];
_brightnessFilter = brightnessFilter;


//  7.设置滤镜组链
[bilateralFilter addTarget:brightnessFilter];
[groupFliter setInitialFilters:@[bilateralFilter]];
groupFliter.terminalFilter = brightnessFilter;

//  8.设置GPUImage处理链 从数据源->滤镜->界面展示
[videoCamera addTarget:groupFliter];
[groupFliter addTarget:captureVideoPreview];

//  9.调用startCameraCapture采集视频,底层会把采集到的视频源,渲染到GPUImageView上,接着界面显示
[videoCamera startCameraCapture];
}

ps:

  1. GPUImageVideoCamera必须要高引用,否则在搜集视频过程遭到见面被销毁;
  2. 须调用startCameraCapture,底层才见面把募集到之张频源,渲染到GPUImageView中才能够显得;
  3. GPUImageBilateralFilter的distanceNormalizationFactor值越聊,磨皮效果更加好,distanceNormalizationFactor取值范围:
    大于1。

以美颜滤镜GPUImageBeautifyFilter实现
1、使用Cocoapods导入GPUImage;
2、导入GPUImageBeautifyFilter文件夹;
3、创建视频源GPUImageVideoCamera;
4、创建最终目的源:GPUImageView;
5、创建最终美颜滤镜:GPUImageBeautifyFilter;
6、设置GPUImage处理链,从数额源 -> 滤镜 -> 最终界面显示。

-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"Beautify美颜";

UISwitch *switcher = [[UISwitch alloc] initWithFrame:CGRectMake(140, 80, 70, 30)];
[switcher addTarget:self action:@selector(changeBeautyFilter:) forControlEvents:UIControlEventValueChanged];

[self.view addSubview:switcher];

//  1. 创建视频摄像头
// SessionPreset:屏幕分辨率,AVCaptureSessionPresetHigh会自适应高分辨率
// cameraPosition:摄像头方向
// 最好使用AVCaptureSessionPresetHigh,会自动识别,如果用太高分辨率,当前设备不支持会直接报错
GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPresetHigh cameraPosition:AVCaptureDevicePositionFront];

//  2. 设置摄像头输出视频的方向
videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
_videoCamera = videoCamera;


//  3. 创建用于展示视频的GPUImageView
GPUImageView *captureVideoPreview = [[GPUImageView alloc] initWithFrame:self.view.bounds];
[self.view insertSubview:captureVideoPreview atIndex:0];
_captureVideoPreview = captureVideoPreview;

//  4.设置处理链
[_videoCamera addTarget:_captureVideoPreview];

//  5.调用startCameraCapture采集视频,底层会把采集到的视频源,渲染到GPUImageView上,接着界面显示
[videoCamera startCameraCapture];
}

切换美颜的时如果活动处理链

// 移除之前所有处理链
[_videoCamera removeAllTargets];

// 创建美颜滤镜
GPUImageBeautifyFilter *beautifyFilter = [[GPUImageBeautifyFilter alloc] init];

// 设置GPUImage处理链,从数据源 => 滤镜 => 最终界面效果
[_videoCamera addTarget:beautifyFilter];
[beautifyFilter addTarget:_captureVideoPreview];

demo下载

美颜原理

  • 磨皮(GPUImageBilateralFilter):本质就是是吃诸如素点模糊,可以采取高斯歪曲,但是也许导致边缘会无清楚,用两者滤波(Bilateral
    Filter) ,有指向的混淆像素点,能保证边缘不叫歪曲。
  • 美白(GPUImageBrightnessFilter):本质就是是增强亮度。
还存在些关于性的题材:

1 调用setNewFrameAvailableBlock后多机型只能走至不多不少15fps
2 在6s这代表机型上温度格外高,帧率可至30fps但未安宁

图像处理

落影lying-in的GPUImage详细解析对GPUImage实现美颜滤镜的原理同笔触做了详尽介绍,很多关于图像处理的知识写的深详细,很受用。

参考文献
http://www.jianshu.com/p/2ce9b63ecfef
http://www.jianshu.com/p/4646894245ba

美颜功能

  • 关注效果,忽悠本人

Update(8-13)

  1. 关于性问题,最近将路被融为一体的美颜滤镜(BeautifyFace)里用到之
    GPUImageCannyEdgeDetectionFilter 替换为
    GPUImageSobelEdgeDetectionFilter
    会有十分特别改善,而且意义几乎一模一样,6s透过长时测试没有再次出现高温警告了。(替换为酷简易,直接改俩处类名/变量名就是得了)

  2. 享用一个BUG,最近察觉当展美颜的上,关闭直播内存还是没有放。分析得出GPUImageRawDataOutput的setNewFrameAvailableBlock方法的block参数还维持在self,解决思路就是是将GPUImageRawDataOutput移除。

事先附上之前的系release代码:

    [self.videoCamera stopCameraCapture];
    [self.videoCamera removeInputsAndOutputs];
    [self.videoCamera removeAllTargets];

发端以为camera调用removeAllTargets会把camera上面的filter,以及filter的output一同释放,但骨子里camera并无见面’帮忙’移除filter的target,所以需要加上:

    [self.beautifyFilter removeAllTargets]; //修复开启美颜内存无法释放的问题

关美颜output是直加于camera上,camera直接removeAllTargets就足以;
开启美颜output加于filter上,camera和filter都需removeAllTargets。

GPUImage原生美颜功能

GPUImage原生.gif

使美颜滤镜实现效益

春风得意颜滤镜处理.gif

GPUImage实战

GPUImage原生美颜

  • 步骤一:使用Cocoapods导入GPUImage
  • 手续二:创建视频源GPUImageVideoCamera
  • 步骤三:创建最终目的源:GPUImageView
  • 步骤四:创建滤镜组(GPUImageFilterGroup),需要结合亮度(GPUImageBrightnessFilter)双边滤波(GPUImageBilateralFilter)立刻点儿只滤镜达到美颜效果.
  • 步骤五:设置滤镜组链
  • 步骤六:设置GPUImage处理链,从数源 => 滤镜 => 最终界面效果
  • 手续七:开始采集视频

注意点:

  • SessionPreset极好利用AVCaptureSessionPresetHigh,会自动识别,如果因此最高分辨率,当前设备未支持会一直报错
  • GPUImageVideoCamera必须要强引用,否则会受销毁,不可知循环不断搜集视频.
  • 必须调用startCameraCapture,底层才会拿集到的看出频源,渲染到GPUImageView中,就会显示了。
  • GPUImageBilateralFilter的distanceNormalizationFactor价值更聊,磨皮效果更加好,distanceNormalizationFactor取值范围:
    大于1

- (void)viewDidLoad {
    [super viewDidLoad];

    // 创建视频源
    // SessionPreset:屏幕分辨率,AVCaptureSessionPresetHigh会自适应高分辨率
    // cameraPosition:摄像头方向
    GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPresetHigh cameraPosition:AVCaptureDevicePositionFront];
     videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
    _videoCamera = videoCamera;

    // 创建最终预览View
    GPUImageView *captureVideoPreview = [[GPUImageView alloc] initWithFrame:self.view.bounds];
    [self.view insertSubview:captureVideoPreview atIndex:0];

    // 创建滤镜:磨皮,美白,组合滤镜
    GPUImageFilterGroup *groupFilter = [[GPUImageFilterGroup alloc] init];

    // 磨皮滤镜
    GPUImageBilateralFilter *bilateralFilter = [[GPUImageBilateralFilter alloc] init];
    [groupFilter addTarget:bilateralFilter];
    _bilateralFilter = bilateralFilter;

    // 美白滤镜
    GPUImageBrightnessFilter *brightnessFilter = [[GPUImageBrightnessFilter alloc] init];
    [groupFilter addTarget:brightnessFilter];
    _brightnessFilter = brightnessFilter;

    // 设置滤镜组链
    [bilateralFilter addTarget:brightnessFilter];
    [groupFilter setInitialFilters:@[bilateralFilter]];
    groupFilter.terminalFilter = brightnessFilter;

    // 设置GPUImage响应链,从数据源 => 滤镜 => 最终界面效果
    [videoCamera addTarget:groupFilter];
    [groupFilter addTarget:captureVideoPreview];

    // 必须调用startCameraCapture,底层才会把采集到的视频源,渲染到GPUImageView中,就能显示了。
    // 开始采集视频
    [videoCamera startCameraCapture];
}

- (IBAction)brightnessFilter:(UISlider *)sender {
    _brightnessFilter.brightness = sender.value;
}

- (IBAction)bilateralFilter:(UISlider *)sender {
    // 值越小,磨皮效果越好
    CGFloat maxValue = 10;
    [_bilateralFilter setDistanceNormalizationFactor:(maxValue - sender.value)];
}

应用美颜滤镜实现

  • 步骤一:使用Cocoapods导入GPUImage
  • 步骤二:导入GPUImageBeautifyFilter文件夹
  • 手续三:创建视频源GPUImageVideoCamera
  • 步骤四:创建最终目的源:GPUImageView
  • 步骤五:创建最终美颜滤镜:GPUImageBeautifyFilter
  • 手续六:设置GPUImage处理链,从数额源 => 滤镜 => 最终界面效果

注意:

  • 切换美颜效果原理:移除之前所有处理链,重新安处理链

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    // 创建视频源
    // SessionPreset:屏幕分辨率,AVCaptureSessionPresetHigh会自适应高分辨率
    // cameraPosition:摄像头方向
    GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPresetHigh cameraPosition:AVCaptureDevicePositionFront];
    videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
    _videoCamera = videoCamera;

    // 创建最终预览View
    GPUImageView *captureVideoPreview = [[GPUImageView alloc] initWithFrame:self.view.bounds];
    [self.view insertSubview:captureVideoPreview atIndex:0];
    _captureVideoPreview = captureVideoPreview;

    // 设置处理链
    [_videoCamera addTarget:_captureVideoPreview];

    // 必须调用startCameraCapture,底层才会把采集到的视频源,渲染到GPUImageView中,就能显示了。
    // 开始采集视频
    [videoCamera startCameraCapture];

}

- (IBAction)openBeautifyFilter:(UISwitch *)sender {

    // 切换美颜效果原理:移除之前所有处理链,重新设置处理链
    if (sender.on) {

        // 移除之前所有处理链
        [_videoCamera removeAllTargets];

        // 创建美颜滤镜
        GPUImageBeautifyFilter *beautifyFilter = [[GPUImageBeautifyFilter alloc] init];

        // 设置GPUImage处理链,从数据源 => 滤镜 => 最终界面效果
        [_videoCamera addTarget:beautifyFilter];
        [beautifyFilter addTarget:_captureVideoPreview];

    } else {

        // 移除之前所有处理链
        [_videoCamera removeAllTargets];
        [_videoCamera addTarget:_captureVideoPreview];
    }


}

GPUImage扩展

  • GPUImage所有滤镜介绍
  • 得意忘形颜滤镜
  • 得意忘形图秀秀滤镜大集中

源码下载

源码
专注:第一不好打开需要 pod install

结束语

接轨还会见教GPUImage原理openGL
ES,视频编码,推流,聊天室,礼物系统等更多职能,敬请关注!!!

相关文章