Нужно больше разных Blur-ов

Размытие изображение посредством фильтра Gaussian Blur широко используется в самых разных задачах. Но иногда хочется чуть большего разнообразия, чем просто один фильтр на все случаи жизни, в котором регулировке поддаётся только один параметр — его размер. В этой статье мы рассмотрим несколько других реализаций размытия.

5wlqe3ngeymx8b2mrqnh4ffa_ok.gif


Введение


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

Фильтр называется Gaussian, потому что он строится из функции, известной как гауссиана, $e^{-x^2}$:

d2epp2qrg8b5wgi2cxdr_mgh07q.gif

двумерный вариант которой получен её вращением относительно оси ординат, $e^{-(x^2+y^2)}$:

ni5rja7lfcvmnjbmx2_pew6e9wc.gif

Здесь для каждой пары координат $(x,y)$ рассчитывается расстояние до центра по формуле $\sqrt{x^2+y^2}$, которое передаётся как аргумент в функцию гауссианы.

Матрица, построенная на отрезке $[-3,3]$ и с некоторым уровнем дискретизации, будет выглядеть так:

$\left( \begin{array}{ccccccc} 1.52 \times 10^{-8} & 2.26 \times 10^{-6} & 0.0000454 & 0.000123 & 0.0000454 & 2.26 \times 10^{-6} & 1.52 \times 10^{-8} \\ 2.26 \times 10^{-6} & 0.000335 & 0.00674 & 0.0183 & 0.00674 & 0.000335 &2.26 \times 10^{-6} \\ 0.0000454 & 0.00674 & 0.135 & 0.368 & 0.135 & 0.00674 & 0.0000454 \\ 0.000123 & 0.0183 & 0.368 & 1.00 & 0.368 & 0.0183 & 0.000123 \\ 0.0000454 & 0.00674 & 0.135 & 0.368 & 0.135 & 0.00674 & 0.0000454 \\ 2.26 \times 10^{-6} & 0.000335 & 0.00674 & 0.0183 & 0.00674 & 0.000335 &2.26 \times 10^{-6} \\ 1.52 \times 10^{-8} & 2.26 \times 10^{-6} & 0.0000454 & 0.000123 & 0.0000454 & 2.26 \times 10^{-6} & 1.52 \times 10^{-8} \\ \end{array} \right) $


Или, если рассматривать значения элементов матрицы как уровень яркости, так:

8mpoceobohykhn1hecizu2sp8iu.gif

что в терминах обработки сигналов называется импульсной характеристикой, поскольку именно так будет выглядеть результат свёртки данного фильтра с единичным импульсом (в данном случае — пикселем).

Изначально гауссиана определена на бесконечном интервале. Но за счёт того, что она довольно быстро затухает, можно исключить из вычислений значения, близкие к нулю — поскольку они всё равно не отразятся на результате. В реальных приложениях также необходима нормализация по значению, чтобы после свёртки яркость изображения не изменялась;, а в случае размытия изображения, в котором каждый пиксель имеет один и тот же цвет, не должно меняться и само изображение.

Для удобства часто используют нормализацию и по координатам, посредством введения дополнительного параметра $\sigma$ — чтобы рассматривать аргумент в диапазоне $[-1,1]$, а $\sigma$ определяет степень сжатия гауссианы:

$\frac{e^{-\frac{x^2+y^2}{2 \sigma ^2}}}{2 \pi \sigma ^2}$


Делитель $2 \pi \sigma ^2$ здесь получен через определённый интеграл на бесконечности:

$\int_{-\infty }^{\infty } \int_{-\infty }^{\infty } e^{-\frac{x^2+y^2}{2 \sigma ^2}} \, dx dy = 2 \pi \sigma ^2$


Начало


Для произвольного фильтра нам нужно сначала определить собственную функцию затухания от одной переменной $f$, из которой вращением получается функция от двух переменных путём замены $x$ на $\sqrt{x^2+y^2}$, где $x$ и $y$ это координаты элемента матрицы в диапазоне $(-1,1)$, и которая далее используется для заполнения элементов матрицы. Нормализацию будем считать не аналитически, а непосредственным суммированием всех элементов матрицы — это и проще, и точнее — поскольку после дискретизации функция получается «прореженной», и значение нормализации будет зависеть от уровня дискретизации.

В случае, если элементы матрицы нумеруются с нуля, координата $x$ или $y$ считается по формуле

$\frac{2 index}{size-1}-1$


где $index$ — порядковый номер элемента в строке или столбце, а $size$ — общее количество элементов.

Например, для матрицы 5 на 5 это будет выглядеть так:

$\left( \begin{array}{ccccc} f(-1,-1) & f\left(-\frac{1}{2},-1\right) & f(0,-1) & f\left(\frac{1}{2},-1\right) & f(1,-1) \\ f\left(-1,-\frac{1}{2}\right) & f\left(-\frac{1}{2},-\frac{1}{2}\right) & f\left(0,-\frac{1}{2}\right) & f\left(\frac{1}{2},-\frac{1}{2}\right) & f\left(1,-\frac{1}{2}\right) \\ f(-1,0) & f\left(-\frac{1}{2},0\right) & f(0,0) & f\left(\frac{1}{2},0\right) & f(1,0) \\ f\left(-1,\frac{1}{2}\right) & f\left(-\frac{1}{2},\frac{1}{2}\right) & f\left(0,\frac{1}{2}\right) & f\left(\frac{1}{2},\frac{1}{2}\right) & f\left(1,\frac{1}{2}\right) \\ f(-1,1) & f\left(-\frac{1}{2},1\right) & f(0,1) & f\left(\frac{1}{2},1\right) & f(1,1) \\ \end{array} \right)$


Или, если исключить граничные значения, которые всё равно равны нулю, то координаты будут считаться по формуле

$\frac{2 index-size+1}{size}$


а матрица соответственно примет вид

$\left( \begin{array}{ccccc} f\left(-\frac{4}{5},-\frac{4}{5}\right) & f\left(-\frac{2}{5},-\frac{4}{5}\right) & f\left(0,-\frac{4}{5}\right) & f\left(\frac{2}{5},-\frac{4}{5}\right) & f\left(\frac{4}{5},-\frac{4}{5}\right) \\ f\left(-\frac{4}{5},-\frac{2}{5}\right) & f\left(-\frac{2}{5},-\frac{2}{5}\right) & f\left(0,-\frac{2}{5}\right) & f\left(\frac{2}{5},-\frac{2}{5}\right) & f\left(\frac{4}{5},-\frac{2}{5}\right) \\ f\left(-\frac{4}{5},0\right) & f\left(-\frac{2}{5},0\right) & f(0,0) & f\left(\frac{2}{5},0\right) & f\left(\frac{4}{5},0\right) \\ f\left(-\frac{4}{5},\frac{2}{5}\right) & f\left(-\frac{2}{5},\frac{2}{5}\right) & f\left(0,\frac{2}{5}\right) & f\left(\frac{2}{5},\frac{2}{5}\right) & f\left(\frac{4}{5},\frac{2}{5}\right) \\ f\left(-\frac{4}{5},\frac{4}{5}\right) & f\left(-\frac{2}{5},\frac{4}{5}\right) & f\left(0,\frac{4}{5}\right) & f\left(\frac{2}{5},\frac{4}{5}\right) & f\left(\frac{4}{5},\frac{4}{5}\right) \\ \end{array} \right)$


После того, как элементы матрицы были рассчитаны по формуле, необходимо посчитать их сумму и поделить матрицу на неё. К примеру, если у нас получилась матрица

$\left( \begin{array}{ccc} 1 & 4 & 1 \\ 4 & 20 & 4 \\ 1 & 4 & 1 \\ \end{array} \right)$


то суммой всех её элементов будет 40, и после нормализации она примет вид

$\left( \begin{array}{ccc} \frac{1}{40} & \frac{1}{10} & \frac{1}{40} \\ \frac{1}{10} & \frac{1}{2} & \frac{1}{10} \\ \frac{1}{40} & \frac{1}{10} & \frac{1}{40} \\ \end{array} \right)$


и суммой всех её элементов станет 1.

Линейное затухание


Для начала возьмём самую простую функцию — линию:

$\left\{ \begin{array}{ll} 1-x, & x<1 \\ 0, & x \geqslant 1 \\ \end{array} \right.$


ma_xnh_mxskz877dlggf2vmbw1o.gif

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

njeuw4jrrzgfckmaymk3gu9zxve.gif

Мягкое линейное затухание


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

$1-\frac{n x-x^n}{n-1}$


в которой $n$ определяет «жёсткость» стыковки, $n>1$» />. Для, например, <img src= получим

$\left\{ \begin{array}{ll} 1-\frac{3 x-x^3}{2}, & x<1 \\ 0, & x \geqslant 1 \\ \end{array} \right.$


j8kjefoivwq3dqdcbhi5oyroqmi.gif

а сам фильтр будет выглядеть как

k_0tq3_scwq2ncbepjk06oc38_e.gif

Гиперболическое затухание


Фильтр можно сделать более «острым» и более плавно уходящим в ноль, взяв в качестве образующей другую функцию — например, гиперболу, а плавный переход к нулю обеспечив путём суммирования с параболой.

wgi4fd9vsmtne1855wrvx5oqqni.gif

После всех вычислений и упрощений получим формулу

$\left\{ \begin{array}{ll} \frac{(x-1)^2 (k x+k+1)}{(k+1) (k x+1)}, & x<1 \\ 0, & x \geqslant 1 \\ \end{array} \right.$


в которой параметр $k>0$» /> определяет характер затухания: </p>

<p><img src=

а сам фильтр будет выглядеть (для $k=5$) как

rl3yj3hwcpq6kbevqe5y8otlslm.gif

Имитация эффекта боке


Можно пойти и другим путём — делать вершину фильтра не острой, а тупой. Наиболее простой способ реализовать это — задать функцию затухания как константу:

$\left\{ \begin{array}{ll} 1, & x<1 \\ 0, & x \geqslant 1 \\ \end{array} \right.$


ebi6vqyp1qbdj6acd2d68000chu.gif

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

$\left\{ \begin{array}{ll} \left(1-x^n\right)^2, & x<1 \\ 0, & x \geqslant 1 \\ \end{array} \right.$


Варьируя параметр $n$, можно получить широкий спектр вариантов фильтра:

$n=0.5$

adofc9srztjsfq2sb1exnjchp3o.gif

$n=2$

d_rxzms6gfhibg46snlmtyfkn_g.gif

$n=10$

ktwpm3dnjhmogjilx3yzekuonii.gif

$n=50$

23tgykw0esj9lyxots_khsj4w1u.gif

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

$\left\{ \begin{array}{ll} \left(1-x^n\right)^2 \left(d+x^m\right), & x<1 \\ 0, & x \geqslant 1 \\ \end{array} \right.$


Здесь параметр $d$ определяет высоту центра, а $m$ — резкость перехода к краям.
Для $d=0.2, m=2, n=10$ получим

x2aqnu87hgsvvaplskygfwzifpg.gif

а для $d=0, m=12, n=2$

qqsgrkh99sal9locksgyqyjprk4.gif

Вариации гауссианы


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

$\left\{ \begin{array}{ll} e^{\frac{k x^2}{x^2-1}}, & -1<x<1 \\ 0, & otherwise \\ \end{array} \right.$


За счёт того, что при $x$ стремящемся к единице знаменатель $x^2-1$ стремится к нулю, дробь $\frac{k x^2}{(x^2-1)}$ стремится к минус бесконечности, а сама экспонента также стремится к нулю. Таким образом, деление на $x^2-1$ позволяет сжать область определения функции с $(-\infty, \infty)$ до $(-1,1)$. При этом, при $x=\pm 1$ за счёт деления на ноль ($0^2-1=0$) значение функции не определено, но имеет два предела — предел с одной стороны (изнутри) равен нулю, а с другой стороны — бесконечности:

$\underset{x\to 1^-}{\text{lim}}e^{\frac{k x^2}{x^2-1}}=0$

$\underset{x\to 1^+}{\text{lim}}e^{\frac{k x^2}{x^2-1}}=\infty$


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

Параметр $k$ определяет схожесть с гауссианой — чем он больше, тем сильнее получается схожесть — за счёт того, что всё более линейный участок $\frac{1}{x^2-1}$ приходиться на центр функции. Можно было бы предположить, что за счёт этого в пределе можно получить оригинальную гауссиану — но, к сожалению, нет — функции всё-таки разные.

9gvyecj7b7_8usa1ew35e5zkyte.gif

Теперь можно посмотреть, что получилось:

$k=5$

leozqg9zbie3esksialgaymu8qw.gif

$k=2$

xdngo2v5s9fj_ztvm8u43ktmf2c.gif

$k=0.5$

nwjcbdqfc7lztdm8gjjtb21uefq.gif

$k=0.1$

tnrpt4l5gtjnthinzorbhvjmnt0.gif

$k=0.01$

f8vbsvjxbwxynwbyjufrs0-zt-w.gif

Вариации формы


Изменив функцию перехода от двух координат к одной $\sqrt{x^2+y^2}$, можно получить и другие фигуры, а не только диск. Например:

$f\left(\frac{\left| x-y\right| +\left| x+y\right|}{2}\right)$


lzvrld6x6iwpskzhhu4nwoyl2je.gif

$f(\left| x\right| +\left| y\right| )$


pjckz6em98bj3yguwrj380o_jn4.gif

Перейдя на комплексные числа, можно конструировать и более сложные фигуры:

$ f\left( \frac{ \left| \Re\left((x+i y) (-1)^{\frac{0}{3}}\right)\right| + \left| \Re\left((x+i y) (-1)^{\frac{1}{3}}\right)\right| + \left| \Re\left((x+i y) (-1)^{\frac{2}{3}}\right)\right| }{\sqrt{3}} \right) $

q7zef0c0vmzgiferwhf3szf9isq.gif

$f\biggl(10\left| \Re\left((x+i y) (-1)^{\frac{1}{8}}\right)\right|\biggr) \cdot f(\left| x+i y\right|)$


bquajh90yke-jhrpmoc1aiuheug.gif

$f\biggl(\biggl| 5 \left| x+i y\right| (x+i y) \Re\biggl(\cos \left(\frac{5}{2} \arg (x+i y)\right)\biggr)\biggr| \biggr) \cdot f(\left| x+i y\right| ) $

otysm7rslxuhpsauwswllpobtfg.gif

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

Несколько конкретных примеров


Статья была бы не полной без практического испытания на конкретных изображениях. Поскольку у нас не научная работа, то и изображение Лены мы брать не будем —, а возьмём что-нибудь мягкое и пушистое:

xuwhstuforsprtraku9mdys-3rw.png

Гауссиана
s0jg6zesrdr2u_efarg2cnrkoe4.gif


s1ai8vajroo990hvknla8tggnnm.png

Гиперболическое затухание
v4eicvjvh2hf3kgsv6i9qy61ste.gif


p5ktfv3wveeb167libkbt462yqw.png

Крест
jd9dhniteivwdh9ng7hn2iwez9y.gif


4_lukngfogbrqqanubov7owlviq.png

Кольцо
t0d2oaowghu-nlo9vjuf-ywfi6i.gif


rghh_iw7von_bhvauyqynekty98.png

Одностороннее затухание
izeoyij8zz_war-k5ae2xh7qdvg.gif


g6y4hi99z_h-unixzazq8wyysj4.png

Те же фильтры, но для текста:

9z6wxifeinrhscysfnhaqo5-pui.gif
2br0vhba_haabbeqfzgu8cpbncq.gif
aa-hthfbpwttdmba8ch2-widfvo.gif
un_vocy34dwowzizxodxt9y4n8m.gif
7akbmg7bs9pde-ehkwjd6-ynqaw.gif
auxjidp-sjadbtwrxmbsmjcmia0.gif

Заключение


Аналогичным образом можно строить и более сложные фильтры, в том числе и с усилением резкости или выделением контуров;, а также модифицировать уже рассмотренные.

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

Более подробно вывод функций для стыковки с константой рассматривается здесь. В качестве функции затухания также могут быть использованы оконные функции, рассмотренные здесь — нужно лишь масштабировать аргумент c (0,1) на ($\frac{1}{2}$,1) или изначально считать оконные функции по формуле $\frac{1}{2} \left(f\left(\frac{t x+1}{t-1}\right)-f\left(\frac{t x-1}{t-1}\right)\right)$.

Исходный документ Wolfram Mathematica для этой статьи можно скачать здесь.

© Habrahabr.ru