View  Edit  Attributes  History  Attach  Print  Search

ACCUEIL | ARDUINO > S'INSTALLER > DEBUTER > APPROFONDIR | PROCESSING | MECATRONIQUE | MATERIEL | OUTILS | TESTS | Plus...|
Python > Shell > ATELIERS Python + Qt > PyQt apps > PyQt+Arduino | Mes Robots | RepRap | Mes lib'Arduino | Mes shields Arduino | Mes distros | Les Mini-PC |
ATELIERS ARDUINO| VIDEOS | COMPRENDRE | REFERENCES | CODER | TECHNIQUE | GNU/LINUX | LIENS | Rien à voir |

Outils > Processing

Processing : Traitement d'image : Extraction des canaux RGB ou des composantes HSV d'une image et analyse tridimensionnelle avec le logiciel libre Scilab

Explication

  • Une des limites de l'analyse par histogramme est de ne pas refléter la répartition topographique des pixels par niveau de couleur RGB ou de composante HSB. De la même façon, l'analyse par extraction d'un canal donné d'une image préserve l'aspect topographique mais ne permet pas d'appréhender correctement les niveaux de couleur qui s'étalent sur 255 niveaux...
  • D'où l'idée de visualiser la structure d'une image de façon tridimensionnelle pour chaque canal RGB ou composante HSV, l'altitude de chaque point de l'image étant fixée par la valeur du canal ou de la composante et la répartition géographique étant respectée, l'ensemble aboutissant à une surface 3D qui permet d'appréhender au mieux la structure de l'image. On obtient en quelque sorte un "histogramme topographique"
  • Il devient ainsi possible de mieux pressentir et appréhender de façon intuitive quelles sont les caractéristiques discriminantes d'un objet, d'une couleur en vue d'en extraire simplement l'information utile en reconnaissance visuelle ou en suivi d'objet, sans entrer dans des calculs complexes et pas forcément contributifs, voire même péjoratifs en terme de puissance calcul utilisée.
  • Ici, on procède de la façon suivante :
    • dans Processing, grâce aux fonctions de gestion simplifiée d'une image, on assure l'extraction pour chaque pixels de la valeur soit d'un canal RGB, soit d'une composante HSV. L'ensemble des données est extraite dans 3 fichiers textes : 1 contenant la matrice 1 dimension des pixels X, 1 contenant la matrice 1 dimension des pixels Y, 1 contenant la matrice 2 dimensions de la valeur extraite pour chaque pixel X,Y
    • ensuite, dans Scilab (logiciel libre de calcul mathématique, équivalent Matlab), on utilise les valeurs contenues dans ces 3 fichiers pour réaliser un affichage 3D de la surface ainsi obtenue, avec échelle colorimétrique de visualisation. Le grand intérêt de Scilab est de permettre la manipulation simple de la surface 3D avec notamment adaptation automatique du graphe aux valeurs issues de l'image.
  • Que du bon, et 100% logiciels libres et open-source !

Matériel et configuration utilisés

  • PC Intel Core Quad 2.33 Ghz
  • Ubuntu 10.04 LTS
  • Processing 1-5
  • Scilab 5.2

Ressources utiles

Procédure

Processing

  • Copier/coller le programme dans Processing et l'enregistrer.
  • Copier un fichier image de votre choix dans le répertoire du programme en le nommant monimage.jpg
  • Mettez à jour le chemin voulu pour les fichiers des matrices

Scilab

  • Ouvrir Scilab et lancer l'éditeur (Menu Scilab : Applications > Editeur)
  • Mettre à jour les chemins des fichiers en fonction de votre cas personnel
  • Lancer le script (Menu Exécuter > Lancer sans Scilab)
  • Manipuler la figure obtenue avec l'outil 3D :
    • notamment en vue de face vous reconnaîtrez l'empreinte de l'image de départ
    • repérer les caractéristiques des zones à analyser

Renouvelez à plusieurs reprises la procédure en modifiant le paramètre à extraire de l'image en modifiant la chaine utilisée pour la fonction matriceForScilab() : vous verrez apparaître des caractéristiques de l'image insoupçonnées.

Exemple de résultat obtenu

IMPORTANT : Les couleurs utilisées pour la représentation 3D ne sont que le reflet de l'altitude d'un point sur la surface, mais n'ont aucun lien avec les couleurs réelles de l'image, si ce n'est la valeur absolue de la grandeur mesurée.

Image de départ

Canal bleu

Canal rouge

Saturation

Teinte

  • L'exemple présenté ici met en évidence, en ce qui concerne la peau :
    • une teinte basse centrée autour du 0 (rouge)
    • une prédominance de rouge également
    • une saturation moyenne basse
    • un canal bleu peu discriminant
  • En se basant sur cette analyse, on pourra mettre en place un algorithme de détection de peau particulièrement ciblé, qui de plus prend en compte les caractéristiques intrinsèque du capteur utilisé.

Le programme Processing


// Programme processing
// généré avec le générateur de code Processing
// du site www.mon-club-elec.fr
// par X. HINAULT - tous droits réservés

// Programme écrit le : 7/9/2011.

// ------- Licence du code de ce programme : GPL v3-----
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License,
//  or any later version.
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

/////////////// Description du programme ////////////

// XXXXXXXXXXXXXXXXXXXXXX ENTETE DECLARATIVE XXXXXXXXXXXXXXXXXXXXXX

// inclusion des librairies utilisées

// déclaration objets

PImage img1, img2; // déclare un/des objets PImage (conteneur d'image)

//---- pour écriture dans fichier texte
PrintWriter outputX = null; // initialise un objet PrintWriter pour stocker le flux de donnée à écrire dans le fichier
String cheminAbsoluFichierX="/home/hinault/Bureau/trans/x.txt";
// le fichier doit exister - chemin entier obligatoire

PrintWriter outputY = null; // initialise un objet PrintWriter pour stocker le flux de donnée à écrire dans le fichier
String cheminAbsoluFichierY="/home/hinault/Bureau/trans/y.txt";
// déclaration variables globales

PrintWriter outputZ = null; // initialise un objet PrintWriter pour stocker le flux de donnée à écrire dans le fichier
String cheminAbsoluFichierZ="/home/hinault/Bureau/trans/z.txt";
// déclaration variables globales

float xf, yf, zf;

// XXXXXXXXXXXXXXXXXXXXXX  Fonction SETUP XXXXXXXXXXXXXXXXXXXXXX

void setup(){ // fonction d'initialisation exécutée 1 fois au démarrage


        // ---- initialisation paramètres graphiques utilisés
        colorMode(HSB, 512,255,255); // fixe format couleur HSB (ou V) (Hint (Teinte) - Saturation - Brightness (ou Value) - pour bascule facile RGB
        // (dans Gimp H de -180 à +180, S de -100 à +100 et V(ou B) de -100 à + 100)
        fill(0,0,255); // couleur remplissage RGB
        stroke (0,0,0); // couleur pourtour RGB
        rectMode(CORNER); // origine rectangle : CORNER = coin sup gauche | CENTER : centre
        imageMode(CORNER); // origine image : CORNER = coin sup gauche | CENTER : centre




// --- initialisation des objets et fonctionnalités utilisées ---

//---- Initialisation des objets PImage ---

        //img1 = createImage(100, 100, RGB); // initialise l'objet PImage (conteneur d'image)
        //image(img1, 0, 0, width/2, height/2); // affiche l'image

        img2 = loadImage("monimage.jpg"); // charge un fichier image dans l'objet PImage (conteneur d'image)
        //img2 = loadImage("hands.jpg"); // charge un fichier image dans l'objet PImage (conteneur d'image)
        // ce fichier doit être présent dans un rép <data> dans le répertoire du programme

        // --- initialisation fenêtre de base ---
        size(img2.width, img2.height); // ouvre une fenêtre xpixels  x ypixels
        frameRate(30);
        background(0,0,0); // couleur fond fenetre

        image(img2, 0, 0);// affiche l'image

         matriceForScilab( img2, "Hue"); // appelle fonction de créations fichiers texte valeurs pixels
         //"Red" pour canal rouge , Blue pour canal bleu, Green pour vert (green)
         // "Hue" pour la teinte (hue), "Sat" pour la saturation et "Bri" pour la luminosité (brightness)


} // fin fonction Setup

// XXXXXXXXXXXXXXXXXXXXXX Fonction Draw XXXXXXXXXXXXXXXXXXXX

void  draw() { // fonction exécutée en boucle

         delay(10000); // garde l'image affichée 10 secondes
        exit(); // stoppe le programme

        // while(true); // stoppe boucle draw

} // fin de la fonction draw()

// XXXXXXXXXXXXXXXXXXXXXX Autres Fonctions XXXXXXXXXXXXXXXXXXXXXX

//--- fonction matriceForScilab ---

void matriceForScilab( PImage imgIn, String strIn){

  // cette fonction crée 3 fichiers texte : 1 matrice des x, une matrice de y et 1 matrice 2 dimensions avec valeurs pixels
  // le String strIN est utilisé pour fixer la grandeur extraite de l'image :
  // "Red" pour canal rouge , Blue pour canal bleu, Green pour vert (green)
  // "Hue" pour la teinte (hue), "Sat" pour la saturation et "Bri" pour la luminosité (brightness)

     //----- crée le fichier matrice des x - contient les n valeurs de x dans 1 colonne

        //----- ouvre le fichier de datalogging texte ---
       outputX=ouvreFichier(cheminAbsoluFichierX);   // ouvre le fichier existant dans un PrintWriter
        //le fichier doit exister - chemin entier obligatoire

       outputX.println("------------ Matrice x -------------"); // Ajoute la ligne au fichier

      for (float xf=0; xf<imgIn.width; xf=xf+1) { // défile les valeurs
      //for (float xf=imgIn.width-1; xf>=0; xf=xf-1) { // défile les valeurs à l'envers pour image ok dans Scilab

       //---- valeur de x ---    
       outputX.println(xf); // Ecrit la valeur dans le fichier + saut ligne

      }

       outputX.println(); // Ajoute saut de ligne de fin de fichier

      outputX.flush(); // Ecrit les données du PrintWriter dans le fichier
      println("Ecriture données X OK.");

     //----- crée le fichier matrice des y - contient les n valeurs de y dans 1 colonne

        //----- ouvre le fichier de datalogging texte ---
       outputY=ouvreFichier(cheminAbsoluFichierY);   // ouvre le fichier existant dans un PrintWriter
        //le fichier doit exister - chemin entier obligatoire

       outputY.println("------------ Matrice y -------------"); // Ajoute la ligne au fichier

      for (float yf=0; yf<imgIn.height; yf=yf+1) { // défile les valeurs

       //---- valeur de y ---    
       outputY.println(yf); // Ecrit la valeur dans le fichier + saut ligne

      }

       outputY.println(); // Ajoute saut de ligne de fin de fichier

      outputY.flush(); // Ecrit les données du PrintWriter dans le fichier
      println("Ecriture données Y OK.");

     //----- crée le fichier matrice des z=f(x,y) ----

       //----- ouvre le fichier de datalogging texte ---
       outputZ=ouvreFichier(cheminAbsoluFichierZ);   // ouvre le fichier existant dans un PrintWriter
        //le fichier doit exister - chemin entier obligatoire

       outputZ.println("------------ Matrice Fonction z=f(x,y) -------------"); // Ajoute la ligne au fichier

       //--- fait défiler les x à l'intérieur des y pour avoir matrice de la forme
       //      x1  x2  x3  ...  xn
       //  y1  z11 z21 z31  ...
       //  y2
       //  y3  

       imgIn.loadPixels(); // charge en mémoire les pixels de l'image


      //for (float xf=0; xf<imgIn.width; xf=xf+1) { // défile les valeurs
      for (float xf=imgIn.width-1; xf>=0; xf=xf-1) { // défile les valeurs à l'envers pour image ok dans Scilab

        for (float yf=0; yf<imgIn.height; yf=yf+1) { // défile les valeurs


           //--- valeur de z ---


           //---- RGB ---
           if (strIn=="Red") zf=red(imgIn.pixels[int(xf + (yf *  imgIn.width))]); // extraction valeur canal rouge pixel
           if (strIn=="Green") zf=green(imgIn.pixels[int(xf + (yf *  imgIn.width))]); // extraction valeur canal vert pixel
           if (strIn=="Blue") zf=blue(imgIn.pixels[int(xf + (yf *  imgIn.width))]); // extraction valeur canal bleu pixel

           // --- HSB ----
           if (strIn=="Hue") zf=hue(imgIn.pixels[int(xf + (yf *  imgIn.width))]); // extraction valeur teinte pixel
           if (strIn=="Sat") zf=saturation(imgIn.pixels[int(xf + (yf *  imgIn.width))]); // extraction valeur teinte pixel
           if (strIn=="Bri") zf=brightness(imgIn.pixels[int(xf + (yf *  imgIn.width))]); // extraction valeur teinte pixel

           outputZ.print(zf); // Ecrit la valeur dans le fichier
           outputZ.print("  "); // TAB entre 2 valeurs

        } // fin for yf

           outputZ.println(); // Ajoute saut de ligne entre 2 défilement des x


      } // fin for xf


      outputZ.println(); // Ajoute saut de ligne de fin de fichier

      outputZ.flush(); // Ecrit les données du PrintWriter dans le fichier
      println("Ecriture données Z OK.");

} // fin fonction matrice pour Scilab


//----- Fonction ouvre Fichier---

PrintWriter ouvreFichier( String cheminAbsoluFichier) {

// ouvre le fichier existant dans un PrintWriter- le fichier doit exister - chemin entier obligatoire
// adapté de la source suivante : http://processing.org/discourse/yabb2/YaBB.pl?num=1267767630

       PrintWriter pw=null;

       try //obligé ici...
       {
       // ouvre le fichier existant - le fichier doit exister - chemin entier obligatoire
       pw = new PrintWriter(new BufferedWriter(new FileWriter(cheminAbsoluFichier, false))); // true means: "append", // false = efface
       }

       catch (IOException e)
       {
       // Report problem or handle it
       }

       return (pw); // renvoie l'objet pw

} // fin de ouvreFichier

//XXXXXXXXXXXXXXXXXX Fin du programme XXXXXXXXXXXXXXXXX
 

Le programme Scilab


// affiche la courbe à partir données issues de 3 fichiers
// 1 fichier pour le vecteur d'abscisses x
// 1 fichier pour le vecteur d'ordonnées y
// 1 fichier pour la matrice 2 dimensions avec valeur z pour chaque point x,y

// par X. HINAULT - Septembre 2011
// tous droits réservés - www.mon-club-elec.fr
// licence GPL v3

//--- fichiers à utiliser ---
chemin='/home/hinault/Bureau/trans/'; // le chemin système absolu

matX=fscanfMat(chemin+'x.txt'); // récupère la matrice x à partir du fichier - %lg pour format double
matY=fscanfMat(chemin+'y.txt'); // récupère la matrice y à partir du fichier - %lg pour format double

matZ=fscanfMat(chemin+'z.txt'); // récupère la matrice z=f(x,y) à partir du fichier - %lg pour format double

//-- initialisation graphique

clf(); // efface la figure

xset('colormap', jetcolormap(32)); // définit le code couleur à utiliser avec plot3D1

//----- définition des matrices de tracé ---

x=matX(:,1); // récupère la première colonne de la matrice

y=matY(:,1); // récupère la  première colonne de la matrice

z=matZ; // récupère la matrice à 2 dimensions X  x Y (x en colonnes, y en lignes)


//---- tracé 3D ---

//subplot(1, 2, 1)
//grayplot(x, y, z)

//subplot(1, 2, 2)
//plot3d(x,y,z); // tracé de la courbe 3D - alpha=45 et theta=35 par défaut
plot3d1(x,y,z); // tracé de la courbe 3D - avec code couleur voulu

//--- pour tracé sans pourtour
e=gce();
e.color_flag=1;
e.color_mode=-1; // pour effacer les pourtour des mailles


draw(gca()); //draw the current axes and its children