Logo Mon Club Elec

Processing – ARToolkit : Test simple de la détection d’un marker à partir d’un flux vidéo webcam.

Processing et ARToolkit sont des outils puissants qui permettent aux développeurs de créer des applications interactives et des expériences immersives. Dans ce tutoriel, nous allons vous montrer comment utiliser Processing et ARToolkit pour tester la détection d’un marker à partir d’un flux vidéo webcam. Nous allons vous guider pas à pas à travers le processus de configuration et de développement, et vous expliquer comment utiliser les fonctionnalités de Processing et ARToolkit pour créer une application de détection de marker.

Processing – ARToolkit : Test simple de la détection d’un marker à partir d’un flux vidéo webcam.

Par X. HINAULT – 13 Février 2012

Processing – ARToolkit : Test simple de la détection d’un marker à partir d’un flux vidéo webcam.

Explication

  • Ce programme pose les bases de l’utilisation de ARToolkit avec Processing à l’aide de la librairie nyar4psg.
  • On réalise ici :
    • la capture d’un flux vidéo avec la librairie GSVideo
    • à chaque nouvelle frame, on réalise la détection détection d’un marker parmi 3 ou 4 prédéfinis (les fichiers doivent être présents sur votre machine)

Matériel et configuration utilisés

  • PC Intel Core Quad 2.33 Ghz
  • Webcam(s) USB C270
  • Ubuntu 10.04 LTS
  • Processing 1-5
  • Librairie GSVideo 0.9
  • nyar4psg 1.1.7

Ressources utiles

Le programme

// Programme processing
// par X. HINAULT – tous droits réservés
// inspired from : // Augmented Reality Basic Example by Amnon Owed (21/12/11)

// Programme écrit le : 10/01/2012.

// ——- 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 ////////////
// Utilise la librairie GSVideo de capture et lecture vidéo

// XXXXXXXXXXXXXXXXXXXXXX ENTETE DECLARATIVE XXXXXXXXXXXXXXXXXXXXXX

// inclusion des librairies utilisées

import codeanticode.gsvideo.*; // importe la librairie vidéo GSVideo qui implémente GStreamer pour Processing (compatible Linux)
// librairie comparable à la librairie native vidéo de Processing (qui implémente QuickTime..)- Voir Reference librairie Video Processing
// cette librairie doit être présente dans le répertoire modes/java/libraries du répertoire Processing (1-5)
// voir ici : http://gsvideo.sourceforge.net/
// et ici : http://codeanticode.wordpress.com/2011/05/16/gsvideo-09-release

import java.io.*; // pour le chargement des fichiers descriptifs des « patterns »

import processing.opengl.*; // pour rendu 3D avec la librairie OPenGL

import jp.nyatla.nyar4psg.*; // La librairie NyARToolkit Processing library = ARToolKit pour Processing
// Cette librairie permet de détecter des « pattern » ou « marker » dans une image
// et d’analyser leur transformation de perspective
// nyAR4psg est à télécharger ici : http://sourceforge.jp/projects/nyartoolkit/releases/
// et à mettre dans le répertoire des librairies

//—– chemin absolu fichier de paramètres de distorsion de la camera —-
//String camParaPath = « /home/hinault/Téléchargements/librairies_processing/nyar4psg-1.1.6/data/camera_para.dat »;
String camParaPath = « /home/hinault/Téléchargements/processing-1.5/modes/java/libraries/NyAR4psg/data/camera_para.dat »;

//—– chemin absolu fichiers de description des « patterns » ou « markers » —-
String patternPath = « /home/hinault/Téléchargements/patternMaker/examples/ARToolKit_Patterns »;

// déclaration objets
GSCapture cam1; // déclare un objet GSCapture représentant une webcam

PImage imgSrc, imgAR; // Objets PImages utiles

// déclaration variables globales

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

//— taille de l’image webcam —
int widthCapture= 640;
int heightCapture=480;

//— taille de l’image à utiliser pour la détection = plus petite pour plus rapide —
int widthAR= 640;
int heightAR=480;

int numMarkers = 3; // le nombre de pattern markers à utiliser
String[] nameMarkers= new String[numMarkers]; // pour mémoriser le nom des marker

MultiMarker nya; // déclaration de l’objet principal pour reconnaissance « markers »

float displayScale; // échelle d’affichage

// 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(0,0,255); // couleur remplissage RGB – noFill() si pas de remplissage
        stroke (0,0,0); // couleur pourtour RGB – noStroke() si pas de pourtour
        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(20);// Images par seconde – The default rate is 60 frames per second

        // — initialisation fenêtre de base —
        size(widthCapture, heightCapture); // ouvre une fenêtre xpixels  x ypixels
        background(bleu); // couleur fond fenetre

        //—- initialisation police utilisée —-
        textFont(createFont(« Arial », 80)); // police utilisée

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

        //======== Initialisation Objets GSVideo (capture et/ou lecture video =========

        //GSCapture(this, int requestWidth, int requestHeight, [int frameRate], [String sourceName], [String cameraName])
        // cam1 = new GSCapture(this, width, height,20, »v4l2src », »/dev/video0″); // Initialise objet GSCapture désignant webcam – avant GSVideo 1.0
        cam1 = new GSCapture(this, widthCapture, heightCapture,« v4l2src »,« /dev/video0 », 20); // Initialise objet GSCapture désignant webcam – depuis GSVideo 1.0
        // largeur et hauteur doivent être compatible avec la webcam – typiquement 160×120 ou 320×240 ou 640×480…
        // NB : Framerate >=20 évite message erreur

        // cam1.play();  // démarre objet GSCapture = la webcam – version GSVideo avant 0.9
        cam1.start();  // démarre objet GSCapture = la webcam – version GSVideo après 0.9

        //pipe = new GSPipeline(this, « gnomevfssrc location=http://192.168.1.118/axis-cgi/mjpg/video.cgi?resolution=640×480 ! jpegdec ! ffmpegcolorspace »);
        //pipe = new GSPipeline(this, « gnomevfssrc location=http://88.167.252.72:2203/video.mjpg ! jpegdec ! ffmpegcolorspace »);
        //pipe = new GSPipeline(this, « gnomevfssrc location=http://88.167.252.72:2203/video.mjpg ! jpegdec ! ffmpegcolorspace ! autovideosink »);
        //pipe = new GSPipeline(this, « souphttpsrc location=http://88.167.252.72:2203/video.mjpg ! jpegdec ! ffmpegcolorspace ! autovideosink »);

        // http://88.167.252.72:2203/video.mjpg
        // « 88.167.252.72:2203 » tu peux l’administrer avec « admin » et « 220369 »

        //=========== initialisation détection des markers =========================

        // création d’un objet MultiMarker avec résolution voulue, les paramètres caméra et le système de coordonnées voulu
        nya = new MultiMarker(this, widthAR, heightAR, camParaPath, NyAR4PsgConfig.CONFIG_DEFAULT);

        // fixe le nombre de fois qu’un marqueur ne doit plus petre détecté pour ne plus l’afficher.
        //Par défaut = 10. Mettre à 1 pour visualisation immédiate
        nya.setLostDelay(1);

        // fixe le niveau de seuil de détection à utiliser. Valeur possible entre 0 et 255. Mettre -1 (=THLESHOLD_AUTO) pour seuil automatique
        nya.setThreshold(MultiMarker.THLESHOLD_AUTO);

        // fixe le niveau de seuil de confiance (= probabilité de correspondance) à utiliser pour la reconnaissance des markers. Valeur possible entre 0 et 1.
        // Valeur par défaut = 0.51 (=.DEFAULT_CF_THRESHOLD). Plus le seuil est élevé et plus la détection est rigoureuse.
        nya.setConfidenceThreshold(MultiMarker.DEFAULT_CF_THRESHOLD);
        //nya.setConfidenceThreshold(0.8); // sélection exigeante

        //– chargement des fichiers de description des patterns
/*
        String[] patterns = loadPatternFilenames(patternPath); // tableau pour des noms des fichiers des pattern retrouvés dans le répertoire

        println (« ——- Liste des fichiers trouvés ————« );

        for (int i=0; i<patterns.length; i++) { // défile le tableau des noms de fichiers

          println («  » + i + « : » + patterns[i]);

        } // fin for
*/

        //— pour charger n fichiers à la suite ..
        //for (int i=0; i<numMarkers; i++) {

          //nya.addARMarker(patternPath + « / » + patterns[i], 80); // ajoute le fichier de description à l’objet principal de détection AR

        //} // fin for

        //— pour chargement manuel des fichiers voulus
        int widthMarker=135; // taille réelle du marker utilisé en mmm
        //int sizeMarker=16; // résolution du marker – 16×16 par défaut – utiliser 16×16
        //int borderMarker=25; // largeur du bord du marker – 25% par défaut

        // nya.addARMarker(patternPath + « / » + patterns[40], 80); // ajoute le fichier de description à l’objet principal de détection AR
        //nameMarkers[0]= patterns[40]; // mémorise le nom du marker [i]
        nameMarkers[0]= « 4x4_99.patt »; // mémorise le nom du fichier du marker voulu
         nya.addARMarker(patternPath + « / » + nameMarkers[0], widthMarker); // ajoute le fichier de description à l’objet principal de détection AR – bordure 25% et 16×16 par défaut
        //nya.addARMarker(patternPath + « / » + nameMarkers[0], sizeMarker, widthMarker); // ajoute le fichier de description à l’objet principal de détection AR – 16×16 par défaut
        //nya.addARMarker(patternPath + « / » + nameMarkers[0],sizeMarker,borderMarker, widthMarker); // ajoute le fichier de description à l’objet principal de détection AR
        println (« Fichier chargé : «  + nameMarkers[0]);

        //nya.addARMarker(patternPath + « / » + patterns[83], 80); // ajoute le fichier de description à l’objet principal de détection AR
        //nameMarkers[1]= patterns[83]; // mémorise le nom du marker [i]
        nameMarkers[1]= « 4x4_50.patt »; // mémorise le nom du fichier du marker voulu
        nya.addARMarker(patternPath + « / » + nameMarkers[1] , widthMarker); // ajoute le fichier de description à l’objet principal de détection AR
        //nya.addARMarker(patternPath + « / » + nameMarkers[1] , sizeMarker,widthMarker); // ajoute le fichier de description à l’objet principal de détection AR
        //nya.addARMarker(patternPath + « / » + nameMarkers[1] , sizeMarker,borderMarker,widthMarker); // ajoute le fichier de description à l’objet principal de détection AR

        println (« Fichier chargé : «  + nameMarkers[1]);

        //nya.addARMarker(patternPath + « / » + patterns[99], 80); // ajoute le fichier de description à l’objet principal de détection AR
        //nameMarkers[2]= patterns[99]; // mémorise le nom du marker [i]
        nameMarkers[2]= « 4x4_83.patt »; // mémorise le nom du fichier du marker voulu
        nya.addARMarker(patternPath + « / » + nameMarkers[2], widthMarker); // ajoute le fichier de description à l’objet principal de détection AR
        //nya.addARMarker(patternPath + « / » + nameMarkers[2], sizeMarker,widthMarker); // ajoute le fichier de description à l’objet principal de détection AR
        //nya.addARMarker(patternPath + « / » + nameMarkers[2], sizeMarker,borderMarker,widthMarker); // ajoute le fichier de description à l’objet principal de détection AR
        println (« Fichier chargé : «  + nameMarkers[2]);

        //noLoop();

} // fin fonction Setup

// XXXXXXXXXXXXXXXXXXXXXX Fonction Draw XXXXXXXXXXXXXXXXXXXX

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

// Code type capture GSVideo – préférer utilisation de captureEvent()

  if (cam1.available() == true) { // si une nouvelle frame est disponible

    cam1.read(); // acquisition d’un frame

    image(cam1, 0, 0); // affiche image
    //set(0, 0, cam); // plus rapide

    println(« debut= »+millis());

    println(« seuil de binarisation actuel = «  + nya.getCurrentThreshold());

    nya.detect(cam1); // detection des markers dans l’image à la résolution voulue
    // l’image passée en paramètre doit avoir la même résolution que ce qui a été défini à l’initialisation du constructeur

    drawMarkers(); // dessiner les coordonnées des « markers » détectés

    //nya.drawBackground(cam1);
    //image(cam1, 0, 0); // affiche image

    println(« fin= »+millis());

  } // fin if available

/*
  if (pipe.available() == true) { // si une nouvelle frame est disponible
    pipe.read(); // acquisition d’un frame
    image(pipe, 0, 0); // affiche image
    //set(0, 0, cam); // plus rapide

  } // fin if available
*/

} // fin de la fonction draw()

// XXXXXXXXXXXXXXXXXXXXXX Autres Fonctions XXXXXXXXXXXXXXXXXXXXXX

//———- fonction de dessin de tous les markers détectés

void drawMarkers() {

    // paramètres affichage texte
    textAlign(LEFT, TOP); // paramètre d’affichage du texte
    textSize(10); // taille à utiliser pour le texte

    // — paramètre graphique
    noStroke();

     // scale from AR detection size to sketch display size (changes the display of the coordinates, not the values)
    //scale(displayScale);

    // for all the markers…
    for (int i=0; i<numMarkers; i++) { // passe en revue les markers de référence

      // if the marker does NOT exist (the ! exlamation mark negates it) continue to the next marker, aka do nothing
      if ((!nya.isExistMarker(i))) { continue; }

      // passe au marker suivant si le marker(i) n’est pas détecté

      // the following code is only reached and run if the marker DOES EXIST

       println (« Le marker «  + nameMarkers[i] +  » est détecté. »);

       println(« seuil de confiance = «  + nya.getConfidence(i)); // affiche le seuil de confiance de détection

       // get the four marker coordinates into an array of 2D PVectors
        PVector[] pos2d = nya.getMarkerVertex2D(i);

        // draw each vector both textually and with a red dot
        for (int j=0; j<pos2d.length; j++) {

          String s = « («  + int(pos2d[j].x) + « , » + int(pos2d[j].y) + « ) »;
          fill(255);
          rect(pos2d[j].x, pos2d[j].y, textWidth(s) + 3, textAscent() + textDescent() + 3);
          fill(0);
          text(s, pos2d[j].x + 2, pos2d[j].y + 2);
          fill(0, 0, 255);
          ellipse(pos2d[j].x, pos2d[j].y, 10, 10);

        } // fin for pos2d

      } // fin if numMarker

} // — fin draw Markers —

//——— fonction loadPatternFilesnames() : charge l’ensemble des fichiers *.patt du répertoire
// this function loads .patt filenames into a list of Strings based on a full path to a directory (relies on java.io)
String[] loadPatternFilenames(String path) {

    File folder = new File(path);
    FilenameFilter pattFilter = new FilenameFilter() {

      public boolean accept(File dir, String name) {

        return name.toLowerCase().endsWith(« .patt »);
      }

    }; // fin filenameFilter

     return folder.list(pattFilter); // renvoi le tableau de String

} // fin loadPatternFilenames

/*
//— évènement capture vidéo —
void captureEvent(GSCapture cam) { // est appelée lorsqu’une capture survient
// cf doc librairie Video Processing – cf exemple Capture LivePocky

   // est appelée à chaque fois qu’une nouvelle frame est disponible, quelque soit la caméra
   // utiliser des conditions pour tester la caméra disponible

  if (cam1.available() == true) cam1.read(); // acquisition d’une nouvelle frame

*/

//————- Fonction d’arret de Processing —-

public void stop(){ // fonction d’arrêt de Processing

        //pipe.delete(); // efface l’objet GScapture
        cam1.delete();

        super.stop(); // obligatoire

} // fin fonction stop()

//XXXXXXXXXXXXXXXXXX Fin du programme XXXXXXXXXXXXXXXXX

 

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é.