【问题标题】:Fast blur on iOSiOS 上的快速模糊
【发布时间】:2012-09-04 20:37:54
【问题描述】:

我在尝试模糊 iOS 应用中的部分屏幕时遇到了麻烦。请参阅图片以更好地了解我正在尝试做的事情。

只有“BlurBox”的内容需要模糊,其余的可以清晰。因此,如果您正在查看表格视图,则只有 BlurBox 下方的内容会变得模糊(即使在您滚动时)。其余的看起来很清楚。

我的第一种方法是每隔 0.01 秒调用一次UIGraphicsGetImageFromCurrentImageContext(),以将 BlurBox 下的所有图层合并到一个图像中。然后模糊该图像并将其显示到所有内容上。

我尝试过的模糊方法是:

https://github.com/tomsoft1/StackBluriOS

https://github.com/coryleach/UIImageAdjust

https://github.com/esilverberg/ios-image-filters

https://github.com/cmkilger/CKImageAdditions

[layer setRasterizationScale:0.25];
[layer setShouldRasterize:YES];

以及一些自定义尝试。我还查看了 Apple 的 GLImageProcessing,但我认为这对于我在这里尝试做的事情来说有点矫枉过正。

问题是它们都 。该应用程序不在应用程序商店中,因此我愿意使用任何私有/未记录的框架。

我的一个想法是覆盖我使用的所有组件(UITableViewCells、UITableView 等)的drawRect 方法,并在运行中独立地模糊每个组件。然而这需要一些时间,这听起来像是一个可行的选择吗?


更新

我尝试使用CIFilters如下:

CIImage *inputImage = [[CIImage alloc] initWithImage:[self screenshot]];

CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[blurFilter setDefaults];
[blurFilter setValue: inputImage forKey: @"inputImage"];
[blurFilter setValue: [NSNumber numberWithFloat:10.0f]
                           forKey:@"inputRadius"];


CIImage *outputImage = [blurFilter valueForKey: @"outputImage"];

CIContext *context = [CIContext contextWithOptions:nil];

self.bluredImageView.image = [UIImage imageWithCGImage:[context createCGImage:outputImage fromRect:outputImage.extent]];

这确实有效,但是速度非常慢。 :(

我看到某些实现只有在我传入从磁盘加载的图像时才会模糊。如果我传入使用UIGraphicsGetImageFromCurrentImageContext() 创建的 UIImage,它就不起作用。关于为什么会这样的任何想法?


更新

我已经尝试过patel的建议如下:

CALayer *backgroundLayer = [CALayer layer];

CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[blurFilter setDefaults];
backgroundLayer.backgroundFilters = [NSArray arrayWithObject:blurFilter];

[[self.view layer] addSublayer:backgroundLayer];

但是,它不起作用:(


添加赏金后的更新:

我已经设法使用TomSoft1's stackblur 使 BlurBox 正常工作,因为他添加了动态将图像标准化为 RGBA 格式(32 位/像素)的功能。但是,它仍然很慢。

我有一个计时器,每 0.03 秒调用一次更新,以抓取 BlurBox 下方的图像,模糊该图像,并将其显示在屏幕上。我需要帮助来提高 BlurBox 上的“fps”。

【问题讨论】:

  • CIBoxBlur 在 iOS 上不存在。试试CIGaussianBlur
  • Oups...刚刚看到 CIGaussianBlur 在 iOS 5 上也不存在
  • GIGaussianBlur 确实有效,但它真的很慢。
  • 啊...我在看内置类别
  • 只是提到StackBluriOS不适用于iOS 6.0

标签: objective-c image image-processing uiimageview core-graphics


【解决方案1】:

我会推荐Brad Larson 的 GPUImage,它完全由 GPU 支持,可用于各种图像处理效果。它非常快,甚至足够快,以至于在他的演示应用程序中,他从摄像头进行实时视频处理,并且帧速率非常好。

https://github.com/BradLarson/GPUImage

这是我编写的代码 sn-p,用于应用基本的框模糊,它模糊了图像的底部和顶部三分之一,但不模糊图像的中间。他的库非常丰富,几乎包含了所有可以想象到的图像滤镜效果。

GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:[self screenshot]];

GPUImageTiltShiftFilter *boxBlur = [[GPUImageTiltShiftFilter alloc] init];
        boxBlur.blurSize = 0.5;

[stillImageSource addTarget:boxBlur];

[stillImageSource processImage];

UIImage *processedImage = [stillImageSource imageFromCurrentlyProcessedOutput];

【讨论】:

  • 我建议使用 GPUImageUIElement 作为需要模糊的项目的输入。如果您只想模糊 UI 元素的一部分,您可以修改 GPUImageGaussianSelectiveBlurFilter 以覆盖矩形区域,而不是圆形区域。
  • 与我的老板交谈后,我担心我将无法使用这个让我的生活轻松 10000 倍的很棒的库。我们可以使用外部“类”,但不能使用完整的库。应该是一些法律上的废话。但是,我认为我可以使用 Brad 的代码作为抽象我需要的部分的起点。这非常有帮助,谢谢。 +150 的建议和 +2^56 的 @BradLarson 开源这个很棒的代码。
  • 谢谢,对不起,您不能完全使用它。 @BradLarson 只是好奇为什么在 GPUImagePicture 上使用 GPUImageUIElement?
  • @cory - 这似乎是一个奇怪的限制,因为使用几个类和完整框架之间在许可方面没有真正的区别。我想您可以从框架中挑选出您需要的类,例如 GPUImageOutput、GPUImageUIElement、GPUImageFilter 和修改后的 GPUImageSelectiveBlurFilter(以及一些依赖项),然后将它们直接构建到您的应用程序中。您可以避免以这种方式将框架用作静态库。我以前没有人对代码有任何问题,因为我不在乎人们如何使用它或从中赚钱。
  • @cory - 各个类应该可以自己使用,只要您引入适当的超类和一两个支持元素。您不需要从其中提取任何内容。如果您不熟悉 OpenGL ES 2.0,其中有很多脚手架代码可能很难分解。
【解决方案2】:

虽然回复可能有点晚,但您可以使用 Core Image 滤镜。这么慢的原因就是这条线。

CIContext *context = [CIContext contextWithOptions:nil];

在 Apple 文档中,他们首先声明要在 Core Image 中获得最佳性能

“不要在每次渲染时都创建 CIContext 对象。 上下文存储了大量的状态信息;重复使用它们会更有效。”

我个人对此的解决方案是为核心图像上下文创建一个单例。所以我只创造了一个。

我的代码在 GitHub 上的这个演示项目中。

https://github.com/KyleLopez/DemoCoreImage

随意使用它,或找到您喜欢的其他解决方案。我在 CoreImage 中发现的最慢的部分是上下文,之后的图像处理速度非常快。

【讨论】:

  • 感谢您的回复,iOS7 指日可待,我认为这个问题几乎已经过时,但我查看了您的项目,非常有帮助。
  • 恐怕这不是它慢的原因。我已经分析了这种模糊操作,并且渲染模糊图像需要 99.9% 的时间。制作上下文所花费的时间甚至没有显示出来。
  • 根据苹果文档,CoreImage 上下文似乎同时支持 CPU 和 GPU 渲染。有上下文选项可以禁用软件渲染器 (CPU),作为回报,强制上下文使用 GPU。
  • 您绝对应该尝试回收 CIContext - 不这样做会带来巨大的性能开销。 @w0mbat 关于性能影响处于模糊状态而不是在上下文创建中的观察是错误的。这很可能是真的,但是模糊需要时间的原因是它需要做很多设置(例如加载和编译着色器来进行模糊)。如果你重用上下文,模糊不需要重新创建着色器,它应该运行得更快。
【解决方案3】:

我尚未对此进行测试,但我想知道您是否可以在您希望框模糊的位置放置一个CALayer,然后找到一个有用的CIFilter,您可以在CALayer's backgroundFilters 上设置它。只是一个想法。

CALayer.backgroundFilters

【讨论】:

  • 可能是 compositingFilter 是要使用的。
  • 已阅读更多内容。好像 API 就在那里,但不会有任何效果...真可惜
  • 您还有其他想法我可以尝试吗?
  • iOS 上的 CALayer 不支持过滤器 - 背景、合成和过滤器 - 仅用于存储指向过滤器的指针。
【解决方案4】:

您可以尝试 Apple Core Image Filter (CIFilter) 例程集。它们需要 iOS 5,因此您可能无法使用它们。

我不确定它是否比您尝试的方法更快,但我过去在项目中使用过它,并且效果非常好。如果您可以抓住您想要模糊的屏幕部分,将其放入图像中,通过过滤器,然后将其重新显示在屏幕上的适当位置,那应该可以。

我使用滤镜实时更改图像的颜色,效果很好。

http://developer.apple.com/library/ios/#DOCUMENTATION/GraphicsImaging/Reference/QuartzCoreFramework/Classes/CIFilter_Class/Reference/Reference.html

【讨论】:

  • 您是否介意发布一些关于您如何做到这一点的代码。我昨天尝试了几个小时,但永远无法让它与 CIFilters 一起工作。我用我尝试过的一些方法注意到了什么,它只会在我传递从磁盘加载的图像时变得模糊。如果我试图通过它,我会用 UIGraphicsGet.. 抓取它。它不会起作用。
  • 我更新了我的问题以展示我如何使用 CIFilter。你能检查一下正确性吗?
  • 看起来您已经让 CIFilter 与 GIGaussianBlur 一起工作(来自上面的更新),而且速度太慢了。我使用了不同的过滤器,在这里没有帮助,抱歉。
【解决方案5】:

你试过这个库吗:

https://github.com/gdawg/uiimage-dsp

它使用 vDSP/Accelerate 框架,看起来很容易使用。

顺便说一句:0.01 秒似乎太快了。 0.03 应该也可以。

【讨论】:

  • 如果我提出它,它仍然落后于刷新率。是的,我试过 gdawg 的图书馆。问题是它不会模糊我用 UIGraphicsGet.. 抓取的图像。它只会模糊我从磁盘加载的图像。知道为什么会这样吗?
  • @random UIImage 由 CIImage 或 CGImage 支持:但 gdawg 的库仅支持 CGImage(my current Swift port 也是如此)。但是,如果您愿意,可以将 CIImage 转换为 CGImage。或者你可以考虑使用my renderImage or my cropped 来保留一个CGImage。
猜你喜欢
  • 2016-12-02
  • 1970-01-01
  • 2021-11-09
  • 2013-02-05
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多