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 |

Suivi de balle colorée (tracking colored ball) avec OpenCV dans Processing

Liens utiles :

Infos sur les couleurs, etc..

Problématique de la détection d'objet dans une image

  • Une des problèmatiques importante ici va être de traiter l'image issue du flux vidéo pour détecter au mieux l'objet suivi, à savoir une balle.
  • Plusieurs fonctions de traitement d'image sont disponibles aussi bien dans Processing que dans la librairie OpenCV
    • avec Processing, voir notamment : blend(), filter(), tint(), colorMode()
    • avec la librairie OpenCV : threshold() (fonction de seuillage), blobs(), blob et aussi copy()
  • La question est de savoir quel traitement appliquer à l'image pour détecter la balle. Le mieux pour définir la procédure est de le faire en manuel dans Gimp à l'aide des outils du menu <couleurs>.

Voici un exemple :

  • Tout d'abord l'image brute :
  • On utilise l'outil Couleur > Auto > Mixeur de Canaux pour modifier les réglages de l'image en passant en monochrome (= niveaux de gris) et on met le rouge à fond, on enlève le bleu et on réduit le vert :
  • Ensuite, on applique l'outil Couleurs > seuil à l'image, ce qui donne :

On dégage bien complètement l'image.

Explication du programme

  • Dans ce programme, on commence par acquérir une image à l'aide de la librairie openCV
  • Ensuite, on bascule cette image dans un objet PImage de Processing à laquelle on applique le traitement montré ci-dessous pour extraire au mieux la balle
  • Une fois l'image traitée, on la recharge dans le buffer OpenCV et on lui applique la reconnaissance de forme.
  • On trace un cercle jaune avec pourtour rouge sur l'objet détecté
  • On refait une capture de l'image brute et on superpose les deux.
  • Tout ceci est réalisé plusieurs fois par seconde ce qui donne un bon tracking de la balle. La balle utilisée est une balle de ping-pong orangée.
  • En situation réelle (lumière du jour, en intérieur), la balle est bien détectée dès 2m50 à 3m de la webcam. Deux balles sont également détectées. Le suivi de la balle est immédiat.
  • Voici le détail de la séquence de traitement réalisée par le programme (l'opération est réalisée plusieurs fois par seconde et est "invisible" au final :
    • Image brute :
  • Mixeur canaux sortie rouge :
  • bascule en monochrome du canal rouge :
  • application d'un seuillage (threshold) :
  • dessin de la forme détectée sur une nouvelle capture brute :

Ressources utiles

  • La librairie openCV

Le programme


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

/////////////// Description du programme ////////////
// Utilise un/des objets PImage (conteneur d'image .jpeg .gif .png et .tga)
// Utilise la librairie OpenCV de capture vidéo et reconnaissance visuelle

// XXXXXXXXXXXXXXXXXXXXXX ENTETE DECLARATIVE XXXXXXXXXXXXXXXXXXXXXX

// inclusion des librairies utilisées

import hypermedia.video.*; // importe la librairie vidéo et reconnaissance visuelle OpenCV
// cette librairie doit être présente dans le répertoire /libraries du répertoire Processing
// voir ici : http://ubaa.net/shared/processing/opencv/

// déclaration objets

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

OpenCV opencv; // déclare un objet OpenCV principal

// déclaration variables globales
int xmin, xmax, ymin, ymax; // coordonnées de la zone à tester


//------ déclaration des variables de couleur utiles ----
int jaune=color(255,255,0);
int vert=color(0,255,0);
int rouge=color(255,0,0);
int bleu=color(0,0,255);
int noir=color(0,0,0);
int blanc=color(255,255,255);
int bleuclair=color(0,255,255);
int violet=color(255,0,255);


// XXXXXXXXXXXXXXXXXXXXXX  Fonction SETUP XXXXXXXXXXXXXXXXXXXXXX

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

        // ---- initialisation paramètres graphiques utilisés
        colorMode(RGB, 255,255,255); // fixe format couleur R G B pour fill, stroke, etc...
        fill(255,255,0); // couleur remplissage RGB
        stroke (255,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
        //strokeWeight(0); // largeur pourtour
        frameRate(30);// Images par seconde

        // --- initialisation fenêtre de base ---
        size(320, 240); // ouvre une fenêtre xpixels  x ypixels
        background(0,0,0); // couleur fond fenetre

// --- 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)
        // ce fichier doit être présent dans le répertoire du programme ou à l'emplacement indiqué
        //image(img2, 0, 0, width, height);// affiche l'image

        //======== Initialisation Objets OpenCV (vidéo et reconnaissance visuelle =========

        opencv = new OpenCV(this); // initialise objet OpenCV à partir du parent This
        opencv.capture(width,height); // initialise capture flux vidéo
        // width et height sont les valeurs de la taille de la fenêtre processing



} // fin fonction Setup

// XXXXXXXXXXXXXXXXXXXXXX Fonction Draw XXXXXXXXXXXXXXXXXXXX

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


        opencv.read(); // lecture flux vidéo via OpenCV

        img1=opencv.image(); // récupère Image opencv dans Processing

        //traitement de l'image de capture openCV dans Processing

        image( img1, 0, 0 );   // affichage image video

        //----- 1°) application du "mixeur de canaux" avec sortie sur canal Rouge
            //---- coeff à appliquer
            float coefRouge=1; // 100% de rouge
            float coefVert=1.5; // 80% du vert
            float coefBleu=-2; // - 200% du bleu


          loadPixels(); // charge les pixels de la fenetre d'affichage

          for (int i = 0; i < width*height; i++) { // passe en revue les pixels de l'image - index 0 en premier

            float r = (red(pixels[i])) + (green(pixels[i])*coefVert) + (blue(pixels[i])*coefBleu); // la couleur rouge
            //---- fonction mixeur de canaux
            //---- le canal rouge est le canal de sortie et a pour coeff 1
            //---- auquel on ajoute du vert avec coeff vert
            //---- et du bleu avec coeff bleu

            // les deux autres canaux restent inchangés
            float g = green(pixels[i]); // la couleur verte

            float b = blue(pixels[i]); // la couleur bleue

             pixels[i] = color(r, g, b); // modifie le pixel en fonction

            }

          updatePixels();  // met à jour les pixels  

        //----- 2°) transformation de l'image en monochrome en se basant sur le canal rouge

          loadPixels(); // charge les pixels de la fenetre d'affichage

          for (int i = 0; i < width*height; i++) { // passe en revue les pixels de l'image - index 0 en premier

            float r = red(pixels[i]);// la couleur rouge
            float g = red(pixels[i]); // la couleur verte

            float b = red(pixels[i]); // la couleur bleue

             pixels[i] = color(r, g, b); // modifie le pixel en fonction

            }

          updatePixels();  // met à jour les pixels  

        //------ on applique filtre de seuillage ---
        filter(THRESHOLD,0.7); // applique filtre seuil à la fenetre d'affichage

        //--- on récupère l'image transformée ---
        img2=get(0,0,width,height); // récupère image à partir fenetre d'affichage


        //--- on rebascule dans OpenCV ---
        opencv.copy(img2); // charge l'image modifiée dans le buffer opencv

        // trouve les formes à l'aide de la librairie openCV
        // blobs(minArea, maxArea, maxBlobs, findHoles, [maxVertices]);
        Blob[] blobs = opencv.blobs( 10, width*height/4, 5, false, OpenCV.MAX_VERTICES*4 );

        // recharge image vidéo non traitée
        opencv.read(); // lecture flux vidéo via OpenCV
        noTint();
        image( opencv.image(), 0, 0 );   // affichage image video


       // draw blob results
      for( int i=0; i<blobs.length; i++ ) { // passe en revue les blobs

        // tracé des formes détectées
        beginShape(); // début tracé forme complexe
        for( int j=0; j<blobs[i].points.length; j++ ) {
            vertex( blobs[i].points[j].x, blobs[i].points[j].y ); // tracé des points de la forme
        }
        endShape(CLOSE); // tracé forme complexe
    }



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

} // fin de la fonction draw()

// XXXXXXXXXXXXXXXXXXXXXX Autres Fonctions XXXXXXXXXXXXXXXXXXXXXX