我编写了以下代码,将棕褐色滤镜应用于图像:
- (void)applySepiaFilter {
// Set previous image
NSData *buffer = [NSKeyedArchiver archivedDataWithRootObject: self.mainImage.image];
[_images push:[NSKeyedUnarchiver unarchiveObjectWithData: buffer]];
UIImage* u = self.mainImage.image;
CIImage *image = [[CIImage alloc] initWithCGImage:u.CGImage];
CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"
keysAndValues: kCIInputImageKey, image,
@"inputIntensity", @0.8, nil];
CIImage *outputImage = [filter outputImage];
self.mainImage.image = [self imageFromCIImage:outputImage];
}
- (UIImage *)imageFromCIImage:(CIImage *)ciImage {
CIContext *ciContext = [CIContext contextWithOptions:nil];
CGImageRef cgImage = [ciContext createCGImage:ciImage fromRect:[ciImage extent]];
UIImage *image = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
return image;
}
当我运行此代码时,它似乎滞后1-2秒。我听说核心图像比核心图形更快,但我对渲染时间不感兴趣。我想知道在CoreGraphics甚至是OpenCV(在项目的其他地方使用)中是否会加快处理速度?如果没有,我有什么方法可以优化此代码以更快地运行?
答案 0 :(得分:8)
我几乎可以保证Core Graphics的速度比使用Core Image慢,具体取决于图像的大小。如果图像很小,Core Graphics可能会很好,但如果你正在进行大量处理,那么它将比使用GPU渲染要慢得多。
核心图像非常快,但是,您必须非常清楚正在发生的事情。 Core Image的大多数性能都是由于设置了上下文,以及将图像复制到Core Image或从Core Image复制图像。除了复制字节外,Core Image也可以在图像格式之间进行转换。
您的代码每次都在执行以下操作:
这不是达到最佳表现的方法。 CGImage的字节通常存在于CPU内存中,但Core Image希望使用GPU进行处理。
Core Image的Getting the Best Performance文档中提供了有关性能注意事项的出色参考:
- 每次渲染时都不要创建CIContext对象。 上下文存储了大量的状态信息;重用它们会更有效率。
- 评估您的应用是否需要色彩管理。除非您需要,否则不要使用它。看看您的应用是否需要色彩管理?。
使用GPU上下文渲染CIImage对象时,请避免使用Core Animation动画。 如果您需要同时使用两者,则可以将两者设置为使用CPU。
确保图像不超过CPU和GPU限制。 (IOS)
尽可能使用较小的图像。 性能随输出像素数量而变化。您可以将Core Image渲染为较小的视图,纹理或帧缓冲区。允许核心动画升级以显示大小。
使用核心图形或图像I / O函数进行裁剪或缩减采样,例如函数CGImageCreateWithImageInRect或CGImageSourceCreateThumbnailAtIndex。
UIImageView类最适合静态图像。 如果您的应用需要获得最佳性能,请使用较低级别的API。
避免CPU和GPU之间不必要的纹理传输。 在应用内容比例因子之前,渲染为与源图像大小相同的矩形。
考虑使用更简单的过滤器,它可以产生类似于算法过滤器的结果。 例如,CIColorCube可以产生类似于CISepiaTone的输出,并且效率更高。
利用iOS 6.0及更高版本中对YUV图像的支持。
如果您需要实时处理性能,则需要使用CoreImage可以将其输出呈现的OpenGL视图,并将图像字节直接读入GPU而不是从CGImage中提取。使用GLKView
和覆盖drawRect:
是一个相当简单的解决方案,可以获得Core Image可以直接渲染的视图。将数据保存在GPU上是从Core Image获得最佳性能的最佳方式。
尝试尽可能多地重复使用。为后续渲染保留CIContext
(如文档所述)。如果您最终使用OpenGL视图,那么这些也是您可能希望尽可能多地重复使用的内容。
通过使用软件渲染,您也可以获得更好的性能。软件渲染可以避免复制到GPU或从GPU复制。 [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer: @(YES)}]
但是,这在实际渲染中会有性能限制,因为CPU渲染通常比GPU渲染慢。
因此,您可以选择难度级别以获得最佳性能。最好的表现可能更具挑战性,但一些调整可能会让你接受"可接受的"用例的性能。