我希望能够相对快速地拍摄图像并将其模糊(例如在 0.1 秒内)。图像大小几乎永远不会大于 256 x 256 像素。
我是否必须遍历每个像素并将它们与邻居平均,还是有更高级别的方法可以做到这一点?
PS:我知道多个框模糊可以近似高斯模糊。
我希望能够相对快速地拍摄图像并将其模糊(例如在 0.1 秒内)。图像大小几乎永远不会大于 256 x 256 像素。
我是否必须遍历每个像素并将它们与邻居平均,还是有更高级别的方法可以做到这一点?
PS:我知道多个框模糊可以近似高斯模糊。
我为 iOS3.2+ 应用程序找到了一种非常快速且非常糟糕的方式
UIView *myView = [self view];
CALayer *layer = [myView layer];
[layer setRasterizationScale:0.25];
[layer setShouldRasterize:YES];
这会将视图光栅化为 4x4 像素块,然后使用双线性过滤将其放大……如果您只想在模态视图下模糊背景视图,它的速度非常快,看起来还不错。
要撤消它,只需将光栅化比例设置回 1.0 或关闭光栅化。
查看 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);
}
如果您总是或至少经常使用相同的模糊设置,您可能会通过在频域而不是空间域中进行过滤来提高速度。
这种方法的优点是与平均邻域相比,逐像素乘法应该非常快。因此,如果您处理大量图像,这可能会有所帮助。
缺点是我不知道在 iPhone 上进行傅立叶变换的速度有多快,所以这很可能比其他实现慢得多。
除此之外,我猜因为 iPhone 支持 OpenGL,你也许可以使用它的纹理功能/绘图来做到这一点。很抱歉,虽然我不是 OpenGL 专家,也不能真正提供任何实用的建议来说明如何做到这一点。
这里有两个解决穷人模糊的技巧:
拍摄图像,以部分不透明度绘制 5 或 6 次(或任何你想要的次数),每次在不同方向偏移几个像素。在更多方向上绘制更多次可以让您获得更好的模糊效果,但您显然会权衡处理时间。如果您想要半径相对较小的模糊,这很有效。
对于单色图像,您实际上可以使用阴影构建作为简单的模糊。
You might want to take a look at Mario Klingemann's StakBlur algorithm. It's not quite Gaussian, but pretty close.
任何通过 openGL 在像素级别上修改图像的算法都会有点慢;对 OpenGL 纹理进行逐像素操作,然后每帧更新它,遗憾的是性能不足。
在着手实施复杂的模糊程序之前,花一些时间编写测试装置并尝试像素操作。
最基本的模糊(或者可能更多的软化)是平均 2 个相邻像素并将平均值应用于两个像素。在整个图像中迭代它,你会得到轻微的模糊(软化)。