Logo Mon Club Elec

Processing – openCV : Suivi de balle colorée avec élimination des artéfacts par calcul de cohérence des paramètres de l’objet détecté.

http://web.archive.org/web/20210804223007/https://www.mon-club-elec.fr/pmwiki_mon_club_elec/pmwiki.php?n=MAIN.ArduinoExpertCapteursComplexesDS18B20

Le traitement d’image et le suivi de balle colorée sont des domaines qui ont connu une croissance exponentielle ces dernières années. Les algorithmes de traitement d’image sont de plus en plus sophistiqués et leurs applications sont de plus en plus variées. Dans cet article, nous allons nous intéresser à l’utilisation de Processing et openCV pour le suivi de balle colorée avec élimination des artéfacts par calcul de cohérence des paramètres de l’objet détecté. Nous verrons comment ces technologies peuvent être utilisées pour améliorer la précision et la fiabilité du suivi de balle colorée.

Processing – openCV : Suivi de balle colorée avec élimination des artéfacts par calcul de cohérence des paramètres de l’objet détecté.

Explication

  • Ce programme est une amélioration du programme Processing Suivi de balle colorée (tracking colored ball) avec OpenCV dans Processing
  • Ici, le but est d’éliminer les artéfacts colorés détectés mais qui ne correspondent pas à l’objet détecté. En fait, la librairie openCV donne accès à la fois au rectangle contenant l’objet détecté et l’aire de l’objet détecté. D’où l’idée d’une double analyse de l’objet détecté :
    • que le rectangle soit proche du carré
    • que la surface de l’objet détecté sur la surface du carré contenant soit compatible avec la détection d’un cercle (ratio = pi/4 théorique, 0.5 en pratique)
  • En utilisant ce double contrôle, les artéfacts sont éliminés à 90 % donnant un très bon suivi de balle.

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 – Avril 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

// ce programme réalise tout d’abord un traitement détecter l’objet de couleur voulu
// puis on utilise un calcul du ratio de l’aire de la forme / aire rectangle contenant
// pour améliorer la discrimination de l’objet
// le suivi d’objet final obtenu est très bon et les formes « aberrantes » sont ignorées

// 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/

import java.awt.Rectangle;
// impporte l’objet rectangle du langage Java qui est utilisé par certaines fonction de la librairie openCV
// l’objet rectangle fournit les champs x,y du centre et hauteur/largeur (height/width) du rectangle
// voir ici : http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Rectangle.html

// 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
        ellipseMode(CENTER); // origine cercles / ellipses : CENTER : centre (autres : RADIUS, CORNERS, CORNER
        //strokeWeight(0); // largeur pourtour
        frameRate(30);// Images par seconde
        smooth(); // lissage des formes

        // — 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
            //———- le traitement le plus efficace qui fonctionne est à tester dans Gimp au préalable
            //——— ici réglage pour balle de couleur orangée —-

          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
        // à adapter en fonction de la luminosité ambiante – plus sombre, valeur 0.7, plus lumineux, valeur 0.8 ou plus  

        //— 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

       // xxxxxxxxxxxx Analyse et gestion des formes reconnues xxxxxxxxxxxxxx
      for( int i=0; i<blobs.length; i++ ) { // passe en revue les blobs (= formes détectées)

      //—- détection du « centre » de l’objet —-
      int centreX= blobs[i].centroid.x; // centroid renvoie un objet Point qui fournit x et y
      int centreY= blobs[i].centroid.y; // centroid renvoie un objet Point qui fournit x et y

      /*
      //———- dessine un cercle autour du centre détecté ———–
      noFill();
      stroke(vert);
      strokeWeight(2);
      ellipse (centreX,centreY, 10,10);
      */

       Rectangle rectangleBlob=blobs[i].rectangle; // récupère le rectangle qui contient la forme détectée

       //—- analyse du rectangle objet —-
       int ratioWH=rectangleBlob.width/rectangleBlob.height; // calcule le ratio largeur/hauteur
       int ratioHW=rectangleBlob.height/rectangleBlob.width; // calcule le ratio hauteur/largeur

       float aireBlob=blobs[i].area; // récupère l’aire de la forme courante

       float ratioAire=aireBlob/(rectangleBlob.width*rectangleBlob.height); // calcul du ratio Aire forme / Aire rectangle
       // aire cercle = pi * r²
       // aire carré = (2r)²=4r²
       // aire cercle/aire carré = (pi * r²)/ (4*r²) = pi/4 = 3/4 env
       // un cercle occupe 3/4 du carré le contenant

       //if ((ratioWH>0.9)) { // si forme proche du carré
       if ((ratioAire>0.5) && ((ratioWH>0.8) || (ratioHW>0.8))) { // si le rapport de l’aire de la forme / rectangle contenant est compatible avec un cercle
        //fill(jaune); // couleur remplissage RGB
        noFill(); // pas de remplissage
        stroke (bleuclair); // couleur pourtour RGB

        //tracé d’un rectangle autour du blob
        rect( rectangleBlob.x, rectangleBlob.y, rectangleBlob.width, rectangleBlob.height );

       }
       else { // trace avec couleurs différentes les rectangles non souhaités

        fill(bleu); // couleur remplissage RGB
        stroke (jaune); // couleur pourtour RGB

        //tracé d’un rectangle autour du blob
        rect( rectangleBlob.x, rectangleBlob.y, rectangleBlob.width, rectangleBlob.height );

       }

        fill(jaune); // couleur remplissage RGB
        stroke (rouge); // couleur pourtour RGB

        // tracé des formes détectées
        beginShape(); // début tracé forme complexe

        for( int j=0; j<blobs[i].points.length; j++ ) { // parcourt tous les points du pourtour du blob
            vertex( blobs[i].points[j].x, blobs[i].points[j].y ); // tracé des points de la forme
        }
        endShape(CLOSE); // tracé forme complexe

    } // —- fin for blobs ——–

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

} // fin de la fonction draw()

// XXXXXXXXXXXXXXXXXXXXXX Autres Fonctions XXXXXXXXXXXXXXXXXXXXXX

 

Voir ici :

Noter cet article

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Archive Mon Club Elec

Articles populaires

Newsletter

Inscrivez-vous maintenant et bénéficiez d'un soutien continu pour réaliser vos travaux électriques en toute sécurité.