2016-04-28 71 views
0

我写了下面的代码到怀旧滤镜应用于图像:目标C提高CIImage过滤速度

- (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

你用仪器找出这里真的很慢吗? – zneak

+0

@zneak这些工具是什么? –

+0

掉下我的脑袋,像“时间分析器”。 – zneak

回答

3

根据图像的大小,我几乎可以保证它在核心图形上的速度比使用核心图像要慢。如果图像很小,Core Graphics可能会很好,但如果您正在进行大量处理,则会比使用GPU渲染慢得多。

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

你的代码做什么,每次执行以下操作:

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

这不是峰值性能的配方。 CGImage中的字节通常位于CPU内存中,但Core Image想要使用GPU进行处理。在Getting the Best Performance文档中提供

出于性能考虑一个很好的参考为核心图片:

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

  • 确保图像不超过CPU和GPU限制。 (iOS)

  • 尽可能地使用较小的图像。 性能与输出像素数量成比例。您可以将Core Image呈现为更小的视图,纹理或帧缓冲区。允许Core Animation高级显示大小。

  • 使用核心图形或图像I/O函数来裁剪或缩小比例,如函数CGImageCreateWithImageInRect或CGImageSourceCreateThumbnailAtIndex。

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

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

  • 考虑使用更简单的过滤器,可以产生类似于算法过滤器的结果。例如,CIColorCube可以产生类似于CISepiaTone的输出,并且可以更高效地执行此操作。

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

如果你需要实时处理性能,你将要使用的OpenGL认为CoreImage可以输出渲染,以及读取图像直接字节到GPU,而不是从一个CGImage拉的。使用GLKView和覆盖drawRect:是一个相当简单的解决方案,可以获得Core Image可以直接渲染的视图。在GPU上保存数据是获得Core Image峰值性能的最佳方式。

尽量重复使用。为后续渲染保留CIContext(如文档所述)。如果你最终使用OpenGL视图,这些也是你可能想要尽可能重用的东西。

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

因此,您可以选择难度水平来获得最佳性能。最好的性能可能会更具挑战性,但是一些调整可能会使您的使用情况达到“可接受”的性能。