如何在iOS上实现框或高斯模糊

时间:2009-07-16 20:30:11

标签: ios image-processing blur

我希望能够拍摄一张图像并相对较快地模糊(例如0.1秒)。图像大小几乎不会大于256 x 256像素。

我是否必须通过每个像素进行循环并将它们与邻居进行平均或者是否有更高级别的方法可以做到这一点?

PS :我知道多个盒子模糊可以接近高斯模糊。

7 个答案:

答案 0 :(得分:35)

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

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

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

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

答案 1 :(得分:5)

来自how-do-i-create-blurred-text-in-an-iphone-view:

看一下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);
}

答案 2 :(得分:4)

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

  1. 预过滤滤镜图像G(u,v),这是一个2D高斯
  2. 将傅里叶变换应用于输入图像f(x,y) - &gt; F(u,v)
  3. 乘法滤波:H(u,v)= F(u,v)。* G(u,v)(逐像素乘法,不是矩阵乘法)
  4. 通过逆傅立叶变换将滤波后的图像变换回空间域:H(u,v) - &gt; H(X,Y)
  5. 这种方法的优点是,与平均邻域相比,逐像素乘法应该相当快。因此,如果您处理大量图像,这可能有所帮助。

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

    除此之外,我想因为iPhone有OpenGL支持,你可以使用它的纹理功能/绘图来做到这一点。很抱歉,虽然我不是OpenGL专家,但无法提供任何实用的建议。

答案 3 :(得分:3)

这是穷人模糊的两个技巧:

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

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

答案 4 :(得分:2)

您可能想看一下Mario Klingemann的StakBlur算法。它不是高斯,但非常接近。

答案 5 :(得分:1)

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

在承诺实施复杂的模糊例程之前花一些时间编写测试装备并尝试像素操作。

答案 6 :(得分:0)

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