你应该了解的Core Image & CIFilter

2018-12-12 ps: CoreImage 只是合成图片的配方。它并不执行任何合成操作。所以任何的中间过程 *CIFilter.outputImage并不会对资源有占用。只有合成可以显示的图片才进行合成计算。

**效果Filter:CIPageCurlWithShadowTransition**

敲了好长时间才把 CIFilter 大部分的滤镜敲打完毕(就是好奇,也看看效果啥的)。也就是属于一遍敲打一边学习。(因为接触CIFilter的时候没有考虑到主线程的问题,所以都是在drawrect中画的。性能不好,也不想给你们看我敲的东西了,自己看着都觉着写的什么玩意)正好有这个机会,把我的学习经验跟大家分享一下,大家可以少走弯路。大家一起学习 Core Imgae (** 就当是无事了解一下也是好的啊**),走上一条不“归路”……

目录

1.写在"CIFilter"前边关于"Core Image"的基础知识
2.那些你应该知道常用"CIFilter"滤镜
3."CIFilter"中的重要矩阵——"卷积矩阵"
4.在"CIFilter"中的一些小技巧

Core Image 基础知识

#首先 —— 我们要明白,当我们操作 || 改变 Image 的时候,我们其实操作的是DATA数据`
如果我们需要将图片转换为Data数据类型。那么我们可以这样做:

UIImage *tempImage = [UIImage imageNamed:@"test_new"];
CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(tempImage.CGImage));
#ps:打印这个数据 " <0c71a5ff 0c70a5ff 0d71a5ff 0c71a5ff 
                0c71a5ff 0c71a5ff 0c71a5ff 0c71a5ff 0c71a5ff 0c71a5ff>"
随便截取一段打印的数据,每一个item代表一个颜色:"R-G-B-A".
了解了这个:"**图片某像素颜色的抓取** && **图片颜色RGBA进行矩阵修改**"那就看起来就容易多了。

#当然你还要注意的就是 UIImage | CGImage | CIImage 之间的区别
其实归结到底,他们只是不同的框架下得产物,同样也正因为不同的框架,使得他们的操作发生了质的变化。
•UIImage : 负责UIKit中的图片展示&数据管理。(CPU计算)
•CGImage: CoreGraphic中对图片的"旋转、缩放 & 挖取"工作。(GPU计算)
•CIImage : 描述一个如何产生一个图像,但其本身本身并不包含图像数据,  
           它代表的是图像数据或者生成图像数据的流程(如"滤镜的输出")
#Core Image 的优势:
最大化利用其所运行之上的硬件的。每个滤镜实际上的实现,即-"内核",是由一个
GLSL(即 OpenGL 的着色语言) 的子集来书写的.当多个滤镜连接成一个滤镜图表,
Core Image 便把内核串在一起来构建一个可在 GPU 上运行的高效程序
"事实上,图像处理和渲染就是将渲染到窗口的像素点进行许多的浮点运算,"
"那么GPU (图形处理器) 可以高效的完成。"

Core Image 概述

屏幕快照 2016-10-25 上午10.44.33.png
Core Image 是 iOS 5 新加入到 iOS 平台的一个图像处理框架,提供了强大高效的图像处理功能, 
用来对基于像素的图像进行操作与分析, 内置了很多强大的滤镜(Filter) (目前数量超过了180种), 
这些Filter 提供了各种各样的效果, 并且还可以通过 "滤镜链" 将各种效果的 Filter叠加起来
形成强大的自定义效果。~

IOS8之后更是支持自定义Filter

•自动图像增强技术支持
•链接多个Filter,进行滤镜链
•"iOS8" 增强 GPU 渲染,在后台也能继续使用GPU处理。
•引入 CIDetector,提供一些常用的图片识别功能:人脸识别、条形码识别、文本识别等。
•越来越多的框架结合:OpenGL ES . Metal . SceneKit . SpriteKit
•iOS10 也对Core Image 有更新内容
#足可以看出 "Apple" 对 "Core Image" 的重视

Core Image 使用

**CIFilter 使用起来特别简单 **

使用流程

CIFilter 基础类

•Core Image: 输入(可通过UIImage、图像文件和像素数据创建)&&输出图像
             数据(filter.outputImage方法获得)
•CIFilter: 应用的滤镜,通过键-值对 决定操作参数(可通过"[filter attributes]"查看
           参数的取值范围以及说明)
•CIContext: 表明上下文,通过CIContext绘制及渲染的CIImage图片数据,
            才会绘制成APP可以使用的图片

我们使用"CIConvolution3X3"举例

- (UIImage *)outputImageWithFilterName:(NSString *)filterName { 
  // 1. 获取source图片
  UIImage *inputOrigin = [UIImage imageNamed:@"histogram"];
  // 2. 创建滤镜 
  CIFilter *filter = [CIFilter filterWithName:filterNamekeysAndValues:kCIInputImageKey, ciImage, nil]; 
  // 设置相关参数 
  {
    CIImage *inputImage = [CIImage imageWithCGImage:inputOrigin.CGImage];
    [filter setValue:inputImage forKey:kCIInputImageKey];
    CGFloat weights[] = {0,-1,0,
                        -1,5,-1,
                         0,-1,0};// 进行打磨处理
# MARK:- 使用卷积5X5矩阵的话, 这个可以实现重影效果"(3X3也可以,效果不好看)"
   //        CGFloat weights[] = {0.5,0,0,0,0,
   //                             0,0,0,0,0,
   //                             0,0,0,0,0,
   //                             0,0,0,0,0,
   //                             0,0,0,0,0.5};//重影效果
    CIVector *inputWeights = [CIVector vectorWithValues:weights count:9];// count 必须与输入的一致
    [filter setValue:inputWeights forKey:kCIInputWeightsKey];
    [filter setValue:@0 forKey:kCIInputBiasKey];
  }
  // 3. 渲染并输出
  CIImage CIImage *outputImage = [self.filter outputImage];  
  // 4. 获取绘制上下文
  self.context = [CIContext contextWithOptions:nil];  
  // 5. 创建输出
  CGImage CGImageRef cgImage = [self.context createCGImage:outputImage fromRect:[outputImage extent]];
   UIImage *image = [UIImage imageWithCGImage:cgImage]; 
  // 6. 释放
  CGImage CGImageRelease(cgImage);  
  return image;
}
#输入参数: inputImage . inputWeights . inputBias
# ps: CIConvolution7X7 . CIConvolution9Horizontal . CIConvolution9Vertical
# "这里就涉及到卷积矩阵了。"

效果如下:

屏幕快照 2016-10-25 下午3.32.56.png

常用的CIFilter

#CIConstantColorGenerator("生成纯色图片做背景用") | CICrop ("裁切图片") | 
#CISourceAtopCompositing("两张图进行合成-前景&背景")| CIQRCodeGenerator("二维码生成")
# CIGaussianBlur ("高斯模糊")| CIConvolution3X3 ("自定义卷积Kernel")
#CICheckerboardGenerator("棋盘样式") | CIStripesGenerator("格子布")
# CIColorCrossPolynomial("多项式交叉"这个比较麻烦。参数设置需要计算等等,但是可以很强大)

多项式交叉


CIColorCrossPolynomial多项式计算规则

多项式交叉能做到的效果

卷积矩阵(让我们离真相更加接近)

网上的介绍:每个Filter被称为Kernel 内核,一部分的核心指的就是这个 卷积矩阵

卷积矩阵的简单事例

#这里其实发生了: 
过滤器连续地读,从左至右,从上到下,内核动作区域的所有像素。
它通过相应的价值和增值结果内核乘以他们每个人的价值。
初始像素已经成为42:
(40*0)+(42*1)+(46*0)+(46*0)+(50*0)+(55*0)+(52*0)+(56*0)+(58*0)= 42
过滤器会进行copy图片,在副本上进行工作得出图形结果("作为初始像素向下移动一个像素")
#这个卷积矩阵可以实现多种效果:
  锐化 | 模糊 | 边缘检测 | 浮雕 ……
屏幕快照 2016-10-25 下午3.24.43.png

一些你应该知道的小知识

# MARK:
1.UIImage 属性.CIImage 可能为nil。
  ps:只有UIImage基于CIImage创建的,才能通过.CIImage得到 <CIImage>
2.使用filter生成的图片并不是总能使用UIImage进行渲染
  ps:生成的图片.extent 可能会是 "infinite(无穷大)".这样的图片不会被渲染,
      需要进行CICrop进行裁切。
3.如果filter对图片进行放大等操作而且需要裁切的,那么他是通过"Center向四周放大的"
   那么或许图片的时候应该考虑到#裁切的范围补偿。

CIContext GPU & CPU 对我们处理图片的影响

在创建结果 UIImage 的时候,最简单的方式就是通过 imageWithCIImage 来实现。这种情况下,不需要显示的声明CIContext,因为 imageWithCIImage 内部自动完成了这个步骤。这使得使用 Core Image 更加的方便。当然,它也引起了另外一个问题,每次都会重新创建一个 CIContext,然而 CIContext 的代价是非常高的。
并且,CIContext 和 CIImage 对象是不可变的,在线程之间共享这些对象是安全的。所以多个线程可以使用同一个 GPU 或者 CPU CIContext 对象来渲染 CIImage 对象。
所以重用 CIContext 是很有必要的。这意味着,我们不应该使用 imageWithCIImage 来生成 UIImage,而应该自己创建维护 CIContext。

 #建议频繁操作CIContext。可以建一个全局的变量去维护。(每个上下文中都是有缓存的,频繁创建就用不到 上下文中 的缓存,既浪费资源又浪费内存的消耗)

基于 GPU 的话,处理速度更快,因为利用了 GPU 硬件的并行优势。可以使用 OpenGLES 或者 Metal 来渲染图像,这种方式CPU完全没有负担,应用程序的运行循环不会受到图像渲染的影响。
但是 GPU 受限于硬件纹理尺寸,而且如果你的程序在后台继续处理和保存图片的话,那么需要使用 CPU,因为当 App 切换到后台状态时 GPU 处理会被打断。使用 CPU 渲染的 iOS 会采用 GCD 来对图像进行渲染,这保证了 CPU 渲染在大部分情况下更可靠,比 GPU 渲染更容易使用,可以在后台实现渲染过程。
综上,对于复杂的图像滤镜使用 GPU 更好,但是如果在处理视频并保存文件,或保存照片到照片库中时,为避免程序进入后台对图片保存造成影响,这时应该使用 CPU 进行渲染。

创建CIContext

// 创建基于 CPU 的 CIContext 对象 (默认是基于 GPU,CPU 需要额外设置参数)
context = [CIContext contextWithOptions: [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:kCIContextUseSoftwareRenderer]];
// 创建基于 GPU 的 CIContext 对象
context = [CIContext contextWithOptions: nil];
// 创建基于 GPU 的 CIContext 对象
EAGLContext *glcontext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
context = [CIContext contextWithEAGLContext: glcontext];

需要特别注意:

"contextWithOptions"方法 创建的 "context"并没有实时性能, 虽然渲染是在 "GPU" 上执行,
但是其输出的 "image" 是不能显示的,只有当其被复制回 "CPU" 存储器上时,才会被转成一个可被
显示的 "image" 类型,比如 UIImage。

基于GPUImage库的计算。 以<CISepiaTone> - ** 模拟器的状态下**为例:

# CPU 耗时:"83.47 ms" —— "( 自己手动计算图片每个像素目标值 ,GPU进行绘制图片)"
# Core Image 耗时: "1217.52 ms"  —— "( 用CIFilter计算,生成CIImage对象进行绘制 )"
# GPUImage 耗时: "340.92 ms" —— "使用GPUImage库进行计算,GPU进行绘制图片"
ps:以上信息为单次计算,可能会有一些误差在里边。大体的时间比例是正确的

在这里不得不提醒大家一下:

通过上边的数据显示,说明:**Core Image** 生成图片是特别占用cpu的。
所以当我们进行 CIFilter 生成 UIimage 的时候,尽量不要放到主线程中操作。
当计算这个任务被加入主线程中,主线程是一个串行的队列,每个操作都会阻碍"主线程屏幕的刷新"  
#ps: 这个会造成卡顿的现象的。
#(顺带着该学习一下多线程了,小编这几天刚看完多线程。又准备去看动画去了推荐"UIDynamic")
# UIKit中的 "动力学引擎" -- 比较Apple原生的东西,看到效果还不错的。这要是都让咱自己写啊,怎么会有精力呢!
# 苹果的东西还是值得一学的。"妈妈再也不用担心我的学习了。"

可能CIFilter内容太多不容易记住:

获取CIFilter-Names  :  [CIFilter filterNamesInCategory:nil]
获取当前Filter的输入参 : [filter inputKeys]
获取当前Filter的输出参数 : [filter outputKeys]
输入参数的attributes : [filter attributes]

那那那,小编就学会这点东西。有啥书写有误的东西,欢迎指教!

最后啊,小编还是想多努力学习,Core Image 仅仅是性能不出众而已。但我们依旧要热爱它,因为apple自家的东西。我们都要支持----(ios开发工作者)


可是话说回来,不是还有 人脸识别 值得你学习吧。

IOS10 图库 可是加入了 ** 人物 ** 的功能呢 。

苹果软件工程高级副总裁克雷格·费德里奇在演讲中表示,“先进计算机视觉”(Advanced Computer Vision)
是今年照片应用最大幅度的一次更新,因为苹果通过深度学习技术将人脸识别带到了 iPhone 身上。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容