Objective C提高了CIImage过滤速度

时间:2016-04-28 20:40:34

标签: objective-c performance opencv core-graphics core-image

我编写了以下代码,将棕褐色滤镜应用于图像:

- (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(在项目的其他地方使用)中是否会加快处理速度?如果没有,我有什么方法可以优化此代码以更快地运行?

1 个答案:

答案 0 :(得分:8)

我几乎可以保证Core Graphics的速度比使用Core Image慢,具体取决于图像的大小。如果图像很小,Core Graphics可能会很好,但如果你正在进行大量处理,那么它将比使用GPU渲染要慢得多。

核心图像非常快,但是,您必须非常清楚正在发生的事情。 Core Image的大多数性能都是由于设置了上下文,以及将图像复制到Core Image或从Core Image复制图像。除了复制字节外,Core Image也可以在图像格式之间进行转换。

您的代码每次都在执行以下操作:

  • 创建CIContext。 (慢)
  • 从CGImage中获取字节并创建CIImage。
  • 将图像数据复制到GPU(慢)。
  • 处理棕褐色滤镜(快速)。
  • 将结果图像复制回CGImage。 (慢)

这不是达到最佳表现的方法。 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渲染慢。

因此,您可以选择难度级别以获得最佳性能。最好的表现可能更具挑战性,但一些调整可能会让你接受"可接受的"用例的性能。