iOS

iOS GPUImage实时美颜滤镜

2018-10-09  本文已影响68人  FPA有缘自续
1.背景

前段时间由于项目需求,做了一个基于GPUImage的美颜+滤镜相机。现在各种各样的直播、小视频App层出不穷,美颜滤镜的需求也越来越多。为了回馈开源,现在我把它放到了GitHub上面(就上传了精华部分),感兴趣的朋友可以去下载。下面将主要介绍实现美颜滤镜的原理和思路。

2. GPUImage

GPUImage是一个开源的基于GPU的图片或视频的处理框架,其本身内置了多达120多种常见的滤镜效果。有了它,添加实时的滤镜只需要简单地添加几行代码。

摄像头开启捕获代码块

   // 设置GPUImage处理链 从数据源->滤镜->界面展示
    self.movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:[NSURL fileURLWithPath:self.moviePath] size:CGSizeMake(kCameraWidth, kCameraWidth) fileType:AVFileTypeQuickTimeMovie outputSettings:self.videoSettings];
    self.videoCamera.audioEncodingTarget = _movieWriter;
    //  这边是初始化一个美颜+美白+可爱的一个混合滤镜
    self.normalFilter = [[GPUImageFilterGroup alloc] init];
    //默认美颜 美白
    self.beautyLevel = [DSFilterInfo getBeautyValue];
    self.brightLevel = [DSFilterInfo getBrightValue];
    [self addGPUImageFilter:[[DSGPUImageBeautyFilter alloc] initCustomFilterWithBeautyValue:self.beautyLevel brightValue:self.brightLevel]];
    //默认添加可爱滤镜
    GPUImageOutput<GPUImageInput> *filter = [[DSFilterHandleTool sharedInstance] getFilterWithfilterType:LZBFilterType_Beauty];
    if (filter) [self addGPUImageFilter:filter];
    //默认美颜
    [self.videoCamera addTarget:self.normalFilter];
    [self.normalFilter addTarget:self];
   // 调用startCameraCapture采集视频,底层会把采集到的视频源,渲染到GPUImageView上,接着界面显示 (放在主线程初始化很卡)
    kDISPATCH_GLOBAL_QUEUE_DEFAULT(^{[self.videoCamera startCameraCapture]; });

GPUImage提供了拍照的方法

代码块

  [self.videoCamera capturePhotoAsImageProcessedUpToFilter:self.normalFilter       
     withCompletionHandler:^(UIImage *processedImage, NSError *error) {
    }];

视频开启拍摄和结束拍摄方法

代码块

//开始视频录制
- (void)recordStartHandler {
    //设定视频录制方向
    self.currentMovieDirection = self.currentDirection;
    // 如果已经存在文件,AVAssetWriter会有异常,删除旧文件
    unlink([self.moviePath UTF8String]);
    //滤镜加到writer
    [self.normalFilter addTarget:self.movieWriter];
    //开始录制
    [self.movieWriter startRecording];
}

//结束视频录制
- (void)recordFinishHandler:(void(^)(UIImage *firstVideoImage))handler {
    //移除target
    [self.normalFilter removeTarget:self.movieWriter];
    @weakify(self);
    [self.movieWriter finishRecordingWithCompletionHandler:^{
        @strongify(self);
        [self createNewWritter];
     // 此时视频文件已经在对应的路径下哦~ 
    }];
}

GPUImage填坑

视频拍摄第一帧黑屏

- (void)createNewWritter {
    self.movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:[NSURL fileURLWithPath:self.moviePath] size:CGSizeMake(kCameraWidth, kCameraWidth) fileType:AVFileTypeQuickTimeMovie outputSettings:self.videoSettings];
    /// 如果不加上这一句,会出现第一帧闪现黑屏 
    [_videoCamera addAudioInputsAndOutputs];
    _videoCamera.audioEncodingTarget = _movieWriter;
}
新增需求

由于boss随口一说 本次美颜滤镜相机还增加了聚焦、曝光操作以及仿苹果原生相机横屏拍摄
下面是涉及这些功能的精华代码

聚焦、曝光(在view上增加一个点击手势即可)

- (void)focusTap:(UITapGestureRecognizer *)tap {
    //    self.cameraView.userInteractionEnabled = NO;
    CGPoint touchPoint = [tap locationInView:tap.view];
    [self layerAnimationWithPoint:touchPoint];
    touchPoint = CGPointMake(touchPoint.x / tap.view.bounds.size.width, touchPoint.y / tap.view.bounds.size.height);
    /*以下是相机的聚焦和曝光设置,前置不支持聚焦但是可以曝光处理,后置相机两者都支持,下面的方法是通过点击一个点同时设置聚焦和曝光,当然根据需要也可以分开进行处理
     */
    if ([self.videoCamera.inputCamera isExposurePointOfInterestSupported] && [self.videoCamera.inputCamera isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {
        NSError *error;
        if ([self.videoCamera.inputCamera lockForConfiguration:&error]) {
            
            [self.videoCamera.inputCamera setExposurePointOfInterest:touchPoint];
            [self.videoCamera.inputCamera setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
            if([self.videoCamera.inputCamera isFocusPointOfInterestSupported] && [self.videoCamera.inputCamera isFocusModeSupported:AVCaptureFocusModeAutoFocus])
            {
                [self.videoCamera.inputCamera setFocusPointOfInterest:touchPoint];
                [self.videoCamera.inputCamera setFocusMode:AVCaptureFocusModeAutoFocus];
            }
            
            [self.videoCamera.inputCamera unlockForConfiguration];
            
        } else {
            NSLog(@"ERROR = %@", error);
        }
    }
}

横屏拍摄(其实根据拍摄的第一帧判断时候为横屏 涉及工具 加速仪)

     /** 开启加速仪(方向检测) 
          在按下快门的那一刻记录当前帧的方向
          然后在视频拍摄完成后根据第一帧方向对视频进行处理 判断是否需要旋转
     */
- (void)startDeviceMotion {
    if (![self.motionManager isDeviceMotionAvailable]) {return;}
    [self.motionManager setDeviceMotionUpdateInterval:1.f];
    [self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
        //Gravity 获取手机的重力值在各个方向上的分量
        double x = motion.gravity.x;
        double y = motion.gravity.y;
        double z = motion.gravity.z;
        self.currentDirection = UIImageOrientationUp;
        if (fabs(z) < 0.5) {
            if (fabs(y)>=fabs(x)) {
                if (y >= 0) self.currentDirection = UIImageOrientationDown;
            }
            else {
                if (x >= 0) self.currentDirection = UIImageOrientationRight;
                else self.currentDirection = UIImageOrientationLeft;
            }
        }
    }];
}

效果图

美颜滤镜.gif
上一篇下一篇

猜你喜欢

热点阅读