GPUImage - Как указать размер фильтра для GPUImageMedianFilter и GPUImageGaussianBlurFilter

Привет, сообщество GPUImage и Брэд!

Я хотел бы указать размер фильтра (радиус) GPUImageMedianFilter и GPUImageGaussianBlurFilter.

Требует ли это указания рекомендаций GPU? Или это можно сделать через обертку GPUImage? Если да, то как я могу это сделать?

Спасибо


person vondip    schedule 18.06.2012    source источник


Ответы (2)


Вероятно, здесь не место задавать конкретный вопрос об этом фреймворке, но я могу вам на него ответить.

GPUImageMedianFilter — это жестко запрограммированный медианный фильтр 3x3, основанный на статье Моргана МакГуайра «Быстрый медианный фильтр с малым радиусом действия» Моргана Макгуайра в книге ShaderX6. Подробнее об этом можно узнать здесь, включая версии с большим радиусом. Несмотря на то, что это самая быстрая реализация этого, которую я нашел, она по-прежнему невероятно медленная для всех, кроме самых быстрых устройств iOS, поэтому увеличение области выборки только еще больше замедлит это.

GPUImageGaussianBlurFilter выполняет 9-кратное простое размытие по Гауссу за два отдельных прохода. Свойство blurSize позволяет немного расширить или сузить область выборки, но если вы выйдете за пределы множителя 1,5, вы начнете видеть интерференционные артефакты из-за того, что для размытия большой области используется слишком мало выборок. Я работаю над парой эффективных способов расширения области размытия, но это ограничение данного конкретного фильтра.

person Brad Larson    schedule 23.06.2012
comment
отлично, большое спасибо, Брэд, как за ответ, так и за потрясающую библиотеку! - person vondip; 23.06.2012

Вот как вычислить медиану в выбранном вами радиусе соседства пикселей:

kernel vec4 medianUnsharpKernel(sampler u) {
vec4 pixel = unpremultiply(sample(u, samplerCoord(u)));
vec2 xy = destCoord();
int radius = 3;
int bounds = (radius - 1) / 2;
vec4 sum  = vec4(0.0);
for (int i = (0 - bounds); i <= bounds; i++)
{
    for (int j = (0 - bounds); j <= bounds; j++ )
    {
        sum += unpremultiply(sample(u, samplerTransform(u, vec2(xy + vec2(i, j)))));
    }
}
vec4 mean = vec4(sum / vec4(pow(float(radius), 2.0)));
float mean_avg = float(mean);
float comp_avg = 0.0;
vec4 comp  = vec4(0.0);
vec4 median  = mean;
for (int i = (0 - bounds); i <= bounds; i++)
{
    for (int j = (0 - bounds); j <= bounds; j++ )
    {
        comp = unpremultiply(sample(u, samplerTransform(u, vec2(xy + vec2(i, j)))));
        comp_avg = float(comp);
        median = (comp_avg < mean_avg) ? max(median, comp) : median;
    }
}

return premultiply(vec4(vec3(abs(pixel.rgb - median.rgb)), 1.0)); 
}

Краткое описание шагов 1. Вычислить среднее значение пикселей, окружающих исходный пиксель в окрестности 3x3; 2. Найдите максимальное значение пикселя для всех пикселов в той же окрестности, которые меньше среднего. 3. [ДОПОЛНИТЕЛЬНО] Вычтите срединное значение пикселя из значения исходного пикселя для обнаружения края.

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

person James Bush    schedule 04.07.2015