В свертке две математические функции объединяются для получения третьей функции. При обработке изображений функции обычно называются ядрами. Ядро - это не что иное, как квадратный массив пикселей (так сказать, маленькое изображение). Обычно значения в ядре складываются в единицу. Это делается для того, чтобы убедиться, что энергия не добавляется и не удаляется с изображения после операции.
В частности, ядро Гаусса (используется для размытия по Гауссу) представляет собой квадратный массив пикселей, где значения пикселей соответствуют значениям кривой Гаусса (в 2D).
Каждый пиксель в изображении умножается на ядро Гаусса. Это делается путем размещения центрального пикселя ядра на пикселе изображения и умножения значений в исходном изображении на пиксели в ядре, которые перекрываются. Значения, полученные в результате этих умножений, суммируются, и этот результат используется для значения в целевом пикселе. Глядя на изображение, вы бы умножили значение в (0,0) во входном массиве на значение в (i) в массиве ядра, значение в (1,0) во входном массиве на значение в (ч). ) в массиве ядра и так далее. и затем добавьте все эти значения, чтобы получить значение для (1,1) на выходном изображении.
Чтобы ответить на ваш второй вопрос первым, чем больше ядро, тем дороже операция. Таким образом, чем больше радиус размытия, тем больше времени займет операция.
Чтобы ответить на ваш первый вопрос, как объяснялось выше, свертка может быть сделана путем умножения каждого входного пикселя на все ядро. Однако, если ядро симметрично (то есть ядро Гаусса), вы также можете умножить каждую ось (x и y) независимо, что уменьшит общее количество умножений. В правильных математических терминах, если матрица отделима, она может быть разложена на (M × 1) и (1 × N) матрицы. Для ядра Gaussian выше это означает, что вы также можете использовать следующие ядра:
1256⋅ ⎡⎣⎢⎢⎢⎢⎢⎢1464141624164624362464162416414641⎤⎦⎥⎥⎥⎥⎥⎥= 1256⋅ ⎡⎣⎢⎢⎢⎢⎢⎢14641⎤⎦⎥⎥⎥⎥⎥⎥⋅ [ 14641]
Теперь вы должны умножить каждый пиксель во входном изображении на оба ядра и добавить результирующие значения, чтобы получить значение для выходного пикселя.
Для получения дополнительной информации о том, как увидеть, является ли ядро отделимым, перейдите по этой ссылке .
Изменить: два ядра, показанные выше, используют немного разные значения. Это связано с тем, что параметр (сигма), используемый для кривой Гаусса для создания этих ядер, немного отличался в обоих случаях. Для объяснения того, какие параметры влияют на форму кривой Гаусса и, следовательно, значения в ядре, перейдите по этой ссылке
Редактировать: на втором изображении выше написано, что используемое ядро перевернуто. Это, конечно, имеет значение, только если ядро, которое вы используете, не симметрично. Причина, по которой вам нужно перевернуть ядро, связана с математическими свойствами операции свертки (см. Ссылку для более подробного объяснения свертки). Проще говоря: если вы не перевернете ядро, результат операции свертки будет перевернут. Перевернув ядро, вы получите правильный результат.
Вот лучшая статья, которую я прочитал на эту тему: Эффективное размытие по Гауссу с линейной выборкой . Он отвечает на все ваши вопросы и действительно доступен.
Для непрофессионала очень короткое объяснение: гауссовская функция с хорошим свойством отделимости, что означает, что двумерная гауссовская функция может быть вычислена путем объединения двух одномерных гауссовских функций.
источник
В общем, свертка выполняется путем взятия интеграла от произведения двух функций в скользящем окне, но если вы не из математического фона, это не очень полезное объяснение и, конечно, не даст вам полезной интуиции для этого. Интуитивно понятнее, свертка позволяет нескольким точкам входного сигнала воздействовать на одну точку выходного сигнала.
Поскольку вам не очень комфортно с извилинами, давайте сначала рассмотрим, что означает свертка в дискретном контексте, подобном этому, а затем рассмотрим более простое размытие.
В нашем дискретном контексте мы можем умножить наши два сигнала, просто умножив каждую соответствующую выборку. Интеграл также просто сделать дискретно, мы просто складываем каждую выборку в интервале, который мы интегрируем. Одна простая дискретная свертка - это вычисление скользящего среднего. Если вы хотите взять скользящее среднее из 10 выборок, это можно рассматривать как свертывание вашего сигнала распределением длиной 10 выборок и высотой 0,1, каждая выборка в окне сначала умножается на 0,1, а затем все 10 складываются вместе для получения среднее. Это также выявляет интересное и важное различие: когда вы размываете с помощью свертки, используемое распределение должно составлять 1,0 для всех его выборок, в противном случае оно увеличит или уменьшит общую яркость изображения при его применении.
Теперь, когда мы посмотрели на свертки, мы можем перейти к размытиям. Гауссово размытие реализуется путем свертки изображения по гауссовскому распределению. Другие размытия, как правило, реализуются путем свертывания изображения другими дистрибутивами. Самым простым размытием является размытие окна, и оно использует то же распределение, которое мы описали выше, это поле с единичной площадью. Если мы хотим размывать область 10x10, то мы умножаем каждый образец в блоке на 0,01, а затем суммируем их все вместе, чтобы получить центральный пиксель. Нам все еще нужно убедиться, что общая сумма всех выборок в нашем распределении размытия равна 1,0, чтобы изображение не становилось все ярче или темнее.
r
источник
Но есть еще две хитрости, которые вы можете рассмотреть в реальной реализации:
Фильтр имеет определенный радиус, и поэтому на самых границах вам нужно будет рассчитывать пиксели, которые выходят за пределы изображения. В таком случае вы можете попробовать одно из следующего: для внешних пикселей вы просто берете последнее возможное значение (то есть пиксель на самой границе, как в
max(x, 0)
. Или вы можете «отразить» изображение наружу (как вx < 0 ? -x : x
). Или вы можете просто остановиться на границе, но тогда вам нужно будет настроить знаменатель в свёрточном фильтре так, чтобы он суммировал до 1. Например:источник