stringtranslate.com

Ядро (обработка изображений)

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

Подробности

Общее выражение свертки:

где – отфильтрованное изображение, – исходное изображение, – ядро ​​фильтра. Каждый элемент ядра фильтра рассматривается с помощью и .

В зависимости от значений элементов ядро ​​может вызывать широкий спектр эффектов:

Вышеупомянутое — лишь несколько примеров эффектов, достижимых с помощью свертки ядер и изображений.

Источник

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

Свертка

2D-анимация свертки

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

Например, если у нас есть две матрицы размером три на три, первая — ядро, а вторая — часть изображения, свертка — это процесс переворачивания строк и столбцов ядра, а также умножения локально подобных записей и суммирования. Элемент с координатами [2, 2] (то есть центральный элемент) результирующего изображения будет представлять собой взвешенную комбинацию всех элементов матрицы изображения с весами, заданными ядром:

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

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

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

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

Если ядро ​​несимметрично, его необходимо перевернуть вокруг горизонтальной и вертикальной оси, прежде чем вычислять свертку, как указано выше. [1]

Общая форма свертки матрицы:

Обработка кромок

Расширение обработки краев

Свертка ядра обычно требует значений из пикселей за пределами границ изображения. Существует множество методов обработки краев изображения.

Продлевать
Ближайшие граничные пиксели концептуально расширяются настолько, насколько это необходимо для предоставления значений для свертки. Угловые пиксели расширены клиньями под углом 90°. Остальные краевые пиксели вытянуты в виде линий.
Сворачивать
Изображение концептуально оборачивается (или размещается в виде плитки), а значения берутся с противоположного края или угла.
Зеркало
Изображение концептуально зеркально отражено по краям. Например, попытка прочитать пиксел на 3 единицы за пределами края вместо этого считывает одну 3 единицы внутри края.
Обрезать/избегать перекрытия
Любой пиксель выходного изображения, для которого потребуются значения за пределами края, пропускается. Этот метод может привести к тому, что выходное изображение будет немного меньше, а края будут обрезаны. Переместите ядро ​​так, чтобы значения извне изображения никогда не требовались. Машинное обучение в основном использует этот подход. Пример: размер ядра 10x10, размер изображения 32x32, результирующее изображение 23x23.
Обрезка ядра
Любой пиксель в ядре, выходящий за пределы входного изображения, не используется, и нормализация корректируется для компенсации.
Постоянный
Используйте постоянное значение для пикселей за пределами изображения. Обычно используется черный или иногда серый цвет. Обычно это зависит от приложения.

Нормализация

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

Оптимизация

Алгоритмы быстрой свертки включают в себя:

Сепарабельная свертка

2D-свертка с ядром M × N требует умножения M × N для каждого образца (пикселя). Если ядро ​​сепарабельное, то вычисления можно свести к умножениям M + N . Использование разделимых сверток может значительно уменьшить объем вычислений, выполняя 1D-свертку дважды вместо одной 2D-свертки. [2]

Выполнение

Вот конкретная реализация свертки, выполненная с помощью языка шейдеров GLSL :

// автор: csblo // Работа, сделанная только путем консультации: // https://en.wikipedia.org/wiki/Kernel_(image_processing)/Kernel_(image_processing)// Определить ядра #define идентификатор mat3(0, 0, 0, 0, 1, 0, 0, 0, 0) #define Edge0 mat3(1, 0, -1, 0, 0, 0, -1, 0, 1) #define Edge1 mat3(0, 1, 0, 1, -4, 1, 0, 1, 0) #define Edge2 mat3(-1, -1, -1, -1, 8, -1, -1 , -1, -1) #define Sharpen mat3(0, -1, 0, -1, 5, -1, 0, -1, 0) #define box_blur mat3(1, 1, 1, 1, 1, 1 , 1, 1, 1) * 0,1111 #define gaussian_blur mat3(1, 2, 1, 2, 4, 2, 1, 2, 1) * 0,0625 #define emboss mat3(-2, -1, 0, -1, 1, 1, 0, 1, 2)// Находим координату элемента матрицы по индексу vec2 kpos ( int index ) { return vec2 [ 9 ] ( vec2 ( - 1 , - 1 ), vec2 ( 0 , - 1 ), vec2 ( 1 , - 1 ), vec2 ( - 1 , 0 ), vec2 ( 0 , 0 ), vec2 ( 1 , 0 ), vec2 ( - 1 , 1 ), vec2 ( 0 , 1 ), vec2 ( 1 , 1 ) )[ index ] / iResolution . ху ; }                           // Извлечение области размером 3x3 из сэмплера с центром в uv // сэмплер: сэмплер текстуры // uv: текущие координаты сэмплера // возврат: массив mat3, каждый индекс которого соответствует цветовому каналу mat3 [ 3 ] Region3x3 ( sampler2D сэмплер , vec2 uv ) { // Создаём каждый пиксел для региона vec4 [ 9 ] Region ; for ( int i = 0 ; i < 9 ; i ++ ) регион [ i ] = текстура ( сэмплер , uv + kpos ( i ));                        // Создаем регион 3x3 с 3 цветовыми каналами (красный, зеленый, синий) mat3 [ 3 ] mRegion ; for ( int i = 0 ; i < 3 ; i ++ ) mRegion [ i ] = mat3 ( регион [ 0 ] [ i ], регион [ 1 ] [ i ], регион [ 2 ] [ i ], регион [ 3 ] [ i ], регион [ 4 ][ i ], регион [ 5 ][ i ], регион [ 6 ][ i ], регион [ 7 ][ i ], регион [ 8 ][ i ] ); вернуть мрегион ; }                            // Свертка текстуры с помощью ядра // ядро: ядро, используемое для свертки // сэмплер: сэмплер текстуры // uv: текущие координаты сэмплера свертка vec3 ( ядро mat3 , sampler2D sampler , vec2 uv ) { vec3 фрагмент ; // Извлекаем область 3x3 с центром в uv mat3 [ 3 ] Region = Region3x3 ( sampler , uv ); // для каждого цветового канала региона for ( int i = 0 ; i < 3 ; i ++ ) { // получаем канал региона mat3 rc = регион [ i ]; // покомпонентное умножение ядра на область канала mat3 c = matrixCompMult ( kernel , rc ); // добавляем каждый компонент матрицы float r = c [ 0 ][ 0 ] + c [ 1 ][ 0 ] + c [ 2 ][ 0 ] + c [ 0 ][ 1 ] + c [ 1 ][ 1 ] + c [ 2 ][ 1 ] + c [ 0 ][ 2 ] + c [ 1 ][ 2 ] + c [ 2 ][ 2 ]; // для фрагмента на канале i устанавливаем фрагмент результата [ i ] = r ; } вернуть фрагмент ; }                                                                     void mainImage ( out vec4 fragColor , in vec2 fragCoord ) { // Нормализованные координаты пикселей (от 0 до 1) vec2 uv = fragCoord / iResolution . ху ; // Свертка ядра с текстурой vec3 col = convolution ( emboss , iChannel0 , uv ); // Вывод на экран fragColor = vec4 ( col , 1.0 ); }                          

Смотрите также

Рекомендации

  1. ^ «Пример 2D-свертки» .
  2. ^ «Свертка». www.songho.ca . Проверено 19 ноября 2022 г.

Источники

Внешние ссылки