Kernel (processamento de imagem) - Kernel (image processing)
No processamento de imagem , um kernel , matriz de convolução ou máscara é uma pequena matriz usada para desfoque, nitidez, relevo, detecção de bordas e muito mais. Isso é feito fazendo uma convolução entre o kernel e uma imagem .
Detalhes
A expressão geral de uma convolução é
onde está a imagem filtrada, é a imagem original, é o kernel do filtro. Cada elemento do kernel do filtro é considerado por e .
Dependendo dos valores do elemento, um kernel pode causar uma ampla gama de efeitos.
Operação | Kernel ω | Resultado de imagem g (x, y) |
---|---|---|
Identidade | ||
Detecção de borda | ||
Afiado | ||
Desfoque de caixa ( normalizado ) |
||
Desfoque gaussiano 3 × 3 (aproximação) |
||
Desfoque gaussiano 5 × 5 (aproximação) |
||
Máscara de desfocagem 5 × 5 com base em desfoque gaussiano com quantidade de 1 e limite de 0 (sem máscara de imagem ) |
|
Os itens acima são apenas alguns exemplos de efeitos alcançáveis pela convolução de kernels e imagens.
Origem
A origem é a posição do kernel que está acima (conceitualmente) do pixel de saída atual. Isso pode estar fora do kernel real, embora geralmente corresponda a um dos elementos do kernel. Para um kernel simétrico, a origem geralmente é o elemento central.
Convolução
Convolução é o processo de adicionar cada elemento da imagem aos seus vizinhos locais, ponderado pelo kernel. Isso está relacionado a uma forma de convolução matemática . A operação de matriz que está sendo realizada - convolução - não é a multiplicação de matriz tradicional, apesar de ser denotada de forma semelhante por *.
Por exemplo, se tivermos duas matrizes três por três, a primeira um kernel e a segunda um pedaço de imagem, a convolução é o processo de inverter as linhas e colunas do kernel e multiplicar entradas localmente semelhantes e somar. O elemento nas coordenadas [2, 2] (ou seja, o elemento central) da imagem resultante seria uma combinação ponderada de todas as entradas da matriz da imagem, com pesos dados pelo kernel:
As outras entradas seriam ponderadas de forma semelhante, onde posicionamos o centro do kernel em cada um dos pontos limites da imagem e calculamos uma soma ponderada.
Os valores de um determinado pixel na imagem de saída são calculados multiplicando cada valor de kernel pelos valores de pixel da imagem de entrada correspondentes. Isso pode ser descrito algoritmicamente com o seguinte pseudocódigo:
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
- * os pixels da imagem de entrada correspondentes são encontrados em relação à origem do kernel.
Se o kernel for simétrico, coloque o centro (origem) do kernel no pixel atual. O kernel irá se sobrepor aos pixels vizinhos em torno da origem. Cada elemento do kernel deve ser multiplicado com o valor do pixel com o qual ele se sobrepõe e todos os valores obtidos devem ser somados. Esta soma resultante será o novo valor para o pixel atual atualmente sobreposto ao centro do kernel.
Se o kernel não for simétrico, ele deve ser invertido em torno de seu eixo horizontal e vertical antes de calcular a convolução como acima.
A forma geral para a convolução da matriz é
Manuseio de Borda
A convolução do kernel geralmente requer valores de pixels fora dos limites da imagem. Existem vários métodos para lidar com as bordas da imagem.
- Ampliar
- Os pixels da borda mais próximos são conceitualmente estendidos até o ponto necessário para fornecer valores para a convolução. Os pixels de canto são estendidos em cunhas de 90 °. Outros pixels de borda são estendidos em linhas.
- Enrolar
- A imagem é conceitualmente envolvida (ou ladrilhada) e os valores são obtidos da borda ou canto oposto.
- Espelho
- A imagem é conceitualmente espelhada nas bordas. Por exemplo, tentar ler um pixel de 3 unidades fora de uma borda, em vez disso, lê uma 3 unidades dentro da borda.
- Cortar
- Qualquer pixel na imagem de saída que exigir valores além da borda é ignorado. Este método pode fazer com que a imagem de saída seja ligeiramente menor, com as bordas cortadas.
- Kernel Crop
- Qualquer pixel no kernel que ultrapassa a imagem de entrada não é usado e a normalização é ajustada para compensar.
Normalização
A normalização é definida como a divisão de cada elemento do kernel pela soma de todos os elementos do kernel, de forma que a soma dos elementos de um kernel normalizado seja a unidade. Isso garantirá que o pixel médio na imagem modificada seja tão brilhante quanto o pixel médio na imagem original.
Implementação concreta
Aqui está uma implementação de convolução concreta feita com a linguagem de sombreamento 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);
}
Referências
- Ludwig, Jamie (nd). Convolução de imagens (PDF) . Portland State University .
- Lecarme, Olivier; Delvare, Karine (janeiro de 2013). O livro do GIMP: um guia completo para quase tudo . Sem Starch Press . p. 429. ISBN 978-1593273835.
- Gumster, Jason van; Shimonski, Robert (março de 2012). Bíblia GIMP . Wiley . pp. 438–442. ISBN 978-0470523971.
- Shapiro, Linda G .; Stockman, George C. (fevereiro de 2001). Visão computacional . Prentice Hall . pp. 53–54. ISBN 978-0130307965.
Veja também
links externos
- Implementando a convolução 2d em FPGA
- Guia de programação vImage: realizando operações de convolução
- Processamento de imagem usando convolução 2D
- GNU Image Manipulation Program - User Manual - 8.2. Matriz de Convolução
- Demonstração GLSL de Kernels de Convolução 3x3
- Projeto de código aberto C ++ completo