Как реализовать рамку или размытие по Гауссу на iOS
Я хочу иметь возможность сделать снимок и размыть его относительно быстро (скажем, через 0,1 сек). Размер изображения почти никогда не будет больше 256 х 256 пикселей.
Нужно ли цитировать по каждому пикселю и усреднять их с соседями или есть способ более высокого уровня, который я мог бы сделать?
PS: я знаю, что несколько размытых ящиков могут аппроксимировать гауссовское размытие.
Ответы
Ответ 1
Я нашел очень быстрый довольно дрянной способ для iOS3.2 + приложений
UIView *myView = [self view];
CALayer *layer = [myView layer];
[layer setRasterizationScale:0.25];
[layer setShouldRasterize:YES];
Это растрирует представление до 4x4 пикселей, а затем масштабирует его обратно с использованием билинейной фильтрации... оно ЧРЕЗВЫЧАЙНО быстро и выглядит нормально, если вы просто хотите размыть фоновый вид под модальным видом.
Чтобы отменить его, просто установите масштаб растеризации на 1,0 или отключите растрирование.
Ответ 2
Из how-do-i-create-blurred-text-in-a-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);
}
Ответ 3
Если вы всегда или хотя бы часто используете одинаковые настройки размытия, вы можете увеличить скорость, выполнив фильтрацию в частотной области вместо пространственного домена.
- Докажите свое изображение фильтра G (u, v), которое является 2D-гауссовым
- Применить преобразование Фурье к вашему входному изображению f (x, y) → F (u, v)
- Фильтр умножением: H (u, v) = F (u, v). * G (u, v) (умножение в пикселях, а не матричное умножение)
- Преобразуйте отфильтрованное изображение обратно в пространственную область с помощью обратного преобразования Фурье: H (u, v) → h (x, y)
Преимуществом такого подхода является то, что умножение по пикселям должно быть довольно быстрым по сравнению с усреднением окрестности. Поэтому, если вы обрабатываете много изображений, это может помочь.
Недостатком является то, что я понятия не имею, как быстро вы можете преобразовывать Фурье на iPhone, поэтому это может быть намного медленнее, чем другие реализации.
Кроме того, я думаю, поскольку iPhone поддерживает OpenGL, вы можете использовать его функции текстурирования/рисования для этого. Извините, что я не эксперт по OpenGL и не могу дать практические советы, как это делается.
Ответ 4
Здесь два трюка для размывания бедных:
-
Возьмите изображение, нарисуйте его с частичной непрозрачностью 5 или 6 (или сколько угодно) раз каждый раз, когда вы смещаете пару пикселей в другом направлении. рисование большего количества раз в более направлениях дает вам лучшее размытие, но вы, очевидно, торгуете временем обработки. Это хорошо работает, если вы хотите размытие с относительно небольшим радиусом.
-
Для монохромных изображений вы можете использовать конструкцию в тени как простое размытие.
Ответ 5
Вы можете взглянуть на алгоритм Mario Klingemann StakBlur. Это не совсем гауссово, но довольно близко.
Ответ 6
Любой алгоритм, который модифицирует изображения на уровне пикселей через openGL, будет медленным; пиксельно-пиксельные манипуляции на текстуре openGL, а затем обновлять их каждый кадр, к сожалению, недостаточно.
Потратьте некоторое время на создание тестовой установки и экспериментируйте с манипуляциями с пикселями, прежде чем совершать сложную процедуру размытия.
Ответ 7
Самый простой размытие (или, может быть, более мягкое) - это средний 2 соседних пикселя и применение среднего к обоим пикселям. повторите это по всему изображению, и вы получите небольшое размытие (размягчение).