19

我希望能够相对快速地拍摄图像并将其模糊(例如在 0.1 秒内)。图像大小几乎永远不会大于 256 x 256 像素。

我是否必须遍历每个像素并将它们与邻居平均,还是有更高级别的方法可以做到这一点?

PS:我知道多个框模糊可以近似高斯模糊。

4

7 回答 7

36

我为 iOS3.2+ 应用程序找到了一种非常快速且非常糟糕的方式

  UIView *myView = [self view];
  CALayer *layer = [myView layer];
  [layer setRasterizationScale:0.25];
  [layer setShouldRasterize:YES];

这会将视图光栅化为 4x4 像素块,然后使用双线性过滤将其放大……如果您只想在模态视图下模糊背景视图,它的速度非常快,看起来还不错。

要撤消它,只需将光栅化比例设置回 1.0 或关闭光栅化。

于 2010-11-22T21:12:00.867 回答
5

我如何在 iPhone 视图中创建模糊文本:

查看 Apple 的 GLImageProcessing iPhone 示例。除其他外,它会进行一些模糊处理。

相关代码包括:

static void blur(V2fT2f *quad, float t) // t = 1
{
    GLint tex;
    V2fT2f tmpquad[4];
    float offw = t / Input.wide;
    float offh = t / Input.high;
    int i;

    glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);

    // Three pass small blur, using rotated pattern to sample 17 texels:
    //
    // .\/.. 
    // ./\\/ 
    // \/X/\   rotated samples filter across texel corners
    // /\\/. 
    // ../\. 

    // Pass one: center nearest sample
    glVertexPointer  (2, GL_FLOAT, sizeof(V2fT2f), &quad[0].x);
    glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &quad[0].s);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glColor4f(1.0/5, 1.0/5, 1.0/5, 1.0);
    validateTexEnv();
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    // Pass two: accumulate two rotated linear samples
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    for (i = 0; i < 4; i++)
    {
        tmpquad[i].x = quad[i].s + 1.5 * offw;
        tmpquad[i].y = quad[i].t + 0.5 * offh;
        tmpquad[i].s = quad[i].s - 1.5 * offw;
        tmpquad[i].t = quad[i].t - 0.5 * offh;
    }
    glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &tmpquad[0].x);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glActiveTexture(GL_TEXTURE1);
    glEnable(GL_TEXTURE_2D);
    glClientActiveTexture(GL_TEXTURE1);
    glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &tmpquad[0].s);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,      GL_INTERPOLATE);
    glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB,         GL_TEXTURE);
    glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB,         GL_PREVIOUS);
    glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB,         GL_PRIMARY_COLOR);
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,     GL_SRC_COLOR);
    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,    GL_REPLACE);
    glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA,       GL_PRIMARY_COLOR);

    glColor4f(0.5, 0.5, 0.5, 2.0/5);
    validateTexEnv();
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    // Pass three: accumulate two rotated linear samples
    for (i = 0; i < 4; i++)
    {
        tmpquad[i].x = quad[i].s - 0.5 * offw;
        tmpquad[i].y = quad[i].t + 1.5 * offh;
        tmpquad[i].s = quad[i].s + 0.5 * offw;
        tmpquad[i].t = quad[i].t - 1.5 * offh;
    }
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    // Restore state
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glClientActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, Half.texID);
    glDisable(GL_TEXTURE_2D);
    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,     GL_SRC_ALPHA);
    glActiveTexture(GL_TEXTURE0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glDisable(GL_BLEND);
}
于 2009-08-10T18:49:14.137 回答
4

如果您总是或至少经常使用相同的模糊设置,您可能会通过在频域而不是空间域中进行过滤来提高速度。

  1. 预先计算您的过滤器图像 G(u,v),它是一个 2D 高斯
  2. 对输入图像应用傅立叶变换 f(x,y)->F(u,v)
  3. 乘法过滤: H(u,v) = F(u,v) .* G(u,v) (像素乘法,不是矩阵乘法)
  4. 通过逆傅里叶变换将过滤后的图像转换回空间域:H(u,v) -> h(x,y)

这种方法的优点是与平均邻域相比,逐像素乘法应该非常快。因此,如果您处理大量图像,这可能会有所帮助。

缺点是我不知道在 iPhone 上进行傅立叶变换的速度有多快,所以这很可能比其他实现慢得多。

除此之外,我猜因为 iPhone 支持 OpenGL,你也许可以使用它的纹理功能/绘图来做到这一点。很抱歉,虽然我不是 OpenGL 专家,也不能真正提供任何实用的建议来说明如何做到这一点。

于 2009-07-17T08:57:19.347 回答
3

这里有两个解决穷人模糊的技巧:

  1. 拍摄图像,以部分不透明度绘制 5 或 6 次(或任何你想要的次数),每次在不同方向偏移几个像素。在更多方向上绘制更多次可以让您获得更好的模糊效果,但您显然会权衡处理时间。如果您想要半径相对较小的模糊,这很有效。

  2. 对于单色图像,您实际上可以使用阴影构建作为简单的模糊。

于 2009-07-16T20:59:38.293 回答
2

You might want to take a look at Mario Klingemann's StakBlur algorithm. It's not quite Gaussian, but pretty close.

于 2009-07-16T20:47:23.513 回答
1

任何通过 openGL 在像素级别上修改图像的算法都会有点慢;对 OpenGL 纹理进行逐像素操作,然后每帧更新它,遗憾的是性能不足。

在着手实施复杂的模糊程序之前,花一些时间编写测试装置并尝试像素操作。

于 2009-07-20T09:40:52.243 回答
0

最基本的模糊(或者可能更多的软化)是平均 2 个相邻像素并将平均值应用于两个像素。在整个图像中迭代它,你会得到轻微的模糊(软化)。

于 2010-11-20T13:15:11.453 回答