美文网首页
Core Image使用指南

Core Image使用指南

作者: 读行笔记 | 来源:发表于2020-12-21 23:13 被阅读0次

    简介

    Core Image是一个图片处理及分析库,里面封装了非常易用的API,比如大量常用滤镜。因为它借助GPU或者CPU渲染,所以可以接近实时的速度处理静态图片和视频图片,图片可来自Core Graphics、Core Video以及I/O框架。

    Core Image架构

    功能列表

    Core Image提供的能力包括:

    • 通过大量内置滤镜处理图片
    • 通过滤镜链自定义处理效果
    • 自动化图片增强
    • 特征检测,比如人脸、矩形、文字等
    • 创建自定义滤镜

    基本概念

    滤镜

    一个滤镜在语义上表示某种能力,当作用在一张图片上时,可以经过某种变换从而得到另一张图片。

    我们都知道,图片在计算机中是以像素为基本单位而保存的像素矩阵,通过图像处理单元GPU才能将其显示在屏幕上。在数学上,滤镜其实也是一个矩阵,也叫卷积核,通常比图片的像素矩阵维度小得多。在真正处理图片时,图片像素矩阵和卷积核做卷积运算,最终输出一个“新”图片。

    滤镜的处理过程

    滤镜链

    顾名思义,滤镜链就是将多个滤镜链接在一起,前一个滤镜的输出作为下一个滤镜的输入,就像流水线一样,图片从第一个滤镜中进入,处理之后再进入下一个,一直到最后一个滤镜。通过这种方式,可以创建出更加如何需求的效果。

    但实际上,Core Image的处理逻辑有点不同,它并不会让一张图片经过多次处理。为了性能考虑,Core Image会先将多个滤镜的卷积核合成为一个,然后一次性得出最终的结果。

    图片处理

    简单来说,图片处理就是将某张图片作用于某个滤镜的过程。

    在Core Image中,图片为CIImage,滤镜为CIFilter,为滤镜设置参数要通过KVC实现。同时,还需要一个上下文对象CIContext,里面保存着所有相关的细节。因为这些细节非常多,所以最好在合适的时机创建一个可重复利用的CIContext对象。

    单滤镜

    最基本的用法就是只使用单个滤镜,如下所示。

    - (void)blurImageWithRadius:(CGFloat)radius {    
        UIImage *originalImage = [UIImage imageNamed:@"blackboard.jpg"];
        CIImage *ciimage = [CIImage imageWithData: UIImageJPEGRepresentation(originalImage, .9)];
        
        CIFilter *gaussianBlur = [CIFilter filterWithName:@"CIGaussianBlur"];
        [gaussianBlur setValue:@(radius) forKey:@"inputRadius"];
        [gaussianBlur setValue:ciimage forKey:@"inputImage"];
        
        [self.processedImageView setImage:[UIImage imageWithCIImage:gaussianBlur.outputImage]];
    }
    

    在CoreImage中所有相关操作中只能使用CIImage这个格式,但是它并不能直接呈现给用户,因为CIImage只是一种用来生产图片的“配方”,其实就是一种操作流程,比如从URL读取图片文件,某个滤镜操作的输出等,只有在渲染或者输出时才会开始执行。总结下来,可以通过下面这些方法创建CIImage:

    • NSURL
    • NSData
    • UIImage
    • CGImageRef
    • CVImageBufferRef
    • CIImageProvider
    - (void)createCIImageMethods {
        CIImage *ciimg;
        
        // 1. URL
        ciimg = [[CIImage alloc] initWithContentsOfURL:[NSURL URLWithString:@"some-url"]];
        
        // 2. bytes
        ciimg = [CIImage imageWithData:[NSData dataWithContentsOfFile:@"some-file-path"]];
        
        // 3. UIImage
        ciimg = [CIImage imageWithData:UIImageJPEGRepresentation([UIImage imageNamed:@"some-img-name"], .9)];
        ciimg = [CIImage imageWithData:UIImagePNGRepresentation([UIImage imageNamed:@"png-name"])];
        
        // 4. CGImageRef
        ciimg = [CIImage imageWithCGImage:[UIImage imageNamed:@"some-img"].CGImage];
        
        //...
    }
    

    滤镜分类

    Core Image中有大量的滤镜,而且随着系统的不断升级,还在不断添加新的滤镜。系统将它们分为以下这些类别:

    类别名称 说明 例子
    CICategoryBlur 模糊 高斯模糊、降噪等
    CICategoryColorAdjustment 颜色调整 色值、曝光度、明暗度调整,色温,色调曲线等
    CICategoryColorEffect 颜色效果 色值转换、黑白效果、褪色等
    CICategoryCompositeOperation 合成 叠加,颜色混合、差分、乘除,亮度、色度混合等等
    CICategoryDistortionEffect 扭曲 隆起、线性隆起,德罗斯特效应,替换扭曲,玻璃扭曲等
    CICategoryGenerator 生成器 生成条形码、二维码、星光🌟、日光,纯色图片、随机图片等
    CICategoryGeometryAdjustment 几何变换 仿射、透视变换,剪裁,兰索斯缩放
    CICategoryGradient 渐变 高斯渐变、线性渐变、径向渐变等
    CICategoryHalftoneEffect 网版效果 圆形网屏,点状网目板等
    CICategoryReduction 不知道该如何翻译 区域平均值、最值,行、列平均值等
    CICategorySharpen 锐化 亮度锐化、非锐化蒙版
    CICategoryStylize 风格化 蒙版混合,软化边缘,喜剧效果,卷积,结晶,边缘检测等
    CICategoryTileEffect 铺贴效果 以多种不同形式填充图案等
    CICategoryTransition 过渡 条形过渡,溶剂过渡等

    把这些功能组合在一起,基本可以实现一个Photoshop了。

    滤镜链

    前面说了,当要经过多个滤镜的处理时,CoreImage为了提高性能会将多个滤镜合成为一个,并在合适时机完成处理。

    例如,如果分步处理,其流程如下:

    分步处理滤镜链

    但如果合成为一个Filter,则其流程如下:

    将多个滤镜合成为一个
    - (CIImage *)processWithImage:(CIImage *)image fileterName:(NSString *)name params:(NSDictionary *)params {
        CIFilter *filter = [CIFilter filterWithName:name];
        [filter setValue:image forKey:@"inputImage"];
        for (NSString *key in params.allKeys) {
            [filter setValue:params[key] forKey:key];
        }
        return filter.outputImage;
    }
    
    - (IBAction)startProcessWithChain:(UIButton *)sender {
        CIImage *blurImg, *bloomImg, *croppedImg;
        blurImg = [self processWithImage:self.inputImage
                             fileterName:@"CIGaussianBlur"
                                  params:@{kCIInputRadiusKey: @(1.2)}];
        bloomImg = [self processWithImage:blurImg
                              fileterName:@"CIBloom"
                                   params:@{kCIInputRadiusKey: @(8.0),
                                            kCIInputIntensityKey: @(1.0)}];
        croppedImg = [bloomImg imageByCroppingToRect:CGRectMake(50, 100, 300, 300)];
        
        [self.processedImageView setImage:[UIImage imageWithCIImage:croppedImg]];
    }
    

    常用操作

    Core Image除过用CFilter来处理图片外,还可以通过一些预定义的方法直接处理图片,将更加简便。比如:

    • initWithColor: 纯色图片
    • imageByApplyingTransform: 给图片进行仿射变换
    • imageByCompositingOverImage: 叠加图片
    • imageByCroppingToRect: 剪裁图片
    • imageByClampingToRect: 扩展边界
    • imageByInsertingIntermediate 插值

    检测

    在图片识别处理中,如果要识别特定对象,一般都要先进行轮廓检测,然后再根据轮廓剪裁后识别物体,这样会更加高效准确。比如人脸、矩形等对象的识别。在Core Image中,提供了开箱即用的轮廓检测功能,其中只能进行三类操作:人脸、矩形、文字。下面看看人脸检测的使用方法:

    - (void)detect:(UIBarButtonItem *)sender{
        CIImage *image = [CIImage imageWithData:UIImageJPEGRepresentation(self.image, .95)];
        NSLog(@"image size: %@", NSStringFromCGSize(self.image.size));
        CIContext *context = [CIContext context];
        NSDictionary *options = @{CIDetectorAccuracy: CIDetectorAccuracyHigh};
        CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace context:context options:options];
        options = @{CIDetectorImageOrientation: [[image properties] valueForKey:(NSString *)kCGImagePropertyOrientation]};
        
        NSArray *features = [detector featuresInImage:image options:options];
        
        for (CIFaceFeature *feature in features) {
            NSLog(@"face bounds: %@", NSStringFromCGRect(feature.bounds));
            [self drawBorderWithFaceFeature:feature];
        }
    }
    
    - (void)drawBorderWithFaceFeature:(CIFaceFeature *)feature{
        CGRect frame = [self convertFaceBoundsToView:feature.bounds];
        NSLog(@"converted face bounds: %@", NSStringFromCGRect(frame));
    
        UILabel *label = [[UILabel alloc] initWithFrame:frame];
        label.backgroundColor = [UIColor clearColor];
        label.layer.borderColor = [UIColor redColor].CGColor;
        label.layer.borderWidth = 2.f;
        [self.imageView addSubview:label];
    }
    
    - (CGRect)convertFaceBoundsToView:(CGRect)bounds{
        CGFloat ratio = CGRectGetWidth(self.imageView.bounds)/self.image.size.width;
        return CGRectMake(CGRectGetMinX(bounds)*ratio, CGRectGetMinY(bounds)*ratio, CGRectGetWidth(bounds)*ratio, CGRectGetHeight(bounds)*ratio);
    }
    
    

    经过使用发现,只要当图片中含有少量人时结果比较准确,当图片清晰度降低、并且人较多时结果不一定准确。

    注意点

    为了提高应用程序的性能,在使用Core Image时尽可能注意以下细节:

    • 不要每次都创建CIContext,应尽可能复用;
    • 如果没有必要,避免动画和颜色空间管理;
    • 尽可能使用更小的图片、简单的滤镜;
    • 确保不要超过CPU或者GPU的限度等。

    参考

    相关文章

      网友评论

          本文标题:Core Image使用指南

          本文链接:https://www.haomeiwen.com/subject/pmfjnktx.html