前言
Core Image是一种图画处理和剖析的技术,用于对静态图画和视频图画供给近似实时的处理。运用GPU或许CPU烘托,支撑来自Core Graphics、Core Video和Image I/O的图画数据类型进行操作。
Core Image经过供给易于运用的API来隐藏底层图形处理的细节。
才能
- 供给内置的图画滤镜
- 特征检测才能,如人脸检测
- 支撑主动的图画增强,如修正红眼,平衡肤色,调整对比度与阴影
- 将多个图画滤镜组合在一起,发明自定义的作用
- 支撑创立运行在GPU上的自定义滤镜
- 给予反应的图画处理才能
- 实时的视频图画处理
常用场景
- 实现图画的艺术作用,例如风格化、半颜色滤镜等。也合适修正图画问题,如颜色彩整和锐化滤镜。
- 用于剖析图画质量,如调整颜色,对比度,颜色颜色等,以及纠正红颜等闪光灯伪影。
- 检测静态图画中的人脸特征,并随着时间推移,在视频图画中盯梢它们。
不要运用Core Image来创立模糊作用,而是运用
NSVisualEffectView
(macOS)或UIVisualEffectView
(iOS/tvOS)类,它们会主动匹配体系外观并供给高效的实时烘托。
图画处理
依赖于CIFilter和CIImage类,它们描绘了滤镜的输入与输出。
处理流程
import CoreImage
let context = CIContext() // 1
let filter = CIFilter(name: "CISepiaTone")! // 2
filter.setValue(0.8, forKey: kCIInputIntensityKey)
let image = CIImage(contentsOfURL: myURL) // 3
filter.setValue(image, forKey: kCIInputImageKey)
let result = filter.outputImage! // 4
let cgImage = context.createCGImage(result, from: result.extent) // 5
- 创立CIContext目标。咱们并不总是需求创立新的CIContext,通常会从其他办理烘托的结构中获取。创立自定义的上下文能够更精准的操控烘托进程以及烘托所需求的资源。Context是高资源消耗的目标,运用时尽早创立,并且在处理图画时进行复用。
- 创立需求运用的滤镜,并装备参数。
- 创立一个表明待处理图画的CIImage目标,并为其作为滤镜的输入图画。
- 获得表明滤镜输出成果的CIImage目标。此刻滤镜没有实际生效,Core Image会在恳求烘托时履行该目标的生成。
- 将输出图画烘托成Core Graphics图画,即CGImage,这样咱们就能够显现图画或许保存成文件。
CIImage目标
CIImage目标表明的是一个不可变的待烘托图画信息调集,并不直接表明图画的位图信息。
-
作为输入图画,它会描绘怎么加载图画数据
-
作为输出图画,它会描绘履行滤镜的步骤,即怎么从滤镜处理中输出图画。只有在履行烘托恳求时,Core Image才会经过CIImage去生成位图数据。
输入图画
- 经过图画文件的URL
- 经过图画的NSData二进制数据
- 经过CGImageRef(Quartz2D)、UIImage(UIKit) 或许 NSBitmapImageRep(AppKit)
- 经过Metal、OpenGL 或许OpenGL ES的纹理
- 经过Core Video的 CVImageBufferRef(图画) 或许 CVPixcelBufferRef(像素缓存数据)
- 经过IOSurfaceRef在进程之间共享的图画数据。
- 经过内存中的图画内存数据(如指向此类数据的指针,或许CIImageProvider目标)
有关创立CIImage
目标的完好列表,请参阅*CIimage类参阅*。
####输出图画
作为CIFilter的outputImage特点的类型。
能够经过CIContext或许draw办法来显式恳求烘托(请参阅运用Core Image Context构建自己的作业流程)
能够经过运用其他结构来实现隐式恳求烘托(请参阅与其他结构集成)
CIFilter
表明图画的处理作用,以及操控该作用的参数数值。需求指定输入参数,然后从outputImage中获得处理成果。
体系内集成很多滤镜,咱们能够经过滤镜的称号来获取运用(请参阅查询体系以获取滤镜或*Core Image滤镜参阅*)
线程安全
CIContext 和 CIImage 目标是不可变的,在线程之间共享这些目标是安全的。所以多个线程能够运用同一个 GPU 或许 CPU CIContext 目标来烘托 CIImage 目标。
多个滤镜的链式调用
每个Core Image的滤镜都会生成一个输出CIImage目标,因而能够运用该目标作为另一个滤镜的输入,来到达链式调用的目的。
Core Image会优化向这样的链式吊用,以快速有用的烘托成果。链中的每个CIImage目标都不会完好烘托成图画,而是传递滤镜的处理步骤和参数。Core Image不会独自履行每个滤镜,也不会在进程中发生临时像素缓存区。Core Image会重新组织滤镜,甚至或许重新排列滤镜的运用顺序(如Color -> Bloom -> Crop,会被优化为 Crop -> Color -> Bloom),来更有用率的烘托成果图。
func applyFilterChain(to image: CIImage) -> CIImage {
// The CIPhotoEffectInstant filter takes only an input image
let colorFilter = CIFilter(name: "CIPhotoEffectProcess", withInputParameters:
[kCIInputImageKey: image])!
// Pass the result of the color filter into the Bloom filter
// and set its parameters for a glowy effect.
let bloomImage = colorFilter.outputImage!.applyingFilter("CIBloom",
withInputParameters: [
kCIInputRadiusKey: 10.0,
kCIInputIntensityKey: 1.0
])
// imageByCroppingToRect is a convenience method for
// creating the CICrop filter and accessing its outputImage.
let cropRect = CGRect(x: 350, y: 350, width: 150, height: 150)
let croppedImage = bloomImage.cropping(to: cropRect)
return croppedImage
}
特别滤镜
大多数内置的Core Image滤镜是在输入图的基础上处理,生成单个输出图画。但还有几种其他类型的滤镜,能够与常用的滤镜组合,创立风趣的作用,但这也需求更复杂的作业流程。
Compositing / Blending
运用预设的公式组合两张照片。
- CISourceInCompositing滤镜在组成两张图画后,输出两张图画中不透明的区域。
- CIMultiplyBlendMode滤镜在组成两张图画后,将两张图画的像素颜色相乘,发生变暗的输出图画。
更多有关Compositing / Blending滤镜的完好列表,请查询CICategoryCompositeOperation。
**留意:**在组成输入图画前,能够对图画进行几许调整。请参阅CICategoryGeometryAdjustment滤镜或imageByApplyingTransform:
办法。
Generator
不需求输入图画,这些滤镜会根据输入参数,创立新的图画。
一部分Generator滤镜能够直接产出可供运用的成果,还有一部分能够运用在滤镜的链式调用中,组合出更多的成果。
- CIQRCodeGenerator和CICode128BarcodeGenerator等滤镜能够经过输入的数据生成条形码图画
- CIConstantColorGenerator、CICheckerboardGenerator和CILinearGradient等滤镜能够经过指定颜色生成简略的图画。能够将这些与常用滤镜结合运用——例如,CIRadialGradient滤镜能够创立一个与CIMaskedVariableBlur滤镜一起运用的遮罩。
- CILenticularHaloGenerator和CISunbeamsGenerator等滤镜能够创立独立的视觉作用——将这些作用与组成滤镜结合运用,能够为图画增加特别作用。
更多Generator滤镜,请查询CICategoryGenerator和CICategoryGradient类别。
Reduction
其输出的不是创立位图的信息,而是描绘输入图画的信息。比方:
- CIAreaMaximum滤镜输出的是单个颜色值,代表图画指定区域中一切像素颜色中最亮的颜色。
- CIAreaHistogram滤镜输出的是有关图画指定区域中每个强度值的像素数的信息。
一切Core Image 滤镜都必须发生一个CIImage
目标作为输出,因而Reduction滤镜生成的信息仍然是图画。但通常不会显现这些图画,而是从单像素或单行图画中读取颜色值,或将其用作其他滤镜的输入图画。
有关Reduction滤镜的完好列表,请查询CICategoryReduction类别。
Transition
接纳两个输入图画,并根据某个变量生成图画之间的改变。
通常该变量是时间,因而您能够运用Transition滤镜创立动画,该动画以一张图画开端,以另一张图画结束,并运用风趣的视觉作用从一个图画进行到另一个图画。Core Image 供给了几个内置的过渡滤镜,包括:
- CIDissolveTransition滤镜能够发生一个简略的穿插溶解,从一个图画流向另一个图画。
- CICopyMachineTransition滤镜能够模拟复印机,在一张图画上滑动一条亮光条以显现另一张图画。
有关Transition滤镜的完好列表,请查询CICategoryTransition类别。
经过Quartz 2D基于CPU进行烘托
假如App对实时功能要求不高,能够经过Core Graphics来做视图烘托(例如在drawRect:
中),能够运用 contextWithCGContext:options:
经过Core Graphics Context来获取CIContext。
最佳实践
前期预备
在做功能优化前,先判别当时事务的状况。能够从以下几方面进行剖析
- Core Image的履行频率怎么
- 是用于静态图画,仍是视频图画
- 是否需求支撑实时处理或许剖析
- 事务对颜色的保真度要求怎么
优化
在确认了事务状况后,在着手功能优化。有以下几点主张。
-
不要每次烘托时都创立CIContext目标,改目标存储了很多的状况信息,复用它们将提高功率。
-
假如不需求颜色办理,则不要开启它。要禁用颜色办理,请将
kCIImageColorSpace
键设置为null
。-
默认状况下,Core Image 会将一切滤镜运用到光线性颜色空间中。这供给了最精确和共同的成果。转化到sRGB增加了滤镜的复杂性,并要求Core Image运用以下方程:
rgb = mix(rgb.0.0774, pow(rgb*0.9479 + 0.05213, 2.4), step(0.04045, rgb)) rgb = mix(rgb12.92, pow(rgb*0.4167) * 1.055 - 0.055, step(0.00313, rgb))
-
在以下情形中,请考虑停用颜色办理:
- 您的运用程序需求绝对最高的功能。
- 用户在夸张操作后不会留意到质量差异。
-
-
在GPU上运用CIImage目标时,防止运用Core Animation动画。假如要一起运用,能够将两者都设置为运用CPU
-
确保图画不会超过CPU和GPU的约束。
-
CIContext
对图画巨细的约束会因Core Image运用CPU仍是GPU有所不同。 - 运用办法
inputImageMaximumSize
和outputImageMaximumSize
查看约束。
-
-
运用更小的图画。功能与输出像素数量成反比,像素越多,功能越差。
- 您能够将 Core Image 烘托到较小的视图、纹理或帧缓冲区。再经过允许Core Animation缩放到展现尺寸。
- 运用Core Graphics或Image I/O函数 裁剪 或 缩小取样,例如
CGImageCreateWithImageInRect
或CGImageSourceCreateThumbnailAtIndex
函数。
-
UIImageView类最合适展现静态图画。假如你想要更高的功能,能够能够运用更底层的API
-
防止在CPU和GUP之间进行不必要的纹理传输。
-
烘托与源图相同巨细的矩形,而不是用缩放因子(sacle factor)去操控。
-
考虑运用更简略的滤镜,用简略的滤镜去制作近似算法滤镜的成果。例如,CIColorCube能够发生类似于CISepiaTone的输出,并且履行得更有用。
-
利用iOS 6.0及更高版别中对YUV图画的支撑。相机像素缓冲区原生是YUV,但大多数图画处理算法都希望RBGA数据。在两者之间转化是有本钱的。Core Image支撑从
CVPixelBuffer
目标读取YUB并运用恰当的颜色转化。(options = @{ (id)kCVPixelBufferPixelFormatTypeKey :@(kCVPixelFormatType_420YpCbCr88iPlanarFullRange) };
)
参阅资料
官方文档