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

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
// 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
Articles similaires:
- Processing ARToolkit : Second essai utilisant ARToolkit et la réalité augmentée
- Processing ARToolkit : Remplacement du marker par une image en live sur un flux vidéo webcam et détection du repère 3D du marker.
- Processing ARToolkit : Remplacement du marker par une vidéo active en live sur un flux vidéo webcam et détection du repère 3D du marker.
- Processing ARToolkit : Troisième essai utilisant ARToolkit et la réalité augmentée : RGB Cube en lévitation !
- Processing + ARToolkit + JavacvPro : Détection du centre, du type d’un marker à partir d’un flux vidéo webcam.
Articles Liés
- Javascript : Graphique Dygraphs simple
Le Javascript est un langage de programmation très populaire et puissant qui permet aux développeurs…
- Javascript : Afficher 6 widgets graphiques fournis par une librairie graphique externe.
Le Javascript est un langage de programmation très populaire qui permet aux développeurs de créer…
- Javascript : Graphique Dygraphs : afficher date à partir unixtime
Le langage de programmation Javascript est très populaire et est utilisé pour créer des applications…