• 探索iOS之CoreImage框架


    CoreImage提供图像处理、人脸识别、图像增强、图像滤镜、图像转场。它操作的数据来自Core Graphics、Core Video、Image IO,使用CPU或GPU进行渲染。CoreImage对底层实现进行封装,为上层提供简单易用的API。

    一、CoreImage框架

    CoreImage框架分为:渲染层、处理层、API层。其中,渲染层包括GPU渲染(OpenGL和Metal)、CPU渲染(Grand Central Dispatch);处理层有Built-in Filters内建滤镜;API层有Core Graphics、Core Video、Image IO。如下图所示:

    二、图像处理

    1、图像处理流程

    图像处理主要包括三个类:CIContext、CIFilter、CIImage。处理流程示例如下:

    1. import CoreImage
    2. // 1、创建CIContext
    3. let context = CIContext()
    4. // 2、创建CIFilter
    5. let filter = CIFilter(name: "CISepiaTone")!
    6. filter.setValue(0.8, forKey: kCIInputIntensityKey)
    7. // 3、创建CIImage
    8. let image = CIImage(contentsOfURL: mURL)
    9. // 4、image应用到filter滤镜
    10. filter.setValue(image, forKey: kCIInputImageKey)
    11. let result = filter.outputImage!
    12. // 5、使用context创建CGImage(用于管理image以及对象复用)
    13. let cgImage = context.createCGImage(result, from: result.extent)
    14. // 6、显示滤镜结果
    15. imageView.image = UIImage(CIImage: result)

    2、图像数据类型

    图像作为输入输出的Filter,包括数据类型如下:

    图像文件的URL或图像数据的NSData;

    CGImageRef、UIImage、NSBitmapImageRep对象;

    Metal、OpenGl纹理;

    CVImageBufferRef、CVPixelBufferRef;

    跨进程共享数据的IOSurfaceRef;

    内存的Bitmap数据或CIImageProvider;

    3、创建Filter Chain

    Filter Chain滤镜链的创建,示例代码如下:

    1. func applyFilterChain(to image: CIImage) -> CIImage {
    2. // 创建CIFilter,并且设置color滤镜
    3. let colorFilter = CIFilter(name: "CIPhotoEffectProcess", withInputParameters:
    4. [kCIInputImageKey: image])!
    5. // 应用bloom滤镜
    6. let bloomImage = colorFilter.outputImage!.applyingFilter("CIBloom",
    7. withInputParameters: [
    8. kCIInputRadiusKey: 10.0,
    9. kCIInputIntensityKey: 1.0
    10. ])
    11. // 图像裁剪
    12. let cropRect = CGRect(x: 350, y: 350, width: 150, height: 150)
    13. let croppedImage = bloomImage.cropping(to: cropRect)
    14. return croppedImage
    15. }

    4、应用滤镜到视频

    以高斯模糊滤镜应用到视频为例,相关代码如下:

    1. // 创建高斯模糊filter
    2. let filter = CIFilter(name: "CIGaussianBlur")!
    3. let composition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in
    4. let source = request.sourceImage.clampingToExtent()
    5. filter.setValue(source, forKey: kCIInputImageKey)
    6. // 根据时间戳设置模糊系数
    7. let seconds = CMTimeGetSeconds(request.compositionTime)
    8. filter.setValue(seconds * 10.0, forKey: kCIInputRadiusKey)
    9. // 裁剪
    10. let output = filter.outputImage!.cropping(to: request.sourceImage.extent)
    11. // 应用滤镜结果到视频
    12. request.finish(with: output, context: nil)
    13. })

    5、使用Metal实时滤镜

    首先创建Metal view用于图像渲染:

    1. class ViewController: UIViewController, MTKViewDelegate {
    2. // Metal设备、纹理、队列
    3. var device: MTLDevice!
    4. var commandQueue: MTLCommandQueue!
    5. var sourceTexture: MTLTexture!
    6. // 高斯模糊
    7. var context: CIContext!
    8. let filter = CIFilter(name: "CIGaussianBlur")!
    9. let colorSpace = CGColorSpaceCreateDeviceRGB()
    10. override func viewDidLoad() {
    11. super.viewDidLoad()
    12. // 创建设备、命令队列
    13. device = MTLCreateSystemDefaultDevice()
    14. commandQueue = device.newCommandQueue()
    15. let view = self.view as! MTKView
    16. view.delegate = self
    17. view.device = device
    18. view.framebufferOnly = false
    19. // 创建CIContext
    20. context = CIContext(mtlDevice: device)
    21. }
    22. }

    实时滤镜渲染流程,示例代码如下:

    1. public func draw(in view: MTKView) {
    2. if let currentDrawable = view.currentDrawable {
    3. let commandBuffer = commandQueue.commandBuffer()
    4. // 1、使用纹理创建UIImage,并且进行滤镜
    5. let inputImage = CIImage(mtlTexture: sourceTexture)!
    6. filter.setValue(inputImage, forKey: kCIInputImageKey)
    7. filter.setValue(20.0, forKey: kCIInputRadiusKey)
    8. // 2、使用context进行渲染
    9. context.render(filter.outputImage!,
    10. to: currentDrawable.texture,
    11. commandBuffer: commandBuffer,
    12. bounds: inputImage.extent,
    13. colorSpace: colorSpace)
    14. // 3、使用buffer显示结果
    15. commandBuffer.present(currentDrawable)
    16. commandBuffer.commit()
    17. }
    18. }

    三、人脸识别

    iOS提供CIDetector进行人脸识别,示例代码如下:

    1. // 1、创建CIContext
    2. CIContext *context = [CIContext context];
    3. // 2、创建options,指定识别精度
    4. NSDictionary *opts = @{ CIDetectorAccuracy : CIDetectorAccuracyHigh };
    5. // 3、创建检测器,指定识别类型
    6. CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace
    7. context:context
    8. options:opts];
    9. // 4、指定图像方向
    10. opts = @{ CIDetectorImageOrientation :
    11. [[mImage properties] valueForKey:kCGImagePropertyOrientation] };
    12. // 5、获取识别结果
    13. NSArray *features = [detector featuresInImage:mImage options:opts];

    人脸识别结果包含:左眼、右眼、嘴巴的位置,结果判断如下:

    1. for (CIFaceFeature *f in features) {
    2. NSLog(@"%@", NSStringFromRect(f.bounds));
    3. if (f.hasLeftEyePosition) {
    4. NSLog(@"Left eye x=%g y=%g", f.leftEyePosition.x, f.leftEyePosition.y);
    5. }
    6. if (f.hasRightEyePosition) {
    7. NSLog(@"Right eye x=%g y=%g", f.rightEyePosition.x, f.rightEyePosition.y);
    8. }
    9. if (f.hasMouthPosition) {
    10. NSLog(@"Mouth x=%g y=%g", f.mouthPosition.x, f.mouthPosition.y);
    11. }
    12. }

    我们来看下人脸识别效果:

    四、图像增强

    iOS提供的图像增强包括:红眼矫正、脸部平衡、色彩增强、阴影突出,如下表所示:

    Filter描述
    CIRedEyeCorrection修复摄像头闪光引起的红眼
    CIFaceBalance根据肤色调整脸部颜色
    CIVibrance增强饱和度
    CIToneCurve调整对比度
    CIHighlightShadowAdjust调整阴影细节

    图像增强的使用示例如下:

    1. NSDictionary *options = @{ CIDetectorImageOrientation :
    2. [[image properties] valueForKey:kCGImagePropertyOrientation] };
    3. NSArray *adjustments = [image autoAdjustmentFiltersWithOptions:options];
    4. for (CIFilter *filter in adjustments) {
    5. [filter setValue:image forKey:kCIInputImageKey];
    6. myImage = filter.outputImage;
    7. }

  • 相关阅读:
    Redis 发布订阅
    [MySQL]基本介绍及安装使用详细讲解
    【PG】PostgreSQL字符集
    基于python的疫情数据可视化分析系统设计与实现-计算机毕业设计源码+LW文档
    illustrator插件-将位图矢量化-转为SVG-AI插件
    Uni App-----之u-input(密码明文小眼睛切换)
    【MySQL】InnoDB和MyISAM区别详解(MySQL专栏启动)
    mysql 增量备份与恢复使用详解
    SpringMVC
    windows系统部署minio,以及添加到系统服务器
  • 原文地址:https://blog.csdn.net/u011686167/article/details/130898957