Как осуществляется Gaussian Blur?

42

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

В прошлом я немного свернул в 1D, но мне это не очень удобно, и я не знаю, что именно нужно свернуть в этом случае.

Может кто-нибудь объяснить в понятных терминах, как делается 2D гауссово размытие изображения?

Я также слышал, что радиус Blur может повлиять на производительность. Это из-за необходимости делать большую свертку?

Алан Вульф
источник

Ответы:

48

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

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

Изображение связано с http://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm

Каждый пиксель в изображении умножается на ядро ​​Гаусса. Это делается путем размещения центрального пикселя ядра на пикселе изображения и умножения значений в исходном изображении на пиксели в ядре, которые перекрываются. Значения, полученные в результате этих умножений, суммируются, и этот результат используется для значения в целевом пикселе. Глядя на изображение, вы бы умножили значение в (0,0) во входном массиве на значение в (i) в массиве ядра, значение в (1,0) во входном массиве на значение в (ч). ) в массиве ядра и так далее. и затем добавьте все эти значения, чтобы получить значение для (1,1) на выходном изображении.

Изображение связано с http://www.songho.ca/dsp/convolution/convolution.html

Чтобы ответить на ваш второй вопрос первым, чем больше ядро, тем дороже операция. Таким образом, чем больше радиус размытия, тем больше времени займет операция.

Чтобы ответить на ваш первый вопрос, как объяснялось выше, свертка может быть сделана путем умножения каждого входного пикселя на все ядро. Однако, если ядро ​​симметрично (то есть ядро ​​Гаусса), вы также можете умножить каждую ось (x и y) независимо, что уменьшит общее количество умножений. В правильных математических терминах, если матрица отделима, она может быть разложена на (M × 1) и (1 × N) матрицы. Для ядра Gaussian выше это означает, что вы также можете использовать следующие ядра:

1256[1464141624164624362464162416414641]знак равно1256[14641][14641]

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

Для получения дополнительной информации о том, как увидеть, является ли ядро ​​отделимым, перейдите по этой ссылке .

Изменить: два ядра, показанные выше, используют немного разные значения. Это связано с тем, что параметр (сигма), используемый для кривой Гаусса для создания этих ядер, немного отличался в обоих случаях. Для объяснения того, какие параметры влияют на форму кривой Гаусса и, следовательно, значения в ядре, перейдите по этой ссылке

Редактировать: на втором изображении выше написано, что используемое ядро ​​перевернуто. Это, конечно, имеет значение, только если ядро, которое вы используете, не симметрично. Причина, по которой вам нужно перевернуть ядро, связана с математическими свойствами операции свертки (см. Ссылку для более подробного объяснения свертки). Проще говоря: если вы не перевернете ядро, результат операции свертки будет перевернут. Перевернув ядро, вы получите правильный результат.

Берт
источник
1
Не могли бы вы добавить краткое примечание, чтобы объяснить, почему два разных ядра 5 на 5 имеют немного разные числа (одно суммирование до 273, другое суммирование до 256)? Это выглядит как потенциальная путаница для кого-то нового в этом.
Трихоплакс
Точно так же, не могли бы вы объяснить, почему ядро ​​перевернуто на второй диаграмме? Я не думаю, что это имеет отношение к объяснению, но тот факт, что это очевидный дополнительный шаг, может помешать пониманию того, кто не знает, что в этом нет необходимости.
Трихоплакс
не забывайте работать в линейном цветовом пространстве для правильных результатов.
v.oddou
16

Вот лучшая статья, которую я прочитал на эту тему: Эффективное размытие по Гауссу с линейной выборкой . Он отвечает на все ваши вопросы и действительно доступен.

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

N×NО(N2)2×NО(N)

NN

Жюльен Геро
источник
13

В общем, свертка выполняется путем взятия интеграла от произведения двух функций в скользящем окне, но если вы не из математического фона, это не очень полезное объяснение и, конечно, не даст вам полезной интуиции для этого. Интуитивно понятнее, свертка позволяет нескольким точкам входного сигнала воздействовать на одну точку выходного сигнала.

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

В нашем дискретном контексте мы можем умножить наши два сигнала, просто умножив каждую соответствующую выборку. Интеграл также просто сделать дискретно, мы просто складываем каждую выборку в интервале, который мы интегрируем. Одна простая дискретная свертка - это вычисление скользящего среднего. Если вы хотите взять скользящее среднее из 10 выборок, это можно рассматривать как свертывание вашего сигнала распределением длиной 10 выборок и высотой 0,1, каждая выборка в окне сначала умножается на 0,1, а затем все 10 складываются вместе для получения среднее. Это также выявляет интересное и важное различие: когда вы размываете с помощью свертки, используемое распределение должно составлять 1,0 для всех его выборок, в противном случае оно увеличит или уменьшит общую яркость изображения при его применении.

Теперь, когда мы посмотрели на свертки, мы можем перейти к размытиям. Гауссово размытие реализуется путем свертки изображения по гауссовскому распределению. Другие размытия, как правило, реализуются путем свертывания изображения другими дистрибутивами. Самым простым размытием является размытие окна, и оно использует то же распределение, которое мы описали выше, это поле с единичной площадью. Если мы хотим размывать область 10x10, то мы умножаем каждый образец в блоке на 0,01, а затем суммируем их все вместе, чтобы получить центральный пиксель. Нам все еще нужно убедиться, что общая сумма всех выборок в нашем распределении размытия равна 1,0, чтобы изображение не становилось все ярче или темнее.

r

е-Икс2/22π

О(N2)О(N),

porglezomp
источник
1
Глядя на ваш другой ответ, кажется, что ваш математический фон лучше, чем я работал, но я надеюсь, что он все еще достаточно подробен, чтобы быть полезным. Я хотел, чтобы это было полезно для людей любого происхождения, вступающих в это.
porglezomp
1
Если вы говорите со мной, совсем нет. Ваш ответ и ответы Берта удивительно поучительны. Спасибо большое! Должен немного переварить информацию (:
Алан Вулф
11

О(N2)О(N)

Но есть еще две хитрости, которые вы можете рассмотреть в реальной реализации:

Фильтр имеет определенный радиус, и поэтому на самых границах вам нужно будет рассчитывать пиксели, которые выходят за пределы изображения. В таком случае вы можете попробовать одно из следующего: для внешних пикселей вы просто берете последнее возможное значение (то есть пиксель на самой границе, как в max(x, 0). Или вы можете «отразить» изображение наружу (как в x < 0 ? -x : x). Или вы можете просто остановиться на границе, но тогда вам нужно будет настроить знаменатель в свёрточном фильтре так, чтобы он суммировал до 1. Например:

сумма1256[1464141624164624362464162416414641]знак равносумма1225[0000001624160024361600162416000000]знак равно1.
     1
    1 1
   1 2 1
  1 3 3 1
[1 4 6 4 1]
Ecir Hana
источник