iOS从零开始学习直播之3.美颜
任何一款直播软件都必须进行美颜,不然哪来的那么多美女,所以技术改变世界,不只是说说而已。美颜在采集的时候就得就行,让主播实时看到直播的效果。
1.美颜原理
其实美颜的本质就是美白和磨皮,分别通过提高亮度和模糊像素点进行。我们一般用GPUImage这个开源的图像处理库来实现。视频的本质就是一张张连续的图片,磨皮就是对于图片上的像素点的取值与周边的像素点取值相关联。常见的有高斯模糊和双边滤波(Bilateral Filter)。
高斯模糊是最常见的一种模糊方式,像素点取值是由周边像素点求加权平均所得,而权重系数则是像素间的距离的高斯函数,大致关系是距离越小、权重系数越大。高斯模糊会导致边缘不清晰。
双边滤波是有针对点的模糊像素点,能保证边缘不被模糊。
2.GPUImage介绍
GPUImage 是一个开源的基于GPU的图片或视频的处理框架,其本身内置了多达120多种常见的滤镜效果。有了它,添加实时的滤镜只需要简单地添加几行代码,非常强大。想研究源码的同学上,可以去GitHub上下载。
3.效果

&esmp;&esmp;请原谅这篇只有UI效果图。用两个Slider来控制磨皮和美白的效果,从上到下取值范围分别为[-1,1] [0,100];
4.GPUImage使用方法
1.用CocoaPods集成到项目中。
pod 'GPUImage', '~> 0.1.7'
2.代码演示
#import "FHUImageFilterViewController.h"
#import <GPUImage/GPUImage.h>
@interface FHUImageFilterViewController ()
// 视频源
@property (nonatomic, strong)GPUImageVideoCamera *videoCamera;
// 磨皮滤镜
@property (nonatomic, weak)GPUImageBilateralFilter *bilateralFilter;
// 美白滤镜
@property (nonatomic, weak)GPUImageBrightnessFilter *brightnessFilter;
@end
@implementation FHUImageFilterViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 创建视屏源
/*
* sessionPreset : 屏幕分辨率
* cameraPosition: 摄像头位置
**/
GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPresetHigh cameraPosition:AVCaptureDevicePositionFront];
// 设置输出图像方向
videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
self.videoCamera = videoCamera;
// 创建最终预览View
GPUImageView *captureVideoPreview = [[GPUImageView alloc] initWithFrame:self.view.bounds];
captureVideoPreview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view insertSubview:captureVideoPreview atIndex:0];
// 创建滤镜:磨皮,美白,组合滤镜
GPUImageFilterGroup *groupFilter = [[GPUImageFilterGroup alloc] init];
// 磨皮滤镜
GPUImageBilateralFilter *bilateraFilter = [[GPUImageBilateralFilter alloc] init];
[groupFilter addTarget:bilateraFilter];
_bilateralFilter = bilateraFilter;
// 美白滤镜
GPUImageBrightnessFilter *brightnessFilter = [[GPUImageBrightnessFilter alloc] init];
[groupFilter addTarget:brightnessFilter];
_brightnessFilter = brightnessFilter;
// 设置滤镜组链
[bilateraFilter addTarget:brightnessFilter];
[groupFilter setInitialFilters:@[bilateraFilter]];
groupFilter.terminalFilter = brightnessFilter;
// 设置GPUImage的响应链, 从数据源 ==> 滤镜 ==> 最终界面效果
[videoCamera addTarget:groupFilter];
[groupFilter addTarget:captureVideoPreview];
// 必须采用startCameraCapture, 底层才会把采集到的视频源,渲染到GPUImageView中,就能显示了。
[videoCamera startCameraCapture];
}
备注:手机分辨率(sessionPreset)有13个值可选,但最好设置成AVCaptureSessionPresetHigh,手机会自动识别。如果设置的太高,手机不支持,会直接报错。
- (IBAction)brightnessFiller:(id)sender {
UISlider *slider = (UISlider *)sender;
// 亮度(brightness)
_brightnessFilter.brightness = slider.value;
}
- (IBAction)bilateralFilter:(id)sender {
UISlider *slider = (UISlider *)sender;
CGFloat maxValue = 100;
//平滑因子(distanceNormalizationFactor)
_bilateralFilter.distanceNormalizationFactor = maxValue - slider.value;
NSLog(@"distanceNormalizationFactor=%f",_bilateralFilter.distanceNormalizationFactor);
}
备注:(1)亮度(brightness)取值范围[-1,1],0为正常状态,默认。
(2)平滑因子(distanceNormalizationFactor)值越小,磨皮效果越好,默认为8。我为了演示效果,把最大值设置成100,这样几乎就没有磨皮效果了,平时最好10以内。最好大于0,不然就会变形。
5.自定义滤镜
如果你感觉GPUImage自带的滤镜不够用的话,也可以自定义滤镜,使用方式和上面的差不多。我以一个别人写的美颜滤镜为例。
1.demo下载地址。把GPUImageBeautifyFilter文件夹导入你的工程中。
2.代码演示
#import "FHBeautyViewController.h"
#import "GPUImageBeautifyFilter.h"
#import <GPUImage/GPUImage.h>
@interface FHBeautyViewController ()
//视频源一定要强引用
@property(nonatomic,strong) GPUImageVideoCamera *videoCamera;
@end
@implementation FHBeautyViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 创建视频源
_videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPresetHigh cameraPosition:AVCaptureDevicePositionFront];
_videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
// 创建美颜滤镜
GPUImageBeautifyFilter *beautifyFilter = [[GPUImageBeautifyFilter alloc] init];
// 创建最终预览View
GPUImageView *captureVideoPreview = [[GPUImageView alloc] initWithFrame:self.view.bounds];
captureVideoPreview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view insertSubview:captureVideoPreview atIndex:0];
// 设置GPUImage处理链,从数据源 => 滤镜 => 最终界面效果
[_videoCamera addTarget:beautifyFilter];
[beautifyFilter addTarget:captureVideoPreview];
// 开始采集视屏
[_videoCamera startCameraCapture];
}
6.demo下载
demo下载地址。下载下来运行,发现报错。

那是因为我没有在工程里上传ijkplayer视屏直播框架,我能上传上去,但下载太慢了,什么原因大家都懂得。我把ijkplayer视屏直播框架放到百度云上了,没有密码,下载下来之后,放到LiveAppDemo-master文件夹里,重新打开就可以运行了。

iOS从零开始学习直播之3.美颜的更多相关文章
- iOS从零开始学习直播之2.采集
直播的采集由采集的设备(摄像头.话筒)不同分为视频采集和音频采集,本篇文章会分别介绍. 1.采集步骤 1.创建捕捉会话(AVCaptureSession),iOS调用相机和话筒之前都需要创建捕 ...
- iOS从零开始学习直播之1.播放
对于直播来说,客户端主要做两件事情,推流和播放.今天先讲播放. 播放流程 1.拉流:服务器已有直播内容,从指定地址进行拉取的过程.其实就是向服务器请求数据. 2.解码:对视屏数据进行解压缩. 3. ...
- iOS从零开始学习直播之音频1.播放本地音频文件
现在直播越来越火,俨然已经成为了下一个红海.作为一个资深码农(我只喜欢这样称呼自己,不喜欢别人这样称呼我),我必须赶上时代的潮流,开始研究视频直播.发现视屏直播类的文章上来就讲拉流.推流.采集.美 ...
- iOS从零开始学习直播之音频4.歌词
上一篇讲了歌曲的切换,这一篇主要讲歌词部分的实现. 先看效果图.当歌手唱到这句歌词时候,我们要标记出来,这里显示字体为黄色. 1.获取歌词 一般歌词都是一个链接.类似于"http ...
- iOS从零开始学习直播之音频3.歌曲切换
上周迟到了,周末去参加OSC源创会了,还是有点启发的.但这不是重点,重点是 上一篇我只是实现了一首歌曲的在线播放,这肯定是不够的.这一篇博客主要是实现了多首歌曲的顺序播放以及上一首和下一首切换. ...
- iOS从零开始学习直播之音频2.后台播放和在线播放
本篇主要讲音频的后台播放和在线播放. 后台播放 上一篇写的工程运行之后程序退至后台,发现运行不了,歌停止了,这显然不行,音乐后台播放是标配啊.今天就来讲一下后台播放. 1.在plist文件里,告诉 ...
- 【如何快速的开发一个完整的iOS直播app】(美颜篇)
原文转自:袁峥Seemygo 感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,美颜功能是很重 ...
- 【如何快速的开发一个完整的 iOS 直播 app】(美颜篇)
来源:袁峥Seemygo 链接:http://www.jianshu.com/p/4646894245ba 前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播 ...
- 从零开始学习CocoaPods安装和使用
从零开始学习CocoaPods安装和使用 转载: Code4App原创:http://code4app.com/article/cocoapods-install-usage http://m.i ...
随机推荐
- 一次修改闭源 Entity Provider 程序集以兼容新 EntityFramework 的过程
读完本文你会知道,如何在没有源码的情况下,直接修改一个 DLL 以去除 DLL 上的强命名限制,并在该程序集上直接添加你的“友元程序集(一种特殊的 Attribute,将它应用在程序集上,使得程序集内 ...
- C# 中参数验证方式的演变
一般在写方法的时候,第一步就是进行参数验证,这也体现了编码者的细心和缜密,但是在很多时候这个过程很枯燥和乏味,比如在拿到一个API设计文档的时候,通常会规定类型参数是否允许为空,如果是字符可能有长度限 ...
- C++中的事件分发
本文意在展现一个C++实现的通用事件分发系统,能够灵活的处理各种事件.对于事件处理函数的注册,希望既能注册到普通函数,注册到事件处理类,也能注册到任意类的成员函数.这样在游戏客户端的逻辑处理中,可以非 ...
- 【原创分享·微信支付】 C# MVC 微信支付教程系列之公众号支付
微信支付教程系列之公众号支付 今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付.现在,我们讲讲这个公众号支付.公众号支付的应用环境常见的用户通过公众号,然后再通 ...
- MySQL设置字段的默认值为当前系统时间
问题产生: 当我们在对某个字段进行设置时间默认值,该默认值必须是的当前记录的插入时间,那么就将当前系统时间作为该记录创建的时间. 应用场景: 1.在数据表中,要记录每条数据是什么时候创建的,应该由数据 ...
- XSS分析及预防
XSS(Cross Site Scripting),又称跨站脚本,XSS的重点不在于跨站点,而是在于脚本的执行.在WEB前端应用日益发展的今天,XSS漏洞尤其容易被开发人员忽视,最终可能造成对个人信息 ...
- 现代3D图形编程学习-基础简介(3)-什么是opengl (译)
本书系列 现代3D图形编程学习 OpenGL是什么 在我们编写openGL程序之前,我们首先需要知道什么是OpenGL. 将OpenGL作为一个API OpenGL 通常被认为是应用程序接口(API) ...
- C++ 拷贝构造函数和赋值运算符
本文主要介绍了拷贝构造函数和赋值运算符的区别,以及在什么时候调用拷贝构造函数.什么情况下调用赋值运算符.最后,简单的分析了下深拷贝和浅拷贝的问题. 拷贝构造函数和赋值运算符 在默认情况下(用户没有定义 ...
- 使用python自动生成docker nginx反向代理配置
由于在测试环境上用docker部署了多个应用,而且他们的端口有的相同,有的又不相同,数量也比较多,在使用jenkins发版本的时候,不好配置,于是想要写一个脚本,能在docker 容器创建.停止的时候 ...
- BI分析受阻?FineBI推出SPA螺旋式分析新功能!
过去,企业级的数据分析通常会有这么几种场景,业务部门托信息部门分析数据,结果报表一出,唇枪舌剑争论你我高低,数据不准,指标不对.信息部门欠缺业务概念,业务部门不懂技术逻辑,数据分析之路,暂时搁浅. 后 ...