由于最近需要做一些美颜相关的工作,在百度上面进行一番搜索发现关于美颜磨皮的相关资料很少。本人对美颜相关的算法一点都不会。只能研究相关的三方框架。下面介绍一下开源框架GPUimage如何实现我们的人脸磨皮功能
首先我们在项目中导入 生成好的包 GUPimage.framework 下载地址:http://download.csdn.net/download/conslee/8386145
下面是我们的主要类容 GPUImageBeautifyFilter类 是一个自定义的美颜滤镜,可以用来处理实时视频流或者是静态图片主要原理是双边滤波、Canny边缘检测和肤色检测
GPUImageBeautifyFilter.h文件
#import
@class GPUImageCombinationFilter;
@interface GPUImageBeautifyFilter : GPUImageFilterGroup {
GPUImageBilateralFilter *bilateralFilter;
GPUImageCannyEdgeDetectionFilter *cannyEdgeFilter;
GPUImageCombinationFilter *combinationFilter;
GPUImageHSBFilter *hsbFilter;
}
@end
GPUImageBeautifyFilter.m文件
#import "GPUImageBeautifyFilter.h"
#import "GPUImageThreeInputFilter.h"
// Internal CombinationFilter(It should not be used outside)
@interface GPUImageCombinationFilter : GPUImageThreeInputFilter{ GLint smoothDegreeUniform;}@property (nonatomic, assign) CGFloat intensity;@endNSString *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 -#pragma mark GPUImageInput protocol- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;{ for (GPUImageOutput*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*currentFilter in self.initialFilters)
{
if (currentFilter == combinationFilter) {
textureIndex = 2;
}
[currentFilter setInputFramebuffer:newInputFramebuffer atIndex:textureIndex];
}
}
@end
有了我们的核心模块 下面再介绍一下另外一个类 GPUImageThreeInputFilter 这个类在我们的GPUimage.framwork包里面有问题,在外面调用不上(亲测)但是我们必须要使用到这个类 我们就需要在Gpuimage开源项目中将这个类单独提出来
准备好了这两步之后 我就不啰嗦了 直接上代码
UIImage *image=[UIImage imageNamed:@"LSS.jpg"];
UIImageView *image1=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 200, 200)];
image1.image=image;
[self.view addSubview:image1];
NSLog(@"%@",image);
// GPUImageBrightnessFilter *filter = [[GPUImageBrightnessFilter alloc] init];
// filter.brightness=0.2;
//磨皮
GPUImagePicture *pic = [[GPUImagePicture alloc] initWithImage:image];
GPUImageBeautifyFilter *filter = [[GPUImageBeautifyFilter alloc] init];
[filter forceProcessingAtSize:image.size];
[pic addTarget:filter];
[pic processImage];
[filter useNextFrameForImageCapture];
image =[filter imageFromCurrentFramebuffer];
//image=[self filteredImage:image withFilterName:@"CILinearToSRGBToneCurve" ];
UIImageView *image2=[[UIImageView alloc]initWithFrame:CGRectMake(0,200, 200, 200)];
image2.image=image;
[self.view addSubview:image2];
NSLog(@"%@",image);
最后的效果图 附上女神一张 漂亮吧 自己再配上滤镜吧