Фильтрация изображений
Введение
Пакет ImageFilters.jl предоставляет инструменты для применения преобразований к массивам с упором на операции, применяемые при обработке изображений, такие как размытие, увеличение резкости и усиление контуров.
Термин фильтрация используется в контексте преобразования Фурье для изображения, при котором каноническая пространственная область изображения сопоставляется с его сопутствующей частотной областью. Операции с изображением в частотной области сводятся к сохранению или исключению определенных частотных составляющих — процессу, аналогичному отсеиванию или фильтрации [1]. Так как при преобразовании Фурье устанавливается связь между пространственным и частотным представлениями изображения, различные операции с изображением в пространственной области можно представить как операции фильтрации, принимающие или отклоняющие определенные частоты.
Часто используемое словосочетание пространственная фильтрация подчеркивает, что операция, по крайней мере теоретически, предназначена для выполнения в пространственной области изображения. Далее можно провести различие между линейной и нелинейной пространственной фильтрацией. Фильтр называется линейным, если выполняемая на пикселях операция линейная; в противном случае он называется нелинейным.
Параметры функции
Функция imfilter()
фильтрует одно-, двух- или многомерный массив img
с ядром kernel
, вычисляя их корреляцию.
Синтаксис imfilter()
выглядит так:
imfilter([T], img, kernel, [border="replicate"], [alg])
imfilter([r], img, kernel, [border="replicate"], [alg])
imfilter(r, T, img, kernel, [border="replicate"], [alg])
В следующих подразделах подробно описываются допустимые значения аргументов функции.
Варианты для r
При необходимости можно производить диспетчеризацию в различные реализации, передавая ресурс r
согласно определению в пакете ComputationalResources.
Пример:
imfilter(ArrayFireLibs(), img, kernel)
Этот вызов запрашивает выполнение вычислений на GPU с использованием библиотек ArrayFire.
Варианты для T
При необходимости можно контролировать тип элементов выходного изображения, передавая тип T
первым аргументом.
Варианты для kernel
Параметр kernel[0, 0,..]
соответствует началу (нулевому смещению) ядра. С помощью centered
можно установить начало в центре массива. Можно также воспользоваться пакетом OffsetArrays для задания индексов kernel
вручную. Например, отфильтровать случайное отцентрированное ядро размером 3x3 можно одним из следующих способов.
kernel = centered(rand(3,3))
kernel = OffsetArray(rand(3,3), -1:1, -1:1)
Параметр kernel
можно задать в виде массива или «разложенного ядра», то есть кортежа (filt1, filt2, ...)
фильтров, которые будут применены по каждой оси изображения. Если известно, что ядро является разделяющимся, такой формат может ускорить обработку. Каждый фильтр должен быть той же размерности, что и само изображение, и иметь форму, указывающую на ось фильтрации, например фильтр 3x1 для фильтрации первого измерения или фильтр 1x3 для фильтрации второго измерения. В случае с двумя измерениями любое ядро, передаваемое в виде одиночной матрицы, проверяется на разделяемость; чтобы эта проверка не проводилась, передайте ядро в виде одноэлементного кортежа: (kernel,)
.
Варианты для border
С помощью аргумента border
указывается способ дополнения для экстраполяции изображения за пределами его исходных границ.
Для иллюстрации результаты дополнения с использованием каждого варианта показаны на примере изображения, состоящего из строки из шести пикселей, которые следуют по алфавиту:
┏━━━━━━┓
┃abcdef┃
┗━━━━━━┛
Результат дополнения демонстрируется только на левой и правой границах, но для верхней и нижней границ результат будет аналогичным.
"replicate"
(по умолчанию)
Пиксели границы продолжаются за границами изображения.
╭────┏━━━━━━┓────╮
│aaaa┃abcdef┃ffff│
╰────┗━━━━━━┛────╯
"circular"
Пиксели границы переносятся в противоположную сторону. Например, при обращении по индексам за пределами левой границы возвращаются значения начиная с правой границы.
╭────┏━━━━━━┓────╮
│cdef┃abcdef┃abcd│
╰────┗━━━━━━┛────╯
"reflect"
Пиксели границы отражаются относительно позиции между пикселями. Пиксель границы при этом опускается.
╭────┏━━━━━━┓────╮
│dcba┃abcdef┃fedc│
╰────┗━━━━━━┛────╯
"symmetric"
Пиксели границы отражаются относительно края изображения.
╭────┏━━━━━━┓────╮
│edcb┃abcdef┃edcb│
╰────┗━━━━━━┛────╯
Fill(m)
Пиксели границы заполняются указанным значением .
╭────┏━━━━━━┓────╮
│mmmm┃abcdef┃mmmm│
╰────┗━━━━━━┛────╯
Inner()
Указывает, что края при фильтрации должны отбрасываться: возвращается только внутренняя часть результата.
NA()
Выбор фильтрации с использованием граничных условий NA (недоступно). Лучше всего подходит для фильтров только с положительными весами, сумма которых равна 1, например фильтров размытия: вместо «придумывания» значений за границами результат нормализуется по определенному числу пикселей внутри границ (аналогично nanmean
).
Пример:
julia> img = [0, 0, 1, 0, 0, 0, 1];
julia> imfilter(img, centered([1, 1, 1]/3), NA())
7-element Vector{Float64}:
0.0
0.3333333333333333
0.3333333333333333
0.3333333333333333
0.0
0.3333333333333333
0.5
Варианты для alg
Параметр alg
позволяет выбрать алгоритм: Algorithm.FIR()
(конечная импульсная характеристика, то есть традиционная цифровая фильтрация) или Algorithm.FFT()
(фильтрация методом Фурье). Если алгоритм не указан, он выбирается с учетом размера изображения и ядра так, чтобы обеспечивалась высокая производительность. Помимо этого, можно использовать фильтр пользовательского типа, например KernelFactors.IIRGaussian
.
Свертка и корреляция
По умолчанию imfilter
выполняет корреляцию.
В следующем примере рассмотрим матрицу изображения f
и маску коэффициентов отцентрированного фильтра w
.
Согласно спецификации Fill(0, w)
граница f
должна дополняться нулями. Степень дополнения определяется автоматически с учетом длины w
.
# Создаем двухмерную дискретную функцию единичного импульса.
f = fill(0, (9, 9));
f[5, 5] = 1
# Указываем маску коэффициентов фильтра и задаем в качестве начала центр маски.
w = centered([1 2 3; 4 5 6 ; 7 8 9]);
Путем отражения w
вычисляется свертка f
и w
. Сравнение корреляции и свертки:
correlation = imfilter(f, w, Fill(0, w))
convolution = imfilter(f, reflect(w), Fill(0, w))
Различные варианты дополнения границ
Используя следующие значения для примера:
f = reshape(1.0:81.0, 9, 9)
w = centered(reshape(1.0:9.0, 3, 3))
можно задать тип дополнения, передав соответствующую строку:
imfilter(f, w, "replicate")
imfilter(f, w, "circular")
imfilter(f, w, "symmetric")
imfilter(f, w, "reflect")
С помощью типа Pad
можно также явным образом задать стиль дополнения:
imfilter(f, w, Pad(:replicate))
imfilter(f, w, Pad(:circular))
imfilter(f, w, Pad(:symmetric))
imfilter(f, w, Pad(:reflect))
Для дополнения указанным значением используйте тип Fill
.
imfilter(f, w, Fill(0, w))
imfilter(f, w, Fill(1, w))
imfilter(f, w, Fill(-1, w))
Укажите Inner()
, если нужно получить внутренний подмассив f, для которого операция фильтрации определена без дополнения:
imfilter(f, w, Inner())
Функция imfilter!
Функция imfilter!()
фильтрует массив img
с ядром kernel
, вычисляя их корреляцию, и сохраняет результат в imgfilt
.
imfilter!(imgfilt, img, kernel, [border="replicate"], [alg])
imfilter!(r, imgfilt, img, kernel, border::Pad)
imfilter!(r, imgfilt, img, kernel, border::NoPad, [inds=axes(imgfilt)])
Индексы imgfilt
определяют область, в которой вычисляется отфильтрованное изображение. Это позволяет выбрать определенную область интереса, однако имейте в виду, что входной массив img
все равно может дополняться.
Можно также явным образом задать индексы inds
объекта imgfilt
, которые нужно вычислить, и использовать граничные условия NoPad
. В этом случае вы отвечаете за правильную настройку дополнения: массив img
должен быть индексируемым во всех позициях, которые требуются для вычисления результата. Этот синтаксис лучше всего поддерживается при использовании КИХ-фильтрации, в частности, БИХ-фильтрация может давать несогласованные результаты при применении ко всему массиву.