Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Augmented Reality e FLARToolkit in pratica

Un esempio concreto di realtà aumentata, dalla creazione del marker alla stesura del codice
Un esempio concreto di realtà aumentata, dalla creazione del marker alla stesura del codice
Link copiato negli appunti

Come anticipato nel precedente articolo sul FLAR Toolkit, realizziamo un piccolo esempio pratico di Augmented Reality in Flash. I requisiti per poter ricreare l'esempio sono i seguenti:

  • Il FLAR Toolkit, scaricabile con SVN, nel nostro caso però ci serviremo solo del file SWC, scaricabile direttamente da qui
  • Un software per la generazione del marker, possibile usare un tool online come ARToolKit Marker Generator o l'applicazione AIR creata da Saqoosha, nell'esempio verrà utilizzata quest'ultima
  • Una stampante per poter stampare il nostro marker
  • Papervision3D, che verrà utilizzato per creare gli elementi aggiuntivi (nel nostro esempio saranno 3 semplici cubi)
  • Un editor per creare ed esportare il file MXML, va quindi benissimo il Flash Builder (nuovo nome del Flex Builder, disponibile in beta)
  • Una webcam per creare il marker e poi per testare il risultato finale

Nonostante il numero di requisiti, il codice che regolerà il nostro esempio non sarà moltissimo, anche perchè la maggior parte delle operazioni saranno svolte dal FLAR Toolkit, che si occuperà rilevare la presenza del marker e e calcolarne la posizione nello spazio 3D, questo per fare in modo che l'animazione possa aggiornarsi in tempo reale qualora andassimo a spostare od inclinare il foglio o comunque la superficie su cui si troverà il marker.

Una volta reperiti i componenti necessari, passiamo finalmente a creare il nostro primo esempio pratico di realtà aumentata. Iniziando dalla generazione del pattern.

Creazione del marker

Per creare il marker abbiamo due possibilità: possiamo sfruttare uno dei marker presenti nei vari esempi (ne abbiamo visti alcuni nell'articolo precedente), oppure crearne uno. In entrambi i casi possiamo avvalerci della nostra webcam e di uno dei programmi segnalati tra i requisiti, ovviamente partire da un marker pre-esistente ha il vantaggio di essere sicuri della sua correttezza, d'altro canto però avere un marker personalizzato da sicuramente una miglior impressione anche verso l'utente.

Se pensiamo di creare un marker personalizzato, creiamo in un qualsiasi programma di grafica un quadrato di 8 cm, con il bordo (nero) spesso 4 cm e di conseguenza l'interno (bianco) a sua volta di 4 cm. All'interno dello spazio bianco possiamo inserire una forma di nostro gradimento, ecco un esempio:

Figura 1. Marker personalizzato
Marker creato con PhotoShop

A questo punto possiamo stampare il nostro marker (o stampare uno dei marker degli esempi disponibili online) e aprire l'ARToolKit Marker Generator. Il software è molto semplice, individua i possibili marker nell'immagine catturata dalla webcam, e li evidenzia con un bordo rosso.

Figura 2. Marker stampato e rilevato dal Marker Generator
Marker

Quando la webcam evidenzia il nostro marker, possiamo cliccare sul pulsante Save pattern e salviamo l'immagine nella cartella dove abbiamo precedentemente copiato il file .dat. Ricordiamoci di inserire nella maschera di salvataggio anche l'estensione del file, che può essere ad esempio .pat (nell'esempio abbiamo salvato il marker come patternHTML.pat).

Nelle parti successive, vedremo come effettuare la calibrazione della camera e scriveremo il codice vero e proprio.

Calibrazione della camera

Una volta ottenuto il pattern dobbiamo impostare alcuni parametri per la gestione dei dati della webcam. Questi dati si trovano in un file chiamato camera_para.dat: possiamo generare questo file utilizzando il software ARToolKit, ma se non abbiamo esigenze particolari, possiamo copiare il file presente nella cartella src/Data dell'esempio in allegato.

Questo file può essere tranquillamente riutilizzato e funziona senza problemi, tanto che la maggior parte degli esempi visibili online utilizza questo stesso file .dat.

Preparare il progetto

Finalmente lanciamo l'ambiente di sviluppo, nel nostro caso caso il Flash Builder, dove creiamo un nuovo Actionscript Project (File > New > ActionScript Project).

Figura 3. Creazione di un nuovo Progetto ActionScript
Creazione di un nuovo Progetto ActionScript

Qui scriviamo il nome del progetto e indichiamo la cartella in cui salvare i file (possiamo anche lasciare il percorso di default). Poi clicchiamo su Next.

Nella seconda schermata abbiamo la possibilità di impostare le directory relative alle librerie Actionscript che vogliamo utilizzare nel progetto, nel nostro caso quindi Papervision3D e FlarToolkit. Per maggior comodità aggiungiamo le librerie precompilate (swc), quello di Papervision3D lo troviamo sul sito ufficiale , mentre quello del FLARToolkit è nella cartella bin del repository SVN.

Una volta ottenuti i file li importiamo spostandoci sulla tab Library path e cliccando su Add SWC.

Figura 4. Aggiunta delle librerie precompilate
Aggiunta delle librerie precompilate

Cliccando su Finish, il sistema crea tutti i file del progetto compreso il file ActionScript della classe principale (nel nostro caso Esempio_Flar.as).

Il codice

È il momento di iniziare a scrivere qualche riga di codice, non molto in realtà: il grosso del lavoro sarà svolto dalle librerie.

Aprendo il file Esempio_Flar.as, vediamo che è stata già dichiarata la classe.

package
{
  import flash.display.Sprite;
  
  public class esempio_flar extends Sprite
  {
    public function esempio_flar() {  }
  }
} 

Per iniziare scriviamo gli import delle classi di FLAR e Papervision. Inoltre avremo bisogno anche delle classi di Flash per gestire la webcam e per analizzare il marker.

// Importa le classi native 
//  BitmapData, ByteArray - analisi del pattern
//  Camera, Video         - visualizzazione della webcam
//  Event                 - gestione degli eventi inviatida FLAR
import flash.display.BitmapData;
import flash.utils.ByteArray;
import flash.media.Camera;
import flash.media.Video;
import flash.events.Event;

// Importa le classi del FLARToolkit
import org.libspark.flartoolkit.core.FLARCode;
import org.libspark.flartoolkit.core.param.FLARParam;
import org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData;
import org.libspark.flartoolkit.core.transmat.FLARTransMatResult;
import org.libspark.flartoolkit.detector.FLARSingleMarkerDetector;
import org.libspark.flartoolkit.pv3d.FLARBaseNode;
import org.libspark.flartoolkit.pv3d.FLARCamera3D;

// Importa le classi di Papervision3D
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;

All'interno della classe creiamo le proprietà necessarie ad incorporare, nel nostro SWF, i file necessari alla calibrazione della webcam (camera_para.dat) e alla definizione del pattern (patternHTML.pat). Per farlo creiamo una variabile di riferimento relativa al marker (pattern) e una relativa ai parametri della webcam (params) e decoriamo le dichiarazioni con il comando Embed. In questo modo inietteremo il codice dei due file direttamente negli oggetti.

Dichiariamo anche gli oggetti che utilizzeremo per generare l'ambiente 3D, individuare il marker e realizzare l'interazione con la webcam.

public class esempio_flar extends Sprite
{
  // Importa il pattern
  [Embed(source="patternHTML.pat", mimeType="application/octet-stream")]
  private var pattern:Class;
  
  // Importa i parametri
  [Embed(source="camera_para.dat", mimeType="application/octet-stream")]
  private var params:Class;
  
  // Variabili per la creazione della visualizzazione della webcam
  private var vid:Video;
  private var cam:Camera;
  private var bmd:BitmapData;
  
  // Variabili relative a papervision e FLAR
  private var fparams:FLARParam;
  private var mpattern:FLARCode;
  private var raster:FLARRgbRaster_BitmapData;
	private var detector:FLARSingleMarkerDetector;
	private var scene:Scene3D;
	private var camera:FLARCamera3D;
	private var container:FLARBaseNode;
	private var vp:Viewport3D;
	private var bre:BasicRenderEngine;
	private var trans:FLARTransMatResult;
	 
	public function esempio_flar() {   }
}

A questo punto utilizziamo il costruttore della nostra classe per inizializzare i diversi componenti dell'ambiente, per farlo utilizziamo le seguenti funzioni che dichiareremo più avanti.

Metodo Descrizione
setupWebcam Imposta la visualizzazione del flusso video dalla Webcam
setupFLARToolkit Inizializza i parametri della Webcam e stabilisce le dimensioni del Marker
setupPattern Stabilisce la posizione del marker all'interno del flusso video
setupPapervision Inizializza la scena tridimensionale, gli oggetti e l'illuminazione

Oltre all'inizializzazione degli oggetti, assegnamo alla funzione renderizza la gestione dell'evento ENTER_FRAME. In questo modo possiamo ricalcolare in ogni istante la posizione degli oggetti in base alla camera e al marker.

public function Esempio_Flar()
{
  setupFLARToolkit();
  setupWebcam();
  setupPattern();
  setupPapervision();
  
  addEventListener(Event.ENTER_FRAME, renderizza);
}

Implementiamo ora le varie funzioni. La prima da realizzare è setupWebcam, che ci permetterà di visualizzare nel nostro SWF l'immagine catturata dalla camera. Il codice è molto semplice ed è riportato di seguito coi relativi commenti.

private function setupWebcam() : void
{
  // Crea un nuovo oggetto Video
  vid = new Video(640, 480); 
  
  // Ricava l'oggetto Camera
  cam = Camera.getCamera();
  
  // Imposta risoluzione (640x480) e frame rate (30) della webcam
  cam.setMode(640, 480, 30); 
  
  // Aggancia il flusso video catturato dalla webcam
  // all'oggetto video creato in precedenza
  vid.attachCamera(cam);
  
  // Inserisce l'oggetto video sullo stage
  addChild(vid);             
} 

Se effettuiamo un test adesso, il Flash Player ci richiede l'accesso alla webcam, per mostrare le immagini della nostra telecamerina.

Fatto questo creiamo le funzioni per l'avvio di FLAR e l'impostazione del pattern: setupFLARToolkit e setupPattern.

private function setupFLARToolkit():void
{
  // Crea un nuovo oggetto FLARParam
  fparams = new FLARParam(); 
  
  // Carica i parametri della Webcam come ByteArray
  fparams.loadARParam(new params() as ByteArray); 
  
  // Crea un nuovo oggetto FLARCode
  mpattern = new FLARCode(16, 16); 
  
  // Carica il pattern
  mpattern.loadARPatt(new pattern()); 
}

private function setupPattern():void
{
  // Crea un oggetto BitmapData con le stesse 
  // dimensioni del flusso della webcam (640x480)
  bmd = new BitmapData(640, 480);
  
  // Disegna nell'oggetto bmd l'attuale frame del flusso video
  bmd.draw(vid);
  
  // Crea un oggetto FLARRgbRaster_BitmapData passandogli 
  // il fotogramma catturato
  raster = new FLARRgbRaster_BitmapData(bmd);
  
  // Crea un nuovo detector passandogli i parametri
  // della webcam, il pattern da rilevare e la larghezza 
  // del marker (80 mm)
  detector = new FLARSingleMarkerDetector(fparams, mpattern, 80); 
} 

Queste funzioni potranno essere utilizzate in generale ogni volta che utilizziamo il FLARToolkit: l'unica cosa che potrebbe cambiare è il pattern (e per questo basta modificare il relativo Embed) o le azioni conseguenti al detect del marker (e in questo caso cambieranno le funzioni relative a Papervision3D), ma i comandi relativi alla creazione del flusso della webcam e al setup di FLAR e del marker possono essere mantenute così come le abbiamo create in questo esempio.

Creiamo ora la funzione relativa al setup di Papervision: in questa funzione impostiamo gli elementi tridimensionali che verranno aggiunti al detect del pattern, avremo quindi un'interazione tra alcuni elementi di Papervision e alcuni di FLAR, infatti per esempio il tipo di camera usato nella scena sarà una FLARCamera3D.

private function setupPapervision():void
{
  // Crea una nuova scena di Papervision
  scene = new Scene3D();
  
  // Crea una nuova camera basata su FLAR 
  // e sui parametri caricati dal file .dat
  camera = new FLARCamera3D(fparams);
  
  // Crea un nuovo FLARBaseNode
  container = new FLARBaseNode(); 
  
  // Aggiunge l'oggetto FLARBaseNode alla scena di Papervision
  scene.addChild(container);
  
  // Crea una luce da usare in Papervision
  var pl:PointLight3D = new PointLight3D();
  
  // Posiziona la luce
  pl.x = 1000;
  pl.y = 1000;
  pl.z = -1000;
  
  // Crea un nuovo materiale per i cubi
  var ml:MaterialsList = new MaterialsList({all: new FlatShadeMaterial(pl)}); 
  
  // Crea i 3 cubi e li posiziona a diverse profondità
  var cube1:Cube = new Cube(ml, 30, 30, 30);
  var cube2:Cube = new Cube(ml, 30, 30, 30);
  var cube3:Cube = new Cube(ml, 30, 30, 30);
  cube2.z = 50;
  cube3.z = 100;
  
  // Aggiunge i cubi alla scena
  container.addChild(cube1);
  container.addChild(cube2);
  container.addChild(cube3);
  
  // Impostia il rendering della scena
  bre = new BasicRenderEngine();
  trans = new FLARTransMatResult();
  
  // Crea la visuale
  vp = new Viewport3D();
  
  // Aggiunge la scena completa allo stage
  addChild(vp);
}

È importante notare che questa funzione crea gli elementi della scena e li imposta, ma non renderizza la scena, questo perchè il rendering della scena deve avvenire solo quando il marker viene rilevato, operazione che eseguiamo nella funzione renderizza.

private function renderizza(evt:Event):void
{
  // Disegna il frame nell'oggetto bmd
  bmd.draw(vid); 
  
  // Se il marker viene rilevato
  if(detector.detectMarkerLite(raster, 80) && detector.getConfidence() > 0.5) 
  {
    // Ricava la transformMatrix dal detector
    detector.getTransformMatrix(trans); 
    
    // Imposta la transformMatrix sulla scena
    container.setTransformMatrix(trans);
    
    // Renderizza la scena di Papervision
    bre.renderScene(scene, camera, vp); 
  }
} 

Notiamo il controllo all'interno dell'oggetto detector: se il marker (memorizzato nell'oggetto raster) viene rilevato nella scena, ricaviamo la transformMatrix (utile per conoscere la posizione e l'eventuale inclinazione e rotazione del marker) e la applichiamo all'oggetto container (che contiene la scena 3D), quindi la renderizziamo. Aver associato l'azione di rendering al detect del marker comporta che, non inquadrando il foglio o la superficie con il nostro marker stampato e rilevabile dalla webcam, non vedremo la scena di Papervision.

Figura 5. Risultato finale con la scena renderizzata
Risultato finale

Ti consigliamo anche