AccueilAccueil  FAQFAQ  RechercherRechercher  S'enregistrerS'enregistrer  MembresMembres  Connexion  

Partagez | 
 

 [Tutoriel]Initiation au traitement d'images numériques

Voir le sujet précédent Voir le sujet suivant Aller en bas 
AuteurMessage
onilink_
Modérateur
avatar

Messages : 8926
Localisation : Montpellier
Projet Actuel : Planet Centauri
OniDev

MessageSujet: [Tutoriel]Initiation au traitement d'images numériques   Mer 6 Avr 2011 - 18:43

Initiation au traitement d'images numériques


Introduction

Une image numérique est définie comme une matrice de taille Largeur*Hauteur.
Elle se lit de gauche a droite et de haut en bas.
Le pixel de position [0,0] est donc celui en haut a gauche.
Chaque valeur de cette matrice représente une couleur.

Pour image en niveaux de gris on pourras coder tonalité de 0 a 255.
Pourquoi de telles valeurs ? Car physiquement, c'est la capacité d'un octet (ou huit bits). De ce fait chaque pixel de l'image seras codé sur un octet.

La taille (ou poids) qu'une image prend en mémoire est donc facile a calculer :
taille = largeur * hauteur

On appelle le nombre de niveaux de gris la tonalité maximale moins la tonalité minimale de chaque pixel. Une image ayant peu de niveaux de gris pourras être codé sur moins de bits mais auras une moins bonne résolution.


Pour coder une image de couleur il faut d'abord savoir ce qu'est une couleur.
"La couleur est la perception subjective qu'a l'œil d'une ou plusieurs fréquences d'ondes lumineuses, avec une (ou des) amplitude(s) donnée(s)." (wikipedia)
Pour faire simple la couleur d'un rayon lumineux dépend de la longueur d'onde de celui ci, donc de sa fréquence. Ainsi pour les fréquences comprises entre 480 et 405 est associé la couleur rouge, celles comprises entre 510 et 480 le orange, et ainsi de suite.
La lumière visible pour l'œil humain est dans le domaine des fréquences comprises entre 405 et 790 (Infrarouges et ultraviolets).

D'où le spectre lumineux suivant :

Intéressons nous maintenant a la perception des couleurs par l'œil humain.
L'œil humain permet la perception des couleurs grâce a des récepteurs, les cônes. Il y en a 3 types, et chacun d'eux est sensible a un domaine de fréquences particulier.
Les cônes L sont sensibles aux rouges, les cônes M au verts et les cônes S au bleu.
D'où leur nom : ondes longues -> Long, ondes moyennes -> Median et ondes courtes -> Small.

Une couleur peut donc être codée avec une tonalité de rouge, de vert et de bleu.
C'est la synthèse additive, le contraire de la synthèse soustractive qui elle est visible dans les mélanges de peintures par exemple (de la peinture jaune mélangé a de la peinture cyan donneras du vert.)
Elle est un peu déconcertante au début, mais on s'y habitue vite.

Mélanges des couleurs primaires de la lumière en mode additif

Nous allons donc utiliser 3 octets pour coder une couleur (un octet par composante).
Nous noterons donc une couleur dans une notation hexadécimale, qui simplifieras l'écriture d'une couleur. L'octet de poids fort coderas le bleu et celui de poids faible de rouge.
La couleur 0xFFFFFF seras donc du blanc (soit r=255,g=255,b=255), la couleur 0x000000 du noir, 0xFF du rouge, 0xFF00 du vert, 0xFF0000 du bleu. Le 0x signifie que nous utilisons une notation hexadécimale.

La taille d'une image 24 bits (true color) est donc :
taille = largeur * hauteur * 3

Il existe aussi les images 32 bits, qui elles ont en plus un canal alpha.
Les formats png, tga et bmp gèrent sans problèmes ces formats.

Maintenant que nous savons ce qu'est une image numérique, nous allons apprendre a créer des filtres de traitement. Ces filtres servirons a améliorer la qualité de nos images (modification du contraste par exemple), ou a obtenir divers effets intéressants.

Matrices de convolution

Une méthode de traitement efficace d'image numérique est l'utilisation d'une convolution entre l'image, et le filtre.
Une convolution est un traitement d'une matrice par une autre appelée matrice de convolution (ici le filtre).

La convolution d'une matrice I par la matrice F consiste a calculer pour chaque point de I la somme des produits de chaque point avec la matrice F.
Voici un schémas qui montre comment calculer la valeur d'un pixel de l'image a filtrer.


Nous travaillerons avec des valeurs allant de 0 a 255 dans notre image, et par conséquent une image obtenue après convolution avec un filtre ne doit pas comporter de pixel ayant une valeur en dehors de ce champs. Hors nous observons qu'avec le filtre précédent, la valeur d'un point peut aller jusqu'à 3*255.
Pour pallier a ce problème il faut normaliser. Cela consiste a, si la somme des valeurs d'un filtre (que l'on noteras S) est supérieur a 1, ou inférieur a 0, de diviser après la convolution la valeur du point obtenu par S.
Ce qui empêcheras les résultat d'avoir des valeurs normalement impossibles pour une matrice représentant une image.

Passons a la pratique !

Mettons maintenant la théorie en pratique. Pour la suite j'utiliserai µDev++, un logiciel qui nous permettra de coder notre application en C++ sans avoir a nous soucier du fenêtrage, du temps, et autres...
Bien sur vous pouvez utiliser tout autre logiciel mais après c'est a vous de voir (et donc de 'traduire' le code en conséquences).

Tout d'abord voici l'image que je vais utiliser pour tester chacun des filtres que nous créerons :
Spoiler:
 

La première opération va consister a stocker notre image dans une matrice de unsigned int.
Voici le code µDev pour charger l'image en mémoire (dans "Create") :
Code:
uint w, h, *data = image_load_bmp("im_ref.bmp", w, h);
et pour libérer la mémoire utilisé (a la fin du "Create", ou dans "End") :
Code:
delete[] data;

Essayons d'afficher notre image pour voir si tout va bien :
Code:
uint w, h, *data = image_load_bmp("im_ref.bmp", w, h);
for(int x=0; x<w; x++)
for(int y=0; y<h; y++)
{
    draw_point_color(x, y, data[x+w*y]);
}
delete[] data;


Voila. Maintenant nous pouvons créer notre matrice de convolution.

Code:
const int filter_w=3, filter_h=3;
double filter[filter_w][filter_h] =
{
    0, 0, 0,
    0, 1, 0,
    0, 0, 0
};
double factor = 1.0;
double sway = 0;


factor est la valeur dont je vous ai parlé plus haut, celle qui serviras a normaliser.
sway elle s'additionnera a la valeur de chaque pixel après convolution (utile dans le cas ou une image est trop sombre par exemple).

Maintenant pour appliquer la convolution il va falloir appliquer deux balayages successifs.
Un serviras a parcourir l'image, un autre le filtre pour faire le calcul de convolution.
Code:
glBegin(GL_POINTS); // Pour indiquer a openGl que nous allons commencer a dessiner des points
for(int x=0; x<w; x++) // Double boucle pour balayer l'image a filtrer
for(int y=0; y<h; y++)
{
    int r = sway, g = sway, b = sway; // Les composantes rgb ou l'on stockera la valeur obtenu pour la convolution au point de coordonnées (x,y)
    for(int xx=0; xx<filter_w; xx++) // Balayage du filtre
    for(int yy=0; yy<filter_h; yy++)
    {
        int X = (x+xx-filter_w/2+w)%w;
        int Y = (y+yy-filter_h/2+h)%h;
        byte *c = (byte*) &data[X + Y*w]; // Un pointeur qui nous permettra de récupérer les composantes rgb de la couleur du pixel de position (x,y) comme s'il s'agissait d'un simple tableau de byte.
        // Calculs de la convolution
        r += (double)c[0] * filter[xx][yy];
        g += (double)c[1] * filter[xx][yy];
        b += (double)c[2] * filter[xx][yy];
    }
    if(r<0) r=0; if(g<0) g=0; if(b<0) b=0; // au cas ou on aurais des valeurs négatives
    // Et on affiche le point de la couleur obtenue
    glColor3ub(r*factor, g*factor, b*factor);
    glVertex2d(x, y);
}
glEnd();


Et voici le code complet du filtrage par matrice de convolution :
Code:
window_set_size(640, 360);

// Le filtre
const int filter_w=3, filter_h=3;
double filter[filter_w][filter_h] =
{
    0, 0, 0,
    0, 1, 0,
    0, 0, 0
};
double factor = 1;
double sway = 0;

uint w, h, *data = image_load_bmp("im_ref.bmp", w, h);

glBegin(GL_POINTS);
for(int x=0; x<w; x++)
for(int y=0; y<h; y++)
{
    int r = sway, g = sway, b = sway;
    for(int xx=0; xx<filter_w; xx++)
    for(int yy=0; yy<filter_h; yy++)
    {
        int X = (x+xx-filter_w/2+w)%w;
        int Y = (y+yy-filter_h/2+h)%h;
        byte *c = (byte*) &data[X + Y*w];

        r += (double)c[0] * filter[xx][yy];
        g += (double)c[1] * filter[xx][yy];
        b += (double)c[2] * filter[xx][yy];
    }
    if(r<0) r=0; if(g<0) g=0; if(b<0) b=0;
   
    glColor3ub(r*factor, g*factor, b*factor);
    glVertex2d(x, y);
}
glEnd();

delete[] data;


Bien sur ce code va se contenter de nous afficher la même image que celle d'entré.
Si vous observez le filtre c'est tout a fait logique. Pour briser la monotonie nous allons donc commencer a créer nos filtres (et qui ont un effet cette fois, si je suis pas trop gentil Very Happy)

Flou simple

Code:
double filter[filter_w][filter_h] =
{
    1, 1, 1,
    1, 1, 1,
    1, 1, 1
};
double factor = 1.0/9.0;
double sway = 0;


Ce filtre va nous faire un flou des plus simple. Pour chaque pixel on fait la moyennes avec ses voisins.

Spoiler:
 

Flou gaussien

Code:
double filter[filter_w][filter_h] =
{
    1, 2, 1,
    2, 4, 2,
    1, 2, 1
};
double factor = 1.0/16.0;
double sway = 0;


Un filtre un peu plus recherché qui nous donne un flou de bonne qualité :p
Spoiler:
 

Augmenter le contraste

Code:
double filter[filter_w][filter_h] =
{
    0,-1, 0,
  -1, 5,-1,
    0,-1, 0
};
double factor = 1;
double sway = 0;


Spoiler:
 


Repoussage

Code:
double filter[filter_w][filter_h] =
{
  -2,-1, 0,
  -1, 1, 1,
    0, 1, 2
};
double factor = 1;
double sway = 0;


Spoiler:
 


Détection des contours simple

Code:
double filter[filter_w][filter_h] =
{
    0, 0, 0,
  -1, 1, 0,
    0, 0, 0
};
double factor = 1;
double sway = 0;


Spoiler:
 


Détection des contours (Laplaciens)

Code:
double filter[filter_w][filter_h] =
{
    0,-1, 0,
  -1, 4,-1,
    0,-1, 0
};
double factor = 1;
double sway = 0;


Spoiler:
 

Code:
double filter[filter_w][filter_h] =
{
  -1,-1,-1,
  -1, 8,-1,
  -1,-1,-1
};
double factor = 1;
double sway = 0;


Spoiler:
 


Code:
double filter[filter_w][filter_h] =
{
    1,-2, 1,
  -2, 4,-2,
    1,-2, 1
};
double factor = 1;
double sway = 0;


Spoiler:
 

Flou cinétique diagonal (léger)

Code:
double filter[filter_w][filter_h] =
{
    1, 0, 0,
    0, 1, 0,
    0, 0, 1
};
double factor = 1.0/3.0;
double sway = 0;


Spoiler:
 


Bien sur vous n'êtes pas limité dans la taille du filtre.
Par exemple pour avoir un filtre cinétique de meilleur qualité vous pouvez utiliser une matrice de 5x5 :
Code:
const int filter_w=5, filter_h=5;
double filter[filter_w][filter_h] =
{
    1, 0, 0, 0, 0,
    0, 2, 0, 0, 0,
    0, 0, 2, 0, 0,
    0, 0, 0, 2, 0,
    0, 0, 0, 0, 1,
};
double factor = 1.0/8.0;
double sway = 0;


Par contre plus la matrice seras grande et plus les calculs seront longs.



Voila, je présenterai d'autres méthodes de traitement prochainement, comme le traitement par histogramme et la transformée de fourrier. Aussi le tuto n'est pas fini, je prendrais le temps de le relire plus tard, et corrigerais les éventuelles fautes.

_________________
                 


Dernière édition par onilink_ le Mer 6 Avr 2011 - 20:23, édité 4 fois
Revenir en haut Aller en bas
l0lmanPH
Utilisateur confirmé: Rang *
avatar

Messages : 226
Localisation : cbna.forumactif.com
Projet Actuel : Le Méchant Tueur de Bisounours
Metroid Prime : Némésis
Tutoriel GM

MessageSujet: Re: [Tutoriel]Initiation au traitement d'images numériques   Mer 6 Avr 2011 - 19:26

Great !

J'ai beaucoup ri avec le logo Triforce-like que tu m'avais montré et µDev. xD
Tu devrais donner un lien vers celui-ci d'ailleurs...

Quelques erreurs :
- "et bmp gèrent Ces formats" ;
- la notation hexa du noir est celle du blanc ;
- "elle se liT donc de gauche ..." ;
- "pour la suite j'utiliserai(PAS DE "S")" ;
- "par conséquent une image obtenuE après convolution" ;
- "des valeurs normalement impossibleS" ;
- "a la fin du crE(PAS D'ACCENT)ate, ou dans end" ;
- "et qui ont un effet EN (?) plus" je crois ;
- "Aussi le tuto n'est pas fini(SANS "S")" ;
- - "parlé plus haut, celle qui servira(PAS DE "S") a normaliser", tu mets des "s" aux 3èmes personnes du futur un peu partout ;
- n'oublie pas de mettre des guillemets autour des noms d'onglets comme "Create" ou "End" xD ;
- et attention je vois aucun "a" accent grave dans ton texte et fais aussi gaffe aux accents sur le "où".

Je vais finir de le lire.

EDIT : Incroyable ce qu'on fait comme filtre avec 3 lignes !

_________________

« Un même visage, un même passé, deux destins différents ? »
Metroid Prime : Némésis, fangame et suite du célèbre Metroid Prime 3 : Corruption.

Rédaction d'un big-tuto pour le SdZ sur Game Maker...
Avancement : 60% hors-ligne, 5% en ligne.


Dernière édition par l0lmanPH le Mer 6 Avr 2011 - 19:43, édité 3 fois
Revenir en haut Aller en bas
onilink_
Modérateur
avatar

Messages : 8926
Localisation : Montpellier
Projet Actuel : Planet Centauri
OniDev

MessageSujet: Re: [Tutoriel]Initiation au traitement d'images numériques   Mer 6 Avr 2011 - 19:31

ok merci, je suis un peu fatigué ces derniers temps (pour changer xD)

_________________
                 


Dernière édition par onilink_ le Mer 6 Avr 2011 - 19:46, édité 1 fois
Revenir en haut Aller en bas
[TheDarkTiger]
Modérateur
avatar

Messages : 7381
Localisation : Essonne

MessageSujet: Re: [Tutoriel]Initiation au traitement d'images numériques   Mer 6 Avr 2011 - 19:41

Si tu à besoin d'aide en traitement d'image, c'est ma spécialité.
Je serait ravi de t'aider Wink

EDIT
Je t'ai corrigé quelques fautes Wink

Sobel :
[-2, -2, 0]
[-2, 0, 2]
[0, 2, 2]

Y a les histogrammes qui sont sympa aussi.

_________________
Bonne chance pour vos projets actuels ! Prêt à aider ceux qui en ont besoin ^^
l'antique http://www.membres.lycos.fr/thedarkminousite/
Bienvenue au 2531eme utilisateur : fffffff !


Dernière édition par [TheDarkTiger] le Mer 6 Avr 2011 - 19:59, édité 1 fois
Revenir en haut Aller en bas
http://www.membres.lycos.fr/thedarkminousite/
onilink_
Modérateur
avatar

Messages : 8926
Localisation : Montpellier
Projet Actuel : Planet Centauri
OniDev

MessageSujet: Re: [Tutoriel]Initiation au traitement d'images numériques   Mer 6 Avr 2011 - 19:48

Cay gentil, mais a mon avis je devrais m'en sortir :p
Je te demanderais peut être de regarder le tuto quand il seras fini pour vérifier qu'il n'y ai pas de bêtises par contre Very Happy

_________________
                 
Revenir en haut Aller en bas
[TheDarkTiger]
Modérateur
avatar

Messages : 7381
Localisation : Essonne

MessageSujet: Re: [Tutoriel]Initiation au traitement d'images numériques   Mer 6 Avr 2011 - 20:00

sans problème Wink

Ca sera pas utile, mais bon :
http://membres.multimania.fr/thedarkminousite/

_________________
Bonne chance pour vos projets actuels ! Prêt à aider ceux qui en ont besoin ^^
l'antique http://www.membres.lycos.fr/thedarkminousite/
Bienvenue au 2531eme utilisateur : fffffff !
Revenir en haut Aller en bas
http://www.membres.lycos.fr/thedarkminousite/
arthuro
Utilisateur confirmé: Rang ****
avatar

Messages : 1337
Localisation : Grenoble / Méribel
Projet Actuel : CBNA

MessageSujet: Re: [Tutoriel]Initiation au traitement d'images numériques   Jeu 7 Avr 2011 - 14:26

sympa,

Je m'était toujours demandé comment était fait le filtre ajout de netteté. Trés simplement en faite.

_________________

D'autres jeux :
In The Cube
In the cube 2
Revenir en haut Aller en bas
Contenu sponsorisé




MessageSujet: Re: [Tutoriel]Initiation au traitement d'images numériques   

Revenir en haut Aller en bas
 
[Tutoriel]Initiation au traitement d'images numériques
Voir le sujet précédent Voir le sujet suivant Revenir en haut 
Page 1 sur 1
 Sujets similaires
-
» Couture - Chouette (anglais en images)
» Paint.NET un logiciel d'images GRATUIT mieux que des logiciels payants
» Tutoriel fraîcheur d'Hawaii
» Traitement de la phobie sociale
» La guerre de 1870-71 en images

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
Forum Le CBNA :: Développement :: Programmation-
Sauter vers: