Как реализовать поле или гауссову размытость на iOS

В дополнение к другим ответам структура может (но обычно не делает), имеют виртуальные функции, в этом случае размер структуры будет также включать пространство для vtbl.

19
задан Cœur 24 January 2019 в 03:02
поделиться

5 ответов

Если вы всегда или, по крайней мере, часто используете одни и те же настройки размытия, вы можете увеличить скорость, выполняя фильтрацию в частотной области, а не в пространственной.

  1. Предварительно выделите изображение фильтра G (u, v), который является двухмерным гауссовым
  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 и не могу дать практических советов, как это сделать.

4
ответ дан 30 November 2019 в 02:39
поделиться

Любой алгоритм, который изменяет изображения на пиксельном уровне через openGL, будет немного медленным; Попиксельная обработка текстуры openGL с последующим ее обновлением в каждом кадре, к сожалению, недостаточна для производительности.

Потратьте некоторое время на написание тестовой установки и экспериментирование с манипуляциями с пикселями, прежде чем переходить к реализации сложной процедуры размытия.

1
ответ дан 30 November 2019 в 02:39
поделиться

Вот два приема для размытия бедняги:

  1. Возьмите изображение, нарисуйте его с частичной непрозрачностью 5 или 6 (или сколько угодно) раз, каждый раз смещая на пару пикселей в другое направление. рисование большего количества раз в большем количестве направлений дает вам лучшее размытие, но вы, очевидно, жертвуете временем обработки. Это хорошо работает, если вам нужно размытие с относительно небольшим радиусом.

  2. Для монохроматических изображений вы можете фактически использовать построение тени как простое размытие.

3
ответ дан 30 November 2019 в 02:39
поделиться

Возможно, вам стоит взглянуть на алгоритм StakBlur Марио Клингеманна. Это не совсем гауссово, но довольно близко.

2
ответ дан 30 November 2019 в 02:39
поделиться

Из 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);
}
5
ответ дан 30 November 2019 в 02:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: