Подтвердить что ты не робот

Как гауссовское размытие изображения без использования встроенных функций gaussian?

Я хочу размыть свое изображение, используя собственную формулу размытия по Гауссу. Я прочитал статью в Википедии, но не уверен, как это реализовать.

Как использовать формулу для определения веса?

Я не хочу использовать какие-либо встроенные функции, такие как MATLAB

4b9b3361

Ответ 1

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

Представьте, что у вас есть изображение, определенное следующим образом:

 0  1  2  3  4  5  6  7  8  9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99

Размерная матрица фильтра 3x3 определяется следующим образом:

0.111 0.111 0.111
0.111 0.111 0.111
0.111 0.111 0.111

Чтобы применить гауссовское размытие, вы должны сделать следующее:

Для пикселя 11 вам нужно будет загружать пиксели 0, 1, 2, 10, 11, 12, 20, 21, 22.

то вы умножите пиксель 0 на верхнюю левую часть фильтра размытия 3x3. Пиксель 1 - верхняя часть, пиксель 2, пиксель 3 - верхний правый, пиксель 10 - средний левый и т.д.

Затем добавьте их полностью и напишите результат на пиксель 11. Как вы можете видеть, Pixel 11 теперь является средним значением самого себя и окружающих пикселей.

Крайние случаи становятся немного сложнее. Какие значения вы используете для значений края текстуры? Один из способов - обернуть вокруг к другой стороне. Это выглядит хорошо для изображения, которое позже выложено плиткой. Другой способ - нажать пиксель в окружающие места.

Итак, для верхнего левого вы можете поместить образцы следующим образом:

 0  0  1
 0  0  1
10 10 11

Надеюсь, вы увидите, как это можно легко распространить на большие ядра фильтров (например, 5x5 или 9x9 и т.д.).

Разница между гауссовским фильтром и фильтром окна - это числа, которые идут в матрице. Гауссовский фильтр использует гауссовское распределение по строке и столбцу.

например, для фильтра, определенного произвольно как (т.е. это не гауссовский, но, вероятно, не за горами)

0.1 0.8 0.1

первый столбец будет таким же, но будет умножен на первый элемент строки выше.

0.01 0.8 0.1
0.08 
0.01 

Второй столбец будет таким же, но значения будут умножены на 0,8 в строке выше (и так далее).

0.01 0.08 0.01
0.08 0.64 0.08
0.01 0.08 0.01

Результат добавления всех вышеперечисленных вместе должен равняться 1. Разница между указанным фильтром и исходным фильтром окна заключается в том, что написанный конечный пиксель будет иметь гораздо более тяжелый вес по отношению к центральному пикселю (то есть тот, который равен в этой позиции уже). Размытие происходит, потому что окружающие пиксели размываются в этом пикселе, хотя и не так сильно. Используя такой фильтр, вы получаете размытие, но не уничтожаете информацию о высокой частоте (то есть о быстром изменении цвета с пикселя на пиксель).

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

Изменить: Ядро фильтра 5x5 определяется точно так же, как указано выше.

например, если ваша строка равна 0,1 0,2 0,4 0,2 0,1, то если вы умножаете каждое значение в своем первом элементе для формирования столбца, а затем умножаете каждый на второй элемент на второй столбец и так далее, вы получите с фильтром

0.01 0.02 0.04 0.02 0.01
0.02 0.04 0.08 0.04 0.02
0.04 0.08 0.16 0.08 0.04
0.02 0.04 0.08 0.04 0.02
0.01 0.02 0.04 0.02 0.01

взяв некоторые произвольные позиции, вы можете видеть, что позиция 0, 0 проста 0.1 * 0.1. Положение 0, 2 составляет 0,1 * 0,4, положение 2, 2 составляет 0,4 * 0,4, а положение 1, 2 составляет 0,2 * 0,4.

Надеюсь, это даст вам достаточно хорошее объяснение.

Ответ 2

Здесь псевдокод для кода, который я использовал в С#, для вычисления ядра. Я не смею утверждать, что я правильно отношусь к конечным условиям:

double[] kernel = new double[radius * 2 + 1];
double twoRadiusSquaredRecip = 1.0 / (2.0 * radius * radius);
double sqrtTwoPiTimesRadiusRecip = 1.0 / (sqrt(2.0 * Math.PI) * radius);
double radiusModifier = 1.0;

int r = -radius;
for (int i = 0; i < kernel.Length; i++)
{
    double x = r * radiusModifier;
    x *= x;
    kernel[i] =
    sqrtTwoPiTimesRadiusRecip * Exp(-x * sqrtTwoPiTimesRadiusRecip);
    r++;
}

double div = Sum(kernel);
for (int i = 0; i < kernel.Length; i++)
{
    kernel[i] /= div;
}

Надеюсь, это поможет.

Ответ 3

Чтобы использовать ядро ​​фильтра, обсуждаемое в статье в Википедии, вам нужно реализовать (дискретно) convolution. Идея состоит в том, что у вас небольшая матрица значений (ядро), вы перемещаете это ядро ​​от пикселя к пикселю в изображении (т.е. Чтобы центр матрицы находился на пикселе), умножайте матричные элементы с перекрывающимся изображением элементы, суммируют все значения в результате и заменяют значение старого пикселя этой суммой.

Гауссовское размытие можно разделить на две одномерные свертки (одну вертикальную и одну горизонтальную) вместо двумерной свертки, что также немного ускоряет работу.

Ответ 4

Я не знаю, хотите ли вы ограничить это некоторыми технологиями, но если SVG (ScalableVectorGraphics) имеет реализацию Gaussian Blur, Я считаю, что это относится ко всем примитивам, включая пиксели. Преимущество SVG заключается в том, что он является стандартом Open и широко применяется.

Ответ 5

Ну, гауссовское ядро ​​является сепарабельным ядром.
Следовательно, все, что вам нужно, это функция, которая поддерживает разделяемую 2D-свертку подобно - ImageConvolutionSeparableKernel().

Как только у вас есть это, все необходимое - это обертка для создания 1D гауссовского ядра и отправьте его функции, как это сделано в ImageConvolutionGaussianKernel().

Код представляет собой прямолинейную реализацию C сглаживания 2D-изображений, ускоренную с помощью SIMD (SSE) и многопоточности (OpenMP).

Весь проект задается как Image Convolution - GitHub.