CoreImage 是 Apple 用于实时图像和视频处理的框架,提供数十种内置 CIFilter 用于色彩校正、模糊、纹理叠加和识别。根据 Apple Documentation,CoreImage 在 iOS 设备上使用 GPU 进行高性能像素处理。该框架支持 CIImage 作为不可变图像对象以及滤镜链,可在不损失质量的情况下组合效果。
要点
CoreImage 是 Apple 用于处理位图图像和视频的框架,最初在 macOS 10.4 Tiger 中引入,后移植到 iOS 5.0。与 Core Graphics 或 UIKit 不同,CoreImage 在像素着色器级别运行,利用 GPU 进行并行计算。这使得可以在毫秒内对百万像素分辨率的图像应用复杂效果——模糊、色彩校正、变形。
CoreImage 的架构基于惰性求值(lazy evaluation)概念:CIFilter 在渲染到 CIContext 之前不会执行处理。开发者将多个 CIFilter 链接在一起,将一个滤镜的输出连接到另一个的输入,只有调用 render 才会启动完整的 GPU 流水线。这最大程度地减少了通过显卡的传递次数并保持了性能。
CoreImage 支持宽色域(P3、sRGB、线性 sRGB)、HDR 图像以及 16 位和 32 位像素格式。在配备 Neural Engine 的设备上,CoreImage 可以将 GPU 着色器与 Core ML 结合进行智能处理——例如基于机器学习的自动色彩校正,如同 iOS 17 中 Photos 应用所实现的那样。
三个核心类构成了 CoreImage 的核心:CIImage(数据)、CIFilter(操作)和 CIContext(执行环境)。每个类负责流水线中的不同阶段,职责分明。
CIImage 是一个轻量级对象,描述图像但不直接包含像素数据。它可以从 UIImage、CGImage、Metal 纹理、GL 纹理或磁盘上的文件创建。CIImage 是不可变的——任何滤镜的应用都会生成一个新的 CIImage,而不会修改原始图像。这使得可以在不复制数据的情况下构建转换链。
一个重要特性:CIImage 在渲染之前不绑定到屏幕分辨率或色彩空间。同一个 CIImage 可以渲染为用于屏幕的 UIImage 和用于打印的 TIFF 文件,使用不同的参数——CoreImage 会自动根据目标上下文调整处理。
CIFilter 是用于应用效果的主要类。每个 CIFilter 代表一个着色器程序,具有输入参数(inputImage、inputIntensity、inputRadius 等)和一个输出图像。Apple 提供超过 200 个内置 CIFilter,按类别分组:CICategoryColorEffect(色彩校正)、CICategoryBlur(模糊)、CICategoryStylize(风格化)、CICategoryGeometryAdjust(几何变换)。
要创建自定义 CIFilter,开发者编写 Metal 着色器(CIKernel)——一种用 Metal Shading Language 编写的片段着色器,独立处理每个像素。编译后,着色器注册为 CIFilter 的子类,并可与 Apple 的内置滤镜一样在链中使用。
| 类别 | 滤镜示例 | 用途 |
|---|---|---|
| ColorEffect | CIColorControls | 亮度、对比度、饱和度 |
| Blur | CIGaussianBlur | 高斯模糊,可调半径 |
| Stylize | CIPixellate | 像素化图像,可调比例 |
| GeometryAdjust | CIAffineTransform | 通过仿射矩阵旋转、缩放、平移 |
| Composite | CISourceOverCompositing | 带 Alpha 通道的图像叠加 |
CIContext 是一个重量级对象,管理 GPU 资源分配、着色器编译和缓冲。创建 CIContext 是一项昂贵的操作,因此 Apple 建议在整个应用生命周期中只创建一次并重复使用。该上下文绑定到特定的 GPU(Metal、OpenGL)或 CPU,并确定输出图像的色彩空间。
CIFilter 库不断扩展:iOS 17 增加了新的 HDR 处理和机器学习滤镜。所有内置滤镜都在 Apple Developer Documentation 中记录,可按类别或名称搜索。要检测设备上可用的滤镜,请使用 CIFilter.filterNames(inCategory:)。
CoreImage 的主要功能是将多个 CIFilter 组合成链。一个滤镜的输出通过 inputImage 参数作为下一个滤镜的输入。CoreImage 在渲染阶段优化该链:在相同色彩空间中工作的相邻滤镜会合并为一次 GPU 传递(kernel fusion)。这在不需开发者干预的情况下提高了性能。
要创建自定义效果,开发者编写带有 [[kernel]] 注释的 Metal 函数。该函数接收像素坐标并返回颜色。CoreImage 将着色器发送到 GPU,在那里对所有图像像素并行执行。自定义滤镜对于独特的视觉效果特别有用:非线性曲线棕褐色、色散模糊或模拟胶片颗粒。
#include <CoreImage/CoreImage.h>
[[kernel]] float4 customFilter(sample_t s, float intensity) {
float4 result;
result.rgb = s.rgb * (1.0 - intensity) + s.r * intensity;
result.a = s.a;
return result;
}
CoreImage 自动管理中间结果的缓存。如果同一滤镜链应用于不同的图像,CoreImage 可以重用已编译的着色器。为获得最佳性能,避免为每个帧创建 CIContext——使用一个上下文并重置滤镜的输入参数。
CIDetector 是 CoreImage 的子系统,用于检测图像中的语义对象,无需使用 Vision 或 Core ML。CIDetector 支持四种检测类型:人脸(CIDetectorTypeFace)、文本(CIDetectorTypeText)、QR 码(CIDetectorTypeQRCode)和矩形(CIDetectorTypeRectangle)。检测器在 CPU 上运行,并针对 NEON 指令进行了优化,确保了在没有强大 GPU 的设备上也能保持稳定速度。
CIDetectorTypeFace 人脸检测器返回一个 CIFaceFeature 数组,包含人脸边界坐标、眼睛和嘴巴位置。从 iOS 12 开始,CIDetector 还可以检测微笑(hasSmile)以及左/右眼状态(leftEyeClosed、rightEyeClosed)。检测精度足以满足大多数 AR 和照片应用的需求,但对于关键场景,Apple 建议使用 Vision.framework。
CIDetectorTypeRectangle 查找图像中的矩形区域——文档、名片、设备屏幕。检测器返回一个 CIRectangleFeature,包含形成矩形轮廓的四个点。根据 WWDC 2024,矩形检测器使用与 Vision 相同的神经网络架构,但内存消耗更低。这使得它更适合实时帧流处理,例如在文档扫描应用中。
实际示例有助于巩固对 CoreImage 的理解。让我们来看两个典型场景:对照片应用色彩滤镜以及检测人脸并绘制边框。
CISepiaTone 滤镜的基本示例,它将彩色图像转换为棕褐色调。滤镜接受 inputIntensity 参数,范围从 0(原始)到 1(最大效果)。请注意惰性求值:filter.outputImage 返回的 CIImage 不包含像素——渲染仅在调用 context.createCGImage 时发生。
import CoreImage
guard let inputImage = CIImage(image: uiImage) else { return }
let filter = CIFilter(name: "CISepiaTone")
filter?.setValue(inputImage, forKey: kCIInputImageKey)
filter?.setValue(0.8, forKey: kCIInputIntensityKey)
let context = CIContext()
let outputImage = filter?.outputImage
let cgImage = context.createCGImage(outputImage!, from: inputImage.extent)
let resultImage = UIImage(cgImage: cgImage!)
以下示例使用 CIDetector 查找图像中的人脸,并在每个检测到的人脸周围绘制矩形。CIFaceFeature 包含图像坐标系中的坐标(原点在左下角),因此在 UIKit 上绘制时需要通过仿射变换进行坐标转换。
let detector = CIDetector(
ofType: CIDetectorTypeFace,
context: context,
options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]
)
let features = detector?.features(in: inputImage) as? [CIFaceFeature]
for face in features ?? [] {
print("Face bounds: \(face.bounds)")
if face.hasSmile {
print("此人在微笑")
}
}
最后一个示例展示了三个滤镜的链:色彩校正、暗角和纹理叠加。请注意,第一个滤镜的 outputImage 作为 inputImage 传递给第二个——无需中间渲染。调用 createCGImage 时,CoreImage 将三个操作合并为一次 GPU 传递。
let colorFilter = CIFilter(name: "CIColorControls")
colorFilter?.setValue(inputImage, forKey: kCIInputImageKey)
colorFilter?.setValues([
kCIInputBrightnessKey: 0.1,
kCIInputContrastKey: 1.2
])
let vignetteFilter = CIFilter(name: "CIVignette")
vignetteFilter?.setValue(colorFilter?.outputImage, forKey: kCIInputImageKey)
vignetteFilter?.setValue(2.0, forKey: "inputRadius")
let finalImage = vignetteFilter?.outputImage
let result = context.createCGImage(finalImage!, from: inputImage.extent)
常见问题
CoreImage 在 GPU 上运行,针对像素操作(滤镜、色彩校正)进行了优化,而 Core Graphics 是用于矢量绘制和 2D 上下文的 CPU 库。CoreImage 更适合批量图像处理,Core Graphics 更适合逐步绘制界面。
可以—— CoreImage 支持通过 AVPlayerItemVideoOutput 或 AVCaptureOutput 处理单个视频帧。对于流式处理,请使用带 CIFilter 的 AVVideoComposition,这允许在不将帧复制到 CPU 和 GPU 之间的情况下应用效果。
CoreImage 默认在 sRGB 工作色彩空间(kCGColorSpaceSRGB)中运行。创建 CIContext 时,可以指定替代空间——用于 HDR 的扩展线性 sRGB 或用于广色域显示器的 Display P3。
链中的滤镜数量没有限制,但每 5-7 个连续滤镜会产生一次额外的 GPU 传递。对于超过 10 个滤镜,建议将链分成组并渲染中间结果,以避免超出着色器寄存器限制。
可以——CIDetector 在使用 iOS 5.0 及更高版本的所有设备上,通过 NEON 指令在 CPU 上运行。检测精度在所有设备上相同,但在 Apple A12+ 芯片上由于神经网络硬件加速,速度更快。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。