Article de reference

Noyau (traitement d'image)

En traitement d'image , un noyau , une matrice de convolution ou un masque est une petite matrice utilisée pour le floutage, la netteté, le gaufrage, la détection des contours ,...

En traitement d'image , un noyau , une matrice de convolution ou un masque est une petite matrice utilisée pour le floutage, la netteté, le gaufrage, la détection des contours , etc. Cela est accompli en effectuant une convolution entre le noyau et une image . Ou plus simplement, lorsque chaque pixel de l'image de sortie est une fonction des pixels proches (y compris lui-même) de l'image d'entrée, le noyau est cette fonction.

Détails

L'expression générale d'une convolution est

où est l'image filtrée, est l'image originale, est le noyau du filtre. Chaque élément du noyau du filtre est pris en compte par et .

Selon les valeurs des éléments, un noyau peut provoquer une large gamme d'effets :

Ce qui précède ne sont que quelques exemples d’effets réalisables en convoluant des noyaux et des images.

Origine

L'origine est la position du noyau qui se trouve au-dessus (conceptuellement) du pixel de sortie actuel. Elle peut se trouver à l'extérieur du noyau réel, mais correspond généralement à l'un des éléments du noyau. Pour un noyau symétrique, l'origine est généralement l'élément central.

Convolution

Animation de convolution 2D

La convolution est le processus consistant à ajouter chaque élément de l'image à ses voisins locaux, pondérés par le noyau. Cela est lié à une forme de convolution mathématique . L'opération matricielle effectuée (la convolution) n'est pas une multiplication matricielle traditionnelle, bien qu'elle soit également désignée par *.

Par exemple, si nous avons deux matrices trois par trois, la première étant un noyau et la seconde une image, la convolution est le processus consistant à inverser les lignes et les colonnes du noyau et à multiplier les entrées localement similaires et à les additionner. L'élément aux coordonnées [2, 2] (c'est-à-dire l'élément central) de l'image résultante serait une combinaison pondérée de toutes les entrées de la matrice d'image, avec des poids donnés par le noyau :

Les autres entrées seraient pondérées de la même manière, où nous positionnerions le centre du noyau sur chacun des points limites de l'image et calculerions une somme pondérée.

Les valeurs d'un pixel donné dans l'image de sortie sont calculées en multipliant chaque valeur de noyau par les valeurs de pixels de l'image d'entrée correspondante. Cela peut être décrit algorithmiquement avec le pseudo-code suivant :

pour chaque 
ligne d'image 
dans 
l'image d'entrée : pour chaque 
pixel 
dans 
la ligne d'image : mettre 
l'accumulateur à zéro pour chaque 
ligne du 
noyau 
: pour chaque 
élément 
de 
la ligne du noyau : si 
la position de l'élément correspond* à la position du pixel 
alors 
multipliez 
la valeur de l'élément correspondant* à la valeur du pixel 
ajoutez 
le résultat à l'accumulateur 
fin si
définir 
le pixel de l'image de sortie sur l'accumulateur
*les pixels de l'image d'entrée correspondants sont trouvés par rapport à l'origine du noyau.

Si le noyau est symétrique, placez le centre (origine) du noyau sur le pixel actuel. Le noyau chevauchera les pixels voisins autour de l'origine. Chaque élément du noyau doit être multiplié par la valeur du pixel avec lequel il chevauche et toutes les valeurs obtenues doivent être additionnées. Cette somme résultante sera la nouvelle valeur du pixel actuel actuellement chevauché par le centre du noyau.

Si le noyau n'est pas symétrique, il doit être retourné autour de son axe horizontal et vertical avant de calculer la convolution comme ci-dessus.

La forme générale de la convolution matricielle est

Manipulation des bords

Extension de la gestion des bords

La convolution du noyau nécessite généralement des valeurs provenant de pixels situés en dehors des limites de l'image. Il existe plusieurs méthodes pour gérer les contours de l'image.

Étendre
Les pixels de bordure les plus proches sont étendus conceptuellement autant que nécessaire pour fournir des valeurs pour la convolution. Les pixels d'angle sont étendus en segments de 90°. Les autres pixels de bord sont étendus en lignes.
Envelopper
L'image est conceptuellement enveloppée (ou carrelée) et les valeurs sont extraites du bord ou du coin opposé.
Miroir
L'image est conceptuellement reflétée sur les bords. Par exemple, si vous essayez de lire un pixel situé à 3 unités à l'extérieur d'un bord, vous en lirez un situé à 3 unités à l'intérieur du bord.
Recadrer / Éviter les chevauchements
Tout pixel de l'image de sortie qui nécessiterait des valeurs au-delà du bord est ignoré. Cette méthode peut entraîner une image de sortie légèrement plus petite, les bords ayant été rognés. Déplacez le noyau de sorte que les valeurs extérieures à l'image ne soient jamais requises. L'apprentissage automatique utilise principalement cette approche. Exemple : taille du noyau 10x10, taille de l'image 32x32, image résultante 23x23.
Récolte de noyaux
Tout pixel du noyau qui s'étend au-delà de l'image d'entrée n'est pas utilisé et la normalisation est ajustée pour compenser.
Constante
Utiliser une valeur constante pour les pixels situés à l'extérieur de l'image. On utilise généralement du noir ou parfois du gris. En général, cela dépend de l'application.

Normalisation

La normalisation est définie comme la division de chaque élément du noyau par la somme de tous les éléments du noyau, de sorte que la somme des éléments d'un noyau normalisé soit égale à un. Cela garantit que le pixel moyen de l'image modifiée est aussi brillant que le pixel moyen de l'image d'origine.

Optimisation

Les algorithmes de convolution rapides incluent :

  • convolution séparable

Convolution séparable

La convolution 2D avec un noyau M × N nécessite M × N multiplications pour chaque échantillon (pixel). Si le noyau est séparable, le calcul peut être réduit à M + N multiplications. L'utilisation de convolutions séparables peut réduire considérablement le calcul en effectuant deux fois la convolution 1D au lieu d'une seule convolution 2D.

Mise en œuvre

Voici une implémentation concrète de convolution réalisée avec le langage de shading GLSL :

// auteur : csblo 
// Travail réalisé simplement en consultant : 
// https://en.wikipedia.org/wiki/Kernel_(image_processing)
// Définir les noyaux 
#définir l'identité mat3(0, 0, 0, 0, 1, 0, 0 
, 0, 0) #définir le bord0 mat3(1, 0, -1, 0, 0, 0, -1, 0 
, 1) #définir le bord1 mat3(0, 1, 0, 1, -4, 1, 0, 1, 0) 
#définir le bord2 mat3(-1, -1, -1, -1, -1, 8, -1, -1, -1, -1) 
#définir la netteté mat3(0, -1, 0, -1, 5, -1, 0, -1, 0) 
#définir le flou de boîte mat3(1, 1, 1, 1, 1, 1, 1, 1) * 0.1111 
#définir le flou gaussien mat3(1, 2, 1, 2, 4, 2, 1, 2, 1) * 0,0625 
#define emboss mat3(-2, -1, 0, -1, 1, 1, 0, 1, 2)
// Trouver les coordonnées de l'élément de matrice à partir de l'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 ; }
// Extraire la région de dimension 3x3 de l'échantillonneur centré sur uv 
// échantillonneur : échantillonneur de texture 
// uv : coordonnées actuelles sur l'échantillonneur 
// retour : un tableau de mat3, chaque index correspondant à un canal de couleur 
mat3 [ 3 ] region3x3 ( sampler2D sampler , vec2 uv ) { // Créer chaque pixel pour la région vec4 [ 9 ] region ; for ( int i = 0 ; i < 9 ; i ++ ) region [ i ] = texture ( sampler , uv + kpos ( i ));
// Créer une région 3x3 avec 3 canaux de couleur (rouge, vert, bleu) 
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 ; }
// Convolution d'une texture avec le noyau 
// noyau : noyau utilisé pour la convolution 
// échantillonneur : échantillonneur de texture 
// uv : coordonnées actuelles sur l'échantillonneur 
vec3 convolution ( noyau mat3 , sampler2D échantillonneur , vec2 uv ) { vec3 fragment ; // Extraire une région 3x3 centrée sur uv mat3 [ 3 ] region = region3x3 ( sampler , uv ); // pour chaque canal de couleur de la région for ( int i = 0 ; i < 3 ; i ++ ) { // obtenir le canal de région mat3 rc = region [ i ]; // multiplication composant par composant du noyau par le canal de région mat3 c = matrixCompMult ( noyau , rc ); // ajouter chaque composant de la matrice 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 ]; // pour le fragment sur le canal i, définir le résultat fragment [ i ] = r ; } return fragment ; }
void mainImage ( out vec4 fragColor , in vec2 fragCoord ) { // Coordonnées de pixels normalisées (de 0 à 1) vec2 uv = fragCoord / iResolution . xy ; // Convolution du noyau avec la texture vec3 col = convolution ( emboss , iChannel0 , uv ); // Sortie sur l'écran fragColor = vec4 ( col , 1.0 ); }

Plus d articles de Worldlex Wiki

Revenez a l index pour explorer davantage de pages sur l histoire, la science, la culture, la geographie et la societe en francais.

Explorer l index