Ядро (обработка изображений)
![]() | Эта статья включает список общих ссылок , но в ней отсутствуют достаточные соответствующие встроенные цитаты . ( Октябрь 2023 г. ) |
При обработке изображений ядро обнаружения , матрица свертки или маска — это небольшая матрица, используемая для размытия, повышения резкости, тиснения, краев и многого другого. Это достигается путем свертки между ядром и образом . Или, проще говоря, когда каждый пиксель выходного изображения является функцией соседних пикселей (включая самого себя) входного изображения, этой функцией является ядро.
Подробности
[ редактировать ]Общее выражение свертки:
где это отфильтрованное изображение, это исходное изображение, является ядром фильтра. Каждый элемент ядра фильтра рассматривается и .
В зависимости от значений элементов ядро может вызывать широкий спектр эффектов:
Операция | Ядро ω | Результат изображения g(x,y) |
---|---|---|
Личность | ![]() | |
Обнаружение гребня или края | ![]() | |
![]() | ||
Заточка | ![]() | |
Размытие коробки ( нормализованный ) |
![]() | |
Размытие по Гауссу 3 × 3 (приближение) |
![]() | |
Размытие по Гауссу 5 × 5 (приближение) |
![]() | |
Нерезкая маскировка 5 × 5 На основе размытия по Гауссу с суммой 1 и порог как 0 (без маски изображения ) |
|
![]() |
Вышеупомянутое — лишь несколько примеров эффектов, достижимых с помощью свертки ядер и изображений.
Источник
[ редактировать ]Начало координат — это положение ядра, которое находится над (концептуально) текущим выходным пикселем. Это может быть за пределами фактического ядра, хотя обычно оно соответствует одному из элементов ядра. Для симметричного ядра началом обычно является центральный элемент.
Свертка
[ редактировать ]
Свертка — это процесс добавления каждого элемента изображения к его локальным соседям, взвешенный ядром. Это связано с формой математической свертки . матричная операция Выполняемая — свертка — не является традиционным умножением матриц, несмотря на то, что она аналогично обозначается *.
Например, если у нас есть две матрицы размером три на три, первая — ядро, а вторая — часть изображения, свертка — это процесс переворачивания строк и столбцов ядра, а также умножения локально подобных записей и суммирования. Элемент с координатами [2, 2] (то есть центральный элемент) результирующего изображения будет представлять собой взвешенную комбинацию всех элементов матрицы изображения с весами, заданными ядром:
Остальные записи будут иметь такой же вес: мы располагаем центр ядра на каждой из граничных точек изображения и вычисляем взвешенную сумму.
Значения данного пикселя в выходном изображении вычисляются путем умножения каждого значения ядра на соответствующие значения пикселей входного изображения. Алгоритмически это можно описать с помощью следующего псевдокода:
for each image row in input image: for each pixel in image row: set accumulator to zero for each kernel row in kernel: for each element in kernel row: if element position corresponding* to pixel position then multiply element value corresponding* to pixel value add result to accumulator endif set output image pixel to accumulator
- *соответствующие пиксели входного изображения находятся относительно начала координат ядра.
Если ядро симметрично, поместите центр (начало координат) ядра в текущий пиксель. Ядро будет перекрывать соседние пиксели вокруг начала координат. Каждый элемент ядра следует умножить на значение пикселя, с которым он перекрывается, и все полученные значения суммировать. Эта результирующая сумма будет новым значением для текущего пикселя, который в данный момент перекрывается с центром ядра.
Если ядро несимметрично, его необходимо перевернуть вокруг горизонтальной и вертикальной оси, прежде чем рассчитывать свертку, как указано выше. [1]
Общая форма свертки матрицы:
Обработка кромок
[ редактировать ]
Свертка ядра обычно требует значений из пикселей за пределами границ изображения. Существует множество методов обработки краев изображения.
- Продлевать
- Ближайшие граничные пиксели концептуально расширяются настолько, насколько это необходимо для предоставления значений для свертки. Угловые пиксели расширены клиньями под углом 90°. Остальные краевые пиксели вытянуты в виде линий.
- Сворачивать
- Изображение концептуально оборачивается (или размещается в виде плитки), а значения берутся с противоположного края или угла.
- Зеркало
- Изображение концептуально зеркально отражено по краям. Например, попытка прочитать пиксел на 3 единицы за пределами края вместо этого считывает одну 3 единицы внутри края.
- Обрезать/избегать перекрытия
- Любой пиксель выходного изображения, для которого потребуются значения за пределами края, пропускается. Этот метод может привести к тому, что выходное изображение будет немного меньше, а края будут обрезаны. Переместите ядро так, чтобы значения извне изображения никогда не требовались. Машинное обучение в основном использует этот подход. Пример: размер ядра 10x10, размер изображения 32x32, результирующее изображение 23x23.
- Обрезка ядра
- Любой пиксель в ядре, выходящий за пределы входного изображения, не используется, и нормализация корректируется для компенсации.
- Постоянный
- Используйте постоянное значение для пикселей за пределами изображения. Обычно используется черный или иногда серый цвет. Обычно это зависит от приложения.
Нормализация
[ редактировать ]Нормализация определяется как деление каждого элемента ядра на сумму всех элементов ядра так, чтобы сумма элементов нормализованного ядра равнялась единице. Это гарантирует, что средний пиксель модифицированного изображения будет таким же ярким, как средний пиксель исходного изображения.
Оптимизация
[ редактировать ]Алгоритмы быстрой свертки включают в себя:
- отделимая свертка
Сепарабельная свертка
[ редактировать ]2D-свертка с ядром M × N требует умножений M × N для каждого образца (пикселя). Если ядро сепарабельное, то вычисления можно свести к умножениям M + N . Использование разделимых сверток может значительно сократить объем вычислений, выполняя 1D-свертку дважды вместо одной 2D-свертки. [2]
Выполнение
[ редактировать ]Вот конкретная реализация свертки, выполненная с помощью языка шейдеров GLSL :
// author : csblo
// Work made just by consulting :
// https://en.wikipedia.org/wiki/Kernel_(image_processing)
// Define kernels
#define identity 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)
// Find coordinate of matrix element from index
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.xy;
}
// Extract region of dimension 3x3 from sampler centered in uv
// sampler : texture sampler
// uv : current coordinates on sampler
// return : an array of mat3, each index corresponding with a color channel
mat3[3] region3x3(sampler2D sampler, vec2 uv)
{
// Create each pixels for region
vec4[9] region;
for (int i = 0; i < 9; i++)
region[i] = texture(sampler, uv + kpos(i));
// Create 3x3 region with 3 color channels (red, green, blue)
mat3[3] mRegion;
for (int i = 0; i < 3; i++)
mRegion[i] = mat3(
region[0][i], region[1][i], region[2][i],
region[3][i], region[4][i], region[5][i],
region[6][i], region[7][i], region[8][i]
);
return mRegion;
}
// Convolve a texture with kernel
// kernel : kernel used for convolution
// sampler : texture sampler
// uv : current coordinates on sampler
vec3 convolution(mat3 kernel, sampler2D sampler, vec2 uv)
{
vec3 fragment;
// Extract a 3x3 region centered in uv
mat3[3] region = region3x3(sampler, uv);
// for each color channel of region
for (int i = 0; i < 3; i++)
{
// get region channel
mat3 rc = region[i];
// component wise multiplication of kernel by region channel
mat3 c = matrixCompMult(kernel, rc);
// add each component of matrix
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];
// for fragment at channel i, set result
fragment[i] = r;
}
return fragment;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = fragCoord/iResolution.xy;
// Convolve kernel with texture
vec3 col = convolution(emboss, iChannel0, uv);
// Output to screen
fragColor = vec4(col, 1.0);
}
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ «Пример 2D-свертки» .
- ^ «Свертка» . www.songho.ca . Проверено 19 ноября 2022 г.
Источники
[ редактировать ]- Людвиг, Джейми (н. д.). Свертка изображения (PDF) . Портлендский государственный университет.
- Лекарм, Оливье; Дельваре, Карин (январь 2013 г.). Книга GIMP: полное руководство практически по всему . Нет крахмального пресса. п. 429. ИСБН 978-1593273835 .
- Гамстер, Джейсон ван; Шимонски, Роберт (март 2012 г.). Библия GIMP . Джон Уайли и сыновья. стр. 438–442. ISBN 978-0470523971 .
- Шапиро, Линда Г .; Стокман, Джордж К. (февраль 2001 г.). Компьютерное зрение . Прентис Холл. стр. 53–54. ISBN 978-0130307965 .
Внешние ссылки
[ редактировать ]- Реализация 2D-свертки на FPGA
- Руководство по программированию vImage: выполнение операций свертки
- Обработка изображений с использованием 2D-свертки
- Программа управления изображениями GNU — Руководство пользователя — 8.2. Матрица свертки
- GLSL Демонстрация ядер свертки 3x3
- Полный проект с открытым исходным кодом на C++.