Objective C提高了CIImage过滤速度

Tyl*_*ert 1 performance opencv core-graphics objective-c 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;
}
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,它似乎滞后1-2秒.我听说核心图像比核心图形更快,但我对渲染时间不感兴趣.我想知道在CoreGraphics甚至是OpenCV(在项目的其他地方使用)中是否会加快处理速度?如果没有,我有什么方法可以优化此代码以更快地运行?

Kek*_*koa 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 的最佳性能文档中提供了性能考虑因素的出色参考:

  • 每次渲染时都不要创建CIContext对象.上下文存储了大量的状态信息; 重用它们更有效.
  • 评估您的应用是否需要色彩管理.除非您需要,否则不要使用它.看看你的应用需要色彩管理吗?
  • 使用GPU上下文渲染CIImage对象时,请避免使用Core Animation动画.如果您需要同时使用两者,则可以将两者设置为使用CPU.

  • 确保图像不超过CPU和GPU限制.(IOS)

  • 尽可能使用较小的图像.性能随输出像素数量而变化.您可以将Core Image渲染为较小的视图,纹理或帧缓冲区.允许核心动画升级以显示大小.

  • 使用Core Graphics或Image I/O函数进行裁剪或缩减采样,例如函数CGImageCreateWithImageInRect或CGImageSourceCreateThumbnailAtIndex.

  • UIImageView类最适合静态图像.如果您的应用需要获得最佳性能,请使用较低级别的API.

  • 避免CPU和GPU之间不必要的纹理传输.在应用内容比例因子之前,渲染到与源图像大小相同的矩形.

  • 考虑使用更简单的过滤器,它可以产生类似于算法过滤器的结果.例如,CIColorCube可以产生类似于CISepiaTone的输出,并且可以更有效地完成输出.

  • 利用iOS 6.0及更高版本中对YUV图像的支持.

如果您需要实时处理性能,您将需要使用CoreImage可以将其输出呈现给的OpenGL视图,并将您的图像字节直接读取到GPU中,而不是从CGImage中提取它.使用a GLKView和overriding drawRect:是一个相当简单的解决方案,可以获得Core Image可以直接渲染的视图.将数据保存在GPU上是从Core Image中获得最佳性能的最佳方法.

尝试尽可能多地重用.保持CIContext随后的渲染(如文档所述).如果您最终使用OpenGL视图,那么这些也是您可能希望尽可能重复使用的内容.

您也可以通过使用软件渲染来获得更好的性能.软件渲染可以避免复制到GPU或从GPU复制.[CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer: @(YES)}]但是,这在实际渲染中会有性能限制,因为CPU渲染通常比GPU渲染慢.

因此,您可以选择难度级别以获得最佳性能.最佳性能可能更具挑战性,但一些调整可能会使您的用例达到"可接受"的性能.