2013-02-20 85 views
31

我一直在寻找过去三天内置的,硬件加速的android模糊位图的方法。我偶然发现了一些缩小位图并将其扩展的解决方法,但是这种方法产生的低质量结果不适合我的图像识别要求。我还读到,使用着色器或JNI实现卷积是一个很好的方法,但我不相信Android框架中没有内置的解决方案来实现这个共同的目的。目前我已经用Java编写了一个自编写的卷积实现,但速度很慢。我的问题是:Android:快速位图模糊?

  • 真正的Android框架没有内置的解决方案
  • 如果没有的话:在仍然合理的实施和维护复杂度下加速卷积的最有效方法是什么?我们应该使用JNI,着色器还是完全不同的东西?

回答

68

我终于找到一个合适的解决方案:

  • RenderScript允许执行那些被透明地缩放到执行装置上的所有可用核重计算。我得出结论,就性能和实现复杂性的合理平衡而言,这是比JNI或着色器更好的方法。
  • 由于API级别17,有API可用的ScriptIntrinsicBlur类。这正是我一直在寻找的,即高水平的硬件加速高斯模糊实现。
  • ScriptIntrinsicBlur现在是支持Froyo及以上(API> 8)的android支持库(v8)的一部分。有关如何使用它的一些基本技巧,support RenderScript library上的Android开发人员博客帖子。

但是,关于ScriptIntrinsicBlur类的文档非常少见,我花了一些时间来计算正确的调用参数。对于bluring名为photo普通ARGB_8888 -typed位图,在这里,他们是:

final RenderScript rs = RenderScript.create(myAndroidContext); 
final Allocation input = Allocation.createFromBitmap(rs, photo, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 
final Allocation output = Allocation.createTyped(rs, input.getType()); 
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); 
script.setRadius(myBlurRadius /* e.g. 3.f */); 
script.setInput(input); 
script.forEach(output); 
output.copyTo(photo); 
+2

@ thV0ID:很好的答案。有什么办法可以使它向后兼容,也可以在ICS中工作? – 2013-07-13 07:03:29

+0

@BhaveshPatadiya:您可以使用RenderScript实现快速卷积并使用高斯内核。在RenderScript中实现卷积的一个例子可以在这里找到:http://stackoverflow.com/a/10257994/1444073 – theV0ID 2013-07-31 19:39:05

+3

RS现在是兼容性库的一部分,renderscript-v8.jar – Gabor 2013-09-24 15:44:23

11

可能是最苛刻的要求是活的模糊,这意味着你活的模糊效果的观点变化。在这种情况下,模糊不应该花费超过10秒左右(使一些游戏室进入16ms/60fps)看起来很平滑。即使不是那么高端的设备(galaxy s3,甚至更慢),也可以通过正确的设置来实现这种效果。

这里是如何按重要性提高性能:

  1. 使用缩小的图片: 这降低了像素极大模糊。当你想要一个真实的模糊图像时,它也适用于你。图像加载和内存消耗也大幅降低。

  2. 使用Renderscript ScriptIntrinsicBlur - 2014年Android中可能没有更好/更快的解决方案。我经常看到的一个错误是,Renderscript上下文没有被重用,但每次使用blur模式时都会创建。请注意,在Nexus 5上,RenderScript.create(this);需要20ms左右,所以您想避免这种情况。

  3. 重用位图:不要创建不必要的实例并始终使用相同的实例。当你需要真正快速的模糊时,垃圾收集扮演着重要角色(收集一些位图需要10-20毫秒的时间)。也裁剪和模糊只有你需要的东西。

  4. 对于活动模糊,可能是因为上下文切换,它不可能在另一个线程中模糊(即使使用线程池),只有主线程足够快以保持视图更新及时,线程我看到滞后100-300ms

更多的提示,请参阅我在这里的其他职位https://stackoverflow.com/a/23119957/774398

BTW。我在这个应用程序做了一个简单的生活模糊:github,Playstore

+0

关于#2,我看不出它有这样的好品质模糊(见这里:http://stackoverflow.com/q/36447630/878126)。另外,你真的暗示st Renderscript对象将保留整个应用程序生命周期,而不需要调用“destroy()”? – 2016-04-06 09:58:13

+0

嗨,我想你已经在你的文章中发现了质量差的错误(我想说我不能重新编制你的错误输出)。对于第二点:如果你模糊了,当然不会破坏上下文。请记住,创建上下文是昂贵的 – for3st 2016-04-06 13:02:18

+0

质量差 - 我不确定原因(因为我使用了其他示例和教程代码),但我使用了“createTyped”,现在它可以工作。如果你可以在那里写下我为什么会遇到这些问题,那就太好了。关于“销毁上下文”,我正在谈论RenderScript.create。如果我在应用中的很多地方模糊图像,应该没问题,永远不要销毁它,对吧?另外,它用于争论的是什么语境? – 2016-04-06 14:04:19