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 ...
随机推荐
- Visaul Studio 常用快捷键的动画演示
从本篇文章开始,我将会陆续介绍提高 VS 开发效率的文章,欢迎大家补充~ 在进行代码开发的时候,我们往往会频繁的使用键盘.鼠标进行协作,但是切换使用两种工具会影响到我们的开发速度,如果所有的操作都可以 ...
- SSH实战 · 唯唯乐购项目(上)
前台需求分析 一:用户模块 注册 前台JS校验 使用AJAX完成对用户名(邮箱)的异步校验 后台Struts2校验 验证码 发送激活邮件 将用户信息存入到数据库 激活 点击激活邮件中的链接完成激活 根 ...
- JavaScript Math和Number对象
目录 1. Math 对象:数学对象,提供对数据的数学计算.如:获取绝对值.向上取整等.无构造函数,无法被初始化,只提供静态属性和方法. 2. Number 对象 :Js中提供数字的对象.包含整数.浮 ...
- 了解PHP中的Array数组和foreach
1. 了解数组 PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.详细的解释可参见:PHP.net中的Array数组 . 2.例子:一般的数组 这里,我 ...
- OpenSceneGraph in ActiveX by ActiveQt
OpenSceneGraph in ActiveX by ActiveQt eryar@163.com Abstract. Qt’s ActiveX and COM support allows Qt ...
- FragmentTabHost的基本用法
开通博客以来已经约莫1个月了.几次想提笔写写东西,但总是由于各种各样的原因并没有开始.现在,年假刚结束,项目也还没有开始,但最终促使我写这篇博客的是,看了一篇博友写的新年计划,说是要在新的一年中写50 ...
- 设计模式之行为类模式大PK
行为类模式大PK 行为类模式包括责任链模式.命令模式.解释器模式.迭代器模式.中介者模式.备忘录模式.观察者模式.状态模式.策略 ...
- Java中常用集合操作
一.Map 名值对存储的. 常用派生类HashMap类 添加: put(key,value)往集合里添加数据 删除: clear()删除所有 remove(key)清除单个,根据k来找 获取: siz ...
- Android local.properties 文件读取
转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6202369.html 本文出自[赵彦军的博客] 在Android Studio项目里面有个local.pro ...
- Struts2日期类型转换
针对日期类java.util.Date进行类型转换,要求客户端使用"yyyy-MM-dd","yyyy/MM/dd"中的任意一种输入,并以"yyyy- ...