Хабрахабр

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

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

Введение

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

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

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

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

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

52 \times 10^{-8} & 2. $\left( \begin{array}{ccccccc} 1. 0000454 & 0. 26 \times 10^{-6} & 0. 0000454 & 2. 000123 & 0. 52 \times 10^{-8} \\ 2. 26 \times 10^{-6} & 1. 000335 & 0. 26 \times 10^{-6} & 0. 0183 & 0. 00674 & 0. 000335 &2. 00674 & 0. 0000454 & 0. 26 \times 10^{-6} \\ 0. 135 & 0. 00674 & 0. 135 & 0. 368 & 0. 0000454 \\ 0. 00674 & 0. 0183 & 0. 000123 & 0. 00 & 0. 368 & 1. 0183 & 0. 368 & 0. 0000454 & 0. 000123 \\ 0. 135 & 0. 00674 & 0. 135 & 0. 368 & 0. 0000454 \\ 2. 00674 & 0. 000335 & 0. 26 \times 10^{-6} & 0. 0183 & 0. 00674 & 0. 000335 &2. 00674 & 0. 52 \times 10^{-8} & 2. 26 \times 10^{-6} \\ 1. 0000454 & 0. 26 \times 10^{-6} & 0. 0000454 & 2. 000123 & 0. 52 \times 10^{-8} \\ \end{array} \right) $ 26 \times 10^{-6} & 1.

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

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

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

Для удобства часто используют нормализацию и по координатам, посредством введения дополнительного параметра $\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.$

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

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

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

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

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

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

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

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

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

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

$\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$ определяет характер затухания:

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

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

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

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

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

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

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

5$" data-tex="display"/> <img src="https://habrastorage.org/getpro/habr/formulas/3c3/7d2/ce2/3c37d2ce27137307ea5e5e32015abebb.svg" alt="$n=0.

$n=2$

$n=10$

$n=50$

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

$\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$ получим

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

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

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

$\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}$ приходиться на центр функции.

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

$k=5$

$k=2$

5$" data-tex="display"/> <img src="https://habrastorage.org/getpro/habr/formulas/e33/638/908/e3363890807177c66e64c8bf4c74fc68.svg" alt="$k=0.

1$" data-tex="display"/> <img src="https://habrastorage.org/getpro/habr/formulas/204/698/0ad/2046980ad9cdcf29566ed0193dd58e8c.svg" alt="$k=0.

01$" data-tex="display"/> <img src="https://habrastorage.org/getpro/habr/formulas/67c/488/f42/67c488f42f888831ac7261eb4e564775.svg" alt="$k=0.

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

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

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

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

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

$ 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) $

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

$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| ) $

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

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

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

Гауссиана

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

Крест

Кольцо

Одностороннее затухание

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






Заключение

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

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

В качестве функции затухания также могут быть использованы оконные функции, рассмотренные здесь — нужно лишь масштабировать аргумент 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 для этой статьи можно скачать здесь.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть