En el procesamiento de imágenes , un núcleo , matriz de convolución o máscara es una matriz pequeña que se utiliza para desenfocar, enfocar, crear relieve , detectar bordes y otras funciones. Esto se logra mediante una convolución entre el núcleo y la imagen . En otras palabras, cuando cada píxel de la imagen de salida es una función de los píxeles cercanos (incluido él mismo) de la imagen de entrada, el núcleo es esa función.
Detalles
La expresión general de una convolución es
dóndees la imagen filtrada,es la imagen original,es el núcleo del filtro. Cada elemento del núcleo del filtro es considerado por y.
Dependiendo de los valores de los elementos, un núcleo puede provocar una amplia gama de efectos:
Los ejemplos anteriores son solo algunos de los efectos que se pueden lograr mediante la convolución de núcleos e imágenes.
Origen
El origen es la posición del núcleo que se encuentra (conceptualmente) por encima del píxel de salida actual. Este origen podría estar fuera del núcleo propiamente dicho, aunque generalmente corresponde a uno de sus elementos. Para un núcleo simétrico, el origen suele ser el elemento central.
Circunvolución

La convolución es el proceso de sumar cada elemento de la imagen a sus vecinos locales, ponderados por el núcleo. Esto se relaciona con una forma de convolución matemática . La operación matricial que se realiza —la convolución— no es la multiplicación matricial tradicional , a pesar de que se denota de forma similar con *.
Por ejemplo, si tenemos dos matrices de tres por tres, la primera un núcleo y la segunda un fragmento de imagen, la convolución es el proceso de invertir tanto las filas como las columnas del núcleo, multiplicar las entradas localmente similares y sumarlas. El elemento en las coordenadas [2, 2] (es decir, el elemento central) de la imagen resultante sería una combinación ponderada de todas las entradas de la matriz de imagen, con pesos dados por el núcleo:
Las demás entradas tendrían un peso similar, donde colocamos el centro del núcleo en cada uno de los puntos del límite de la imagen y calculamos una suma ponderada .
Los valores de un píxel determinado en la imagen de salida se calculan multiplicando cada valor del núcleo por los valores de los píxeles correspondientes de la imagen de entrada. Esto se puede describir algorítmicamente con el siguiente pseudocódigo:
para cada fila de imagen en la imagen de entrada : para cada píxel en la fila de imagen : Poner el acumulador a cero. para cada fila del kernel en kernel : para cada elemento en la fila del kernel : Si la posición del elemento corresponde* a la posición del píxel , entonces multiplica el valor del elemento correspondiente* al valor del píxel y suma el resultado al acumulador .establecer el píxel de la imagen de salida en el acumulador
- * Los píxeles correspondientes de la imagen de entrada se encuentran en relación con el origen del kernel.
Si el núcleo es simétrico, coloque su centro (origen) en el píxel actual. El núcleo se superpondrá a los píxeles vecinos alrededor del origen. Cada elemento del núcleo debe multiplicarse por el valor del píxel con el que se superpone, y todos los valores obtenidos deben sumarse. Esta suma resultante será el nuevo valor del píxel actual que se superpone con el centro del núcleo.
Si el núcleo no es simétrico, debe invertirse tanto sobre su eje horizontal como sobre el vertical antes de calcular la convolución como se indicó anteriormente. [ 1 ]
La forma general para la convolución de matrices es
Manejo de bordes

La convolución de kernel generalmente requiere valores de píxeles fuera de los límites de la imagen. Existen diversos métodos para manejar los bordes de la imagen.
- Extender
- Los píxeles de borde más cercanos se extienden conceptualmente hasta donde sea necesario para proporcionar valores para la convolución. Los píxeles de las esquinas se extienden en cuñas de 90°. Los demás píxeles de borde se extienden en líneas.
- Envoltura
- La imagen se presenta de forma conceptual (o en mosaico) y los valores se toman del borde o esquina opuesta.
- Espejo
- La imagen se refleja conceptualmente en los bordes. Por ejemplo, al intentar leer un píxel situado a 3 unidades fuera de un borde, se lee uno situado a 3 unidades dentro del borde.
- Recortar / Evitar superposición
- Se omiten los píxeles de la imagen de salida que requieran valores fuera del borde. Este método puede resultar en una imagen de salida ligeramente más pequeña, con los bordes recortados. Se ajusta el kernel para que nunca se requieran valores fuera de la imagen. El aprendizaje automático utiliza principalmente este enfoque. Ejemplo: tamaño del kernel 10x10, tamaño de la imagen 32x32, imagen resultante 23x23.
- Cultivo de grano
- Cualquier píxel del núcleo que se extienda más allá de la imagen de entrada no se utiliza y la normalización se ajusta para compensar.
- Constante
- Utilice un valor constante para los píxeles fuera de la imagen. Normalmente se usa el negro o, a veces, el gris. Esto depende, por lo general, de la aplicación.
Normalización
La normalización se define como la división de cada elemento del núcleo entre la suma de todos los elementos del núcleo, de modo que la suma de los elementos de un núcleo normalizado sea igual a la unidad. Esto garantiza que el brillo promedio de los píxeles en la imagen modificada sea igual al brillo promedio de los píxeles en la imagen original.
Mejoramiento
Los algoritmos de convolución rápidos incluyen:
- convolución separable
convolución separable
La convolución 2D con un núcleo M × N requiere M × N multiplicaciones por cada muestra (píxel). Si el núcleo es separable, el cálculo se puede reducir a M + N multiplicaciones. El uso de convoluciones separables puede disminuir significativamente el cálculo al realizar dos convoluciones 1D en lugar de una convolución 2D. [ 2 ]
Implementación
Aquí se muestra una implementación concreta de convolución realizada con el lenguaje de sombreado GLSL :
// autor: csblo // Trabajo realizado únicamente consultando: // https://en.wikipedia.org/wiki/Kernel_(image_processing)// Definir núcleos #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)// Encuentra la coordenada del elemento de la matriz desde el índice 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 ; }// Extrae una región de dimensión 3x3 del muestreador centrado en uv // sampler: muestreador de textura // uv: coordenadas actuales en el muestreador // return: una matriz de mat3, cada índice corresponde a un canal de color mat3 [ 3 ] region3x3 ( sampler2D sampler , vec2 uv ) { // Crea cada píxel para la región vec4 [ 9 ] region ; for ( int i = 0 ; i < 9 ; i ++ ) region [ i ] = texture ( sampler , uv + kpos ( i ));// Crea una región de 3x3 con 3 canales de color (rojo, verde, azul) 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 ; }// Convolucionar una textura con un kernel // kernel: kernel utilizado para la convolución // sampler: muestreador de textura // uv: coordenadas actuales en el muestreador vec3 convolution ( mat3 kernel , sampler2D sampler , vec2 uv ) { vec3 fragment ; // Extraer una región de 3x3 centrada en uv mat3 [ 3 ] region = region3x3 ( sampler , uv ); // para cada canal de color de la región for ( int i = 0 ; i < 3 ; i ++ ) { // obtener el canal de la región mat3 rc = region [ i ]; // multiplicación componente a componente del kernel por el canal de la región mat3 c = matrixCompMult ( kernel , rc ); // Suma cada componente de la matriz 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 ]; // Para el fragmento en el canal i, establece el resultado fragment [ i ] = r ; } return fragment ; }void mainImage ( out vec4 fragColor , in vec2 fragCoord ) { // Coordenadas de píxeles normalizadas (de 0 a 1) vec2 uv = fragCoord / iResolution . xy ; // Núcleo de convolución con textura vec3 col = convolution ( emboss , iChannel0 , uv ); // Salida a pantalla fragColor = vec4 ( col , 1.0 ); }Véase también
Referencias
Fuentes
- Ludwig, Jamie (s.f.). Convolución de imágenes (PDF) . Universidad Estatal de Portland.
- Lecarme, Olivier; Delvare, Karine (enero de 2013). El libro de GIMP: Una guía completa para casi todo . No Starch Press. pág. 429. ISBN 978-1593273835.
- Gumster, Jason van; Shimonski, Robert (marzo de 2012). GIMP Bible . John Wiley & Sons. págs. 438–442 . ISBN 978-0470523971.
- Shapiro, Linda G.; Stockman, George C. (febrero de 2001). Visión por computadora . Prentice Hall. págs. 53–54 . ISBN 978-0130307965.
Enlaces externos
- Implementación de convolución 2D en FPGA
- Guía de programación de vImage: Realización de operaciones de convolución
- Procesamiento de imágenes mediante convolución 2D
- Programa de manipulación de imágenes GNU - Manual de usuario - 8.2. Matriz de convolución
- Demostración de GLSL de núcleos de convolución de 3x3
- Proyecto completo de código abierto en C++
- Procesamiento de imágenes
- Detección de características (visión por computadora)