Non toccare il mouse, scorre in automatico Non toccare il mouse, scorre in automatico.
Riconoscimento automatico della gestualità del direttore d'orchestra
-
Upload
tommaso-matticchio -
Category
Documents
-
view
40 -
download
2
description
Transcript of Riconoscimento automatico della gestualità del direttore d'orchestra
Riconoscimento Automatico dellaGestualita del Direttore d’Orchestra
Relatore: Prof. Goffredo Haus
Correlatore: Dott. Davide Andrea Mauro
Correlatore: Dott. Stefano Baldan
Tesi di Laurea diTommaso MatticchioMatricola n. 715751
Anno Accademico 2011/2012
Indice
Introduzione iii
1 Definizione del Progetto 11.1 Analisi degli obbiettivi . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Definizione delle scelte progettuali . . . . . . . . . . . . . . . . . . . 21.3 Architettura del sistema . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.1 Protocollo OSC . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 Algoritmi utilizzati 72.1 Motiongram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.2 Algoritmo di Otsu . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.3 beatDetection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3 Analisi del software 133.1 Analisi delle Classi . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.1.1 FrameDiff . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133.1.2 Classe MotiongramX e MotiongramY . . . . . . . . . . . . . 153.1.3 Classe Gesture . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2 Metodo draw() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203.3 Analisi della patch in Puredata . . . . . . . . . . . . . . . . . . . . 223.4 Impostazione della patch Puredata . . . . . . . . . . . . . . . . . . 233.5 Costruzione della patch Puredata . . . . . . . . . . . . . . . . . . . 24
4 Considerazioni finali 274.1 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.2 Future works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.3 Conclusioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Bibliografia 29
i
Introduzione
La motivazione che sta alla base di sviluppare un software per il riconoscimento dei
gesti di un direttore d’orchestra, per la produzione di una performance musicale
conforme, e lo studio di sistemi di interfaccia uomo-macchina. Come un computer
puo elaborare e interpretare le complesse indicazioni di un direttore d’orchestra,
quali informazioni puo estrarre dal gesto direttivo. Sin dal primo momento che ci
si e interessati a queste problematiche era chiaro che un computer non puo, allo
stato attuale delle tecnologie, sostituire una vera orchestra; la varieta di significati
che si possono attribuire ad alcuni gesti possono essere talmente emozionali e
estemporanee da non poter essere modellate da algoritmi. Inoltre, le riproduzioni
musicali sono frutto non solo dell’interpretazione estemporanea di un gesto, ma di
prove e perfezionamenti ricercati nel tempo.
Si vuole citare, a titolo di esempio, quello che Alessandro Carbonare, clarinet-
tista di fama mondiale e di affermata bravura, dice in un documentario per Sky
Classica riguardo la sua esperienza con il M° Claudio Abbado:
“[. . . ]Abbado non e un direttore che ferma molto l’orchestra e che dicetante cose, ne dice pochissime. Ti guida ma non ti impone mai quelloche vuoi fare. C’e un dimenuendo nel solo di clarinetto del IV movi-mento[. . . ], qui lui mi ha fatto un cenno di andre giu, come se da lıvolesse far partire un’altra frase pero senza interromperla. Mozart inrealta non ha scritto nessun diminuendo.”1
Appare dunque evidente come la gestualita del direttore d’orchestra sia fortemente
personalizzata sia dal direttore stesso, che da chi esterna quello che il direttore
chiede. Proprio questa mancanza di standard nell’uso del gesto rappresenta il piu
1A. Carbonare a Sky Classica
iii
iv INTRODUZIONE
grande ostacolo alla buona riuscita di un software che pretenda di interpretare
correttamente tutti i gesti che rendono un’esecuzione musicale “umana”.
Per questo motivo la scelta progettuale e stata verso un sistema che riconosca
le tre componenti piu facilmente calcolabili: tempo, volume e attacco del suono
(vedi paragrafo 1.1).
Capitolo 1
Definizione del Progetto
1.1 Analisi degli obbiettivi
Poiche lo sviluppo di un software completo, che risolvesse tutti i problemi che
possono concernere un progetto cosı complesso, e ben al di sopra delle aspettative
(e tempistiche) di un elaborato finale di questo tipo, si e scelto di produrre un
software che riuscisse a riconoscere i due principali aspetti della direzione musicale.
Gli obbiettivi fissati per questo progetto sono dunque:
• riconoscimento del gesto relativo alla velocita dell’esecuzione (pensata co-
me bpm, beats per minute), nel movimento che rappresenta i 2/4 (batte-
re+levare);
• riconoscimento del gesto relativo all’intensita richiesta dal direttore;
• produzione di un flusso audio che sia conforme alla gestualita.
Si e scelto di riconoscere il movimento di 2/4 poiche rappresenta il movimento
base della direzione d’orchestra, poiche tutte le indicazioni di tipo temporali hanno
un battere, che corrisponde al punto piu basso che raggiunge la mano, e un levare,
che corrisponde al punto piu alto. Questo non pone dei limiti, e infatti auspicabile
che si arrivi a riconoscere tutte le tipologie di gesto; questo aspetto trova infatti
posto nella sezione riguardo ai lavori futuri (vedi 4.2).
Nonostante non esistano degli standard che definiscono come un direttore chie-
da maggiore o minore intensita ai propri esecutori, si e scelto di far corrispondere
questo tipo di richiesta alla grandezza del gesto, dove per grandezza si intende
1
2 CAPITOLO 1. DEFINIZIONE DEL PROGETTO
un valore calcolato come distanza tra beat successivi. Questa scelta e stata fatta
perche si ritiene che, nella maggior parte dei casi, la grandezza del gesto trasmetta
all’esecutore l’intensita richiesta.
Per quanto concerne la produzione di una performance musicale attinente si
e scelto di modificare, in tempo reale, la riproduzione di un file MIDI; si e scelto
di non considerare un formato audio (es. file wav, mp3, etc) perche il risulta-
to sarebbe un flusso audio che, dovendo operare sulla velocita di riproduzione,
produrrebbe anche una variazione del pitch. Inoltre si creerebbero problematiche
piu filosofiche e giuridiche, poiche il materiale creato potrebbe apparire come la
semplice distorsione di un lavoro altrui.
1.2 Definizione delle scelte progettuali
Per lo sviluppo del progetto legato all’elaborato finale le scelte fatte possono essere
divise in due categorie:
1. Estrazione dei dati da una webcam;
2. Produzione della performance a partire dai dati estratti al punto precedente.
Per la parte relativa all’estrazione dei dati a partire dalla webcam la scelta e sta-
ta quella di partire da un algoritmo per il riconoscimento della gestualita che non
corrisponde agli algoritmi spesso usati per tracciare il movimento di un oggetto in
una sequenza di frame, ma atto a riconoscere il movimento presente nella sequenza
di frame, indipendente dagli oggetti in essa contenuti. Il risultato di un algoritmo
di questo tipo e chiamato motiongram, ed e stato sviluppato da Jensenius per ri-
conoscere e interpretare quei movimenti extra musicali che ogni musicista produce
durante un’esecuzione. A tale scopo la scelta e stata quella di usare una libreria
per la gestione del flusso video di una webcam, mentre l’implementazione dell’al-
goritmo e stata fatta ex-novo. Le classi che riguardano l’applicazione di queste
metodologie sono: FrameDiff, MotiongramX e MotiongramY. Per una descrizione
piu dettagliata di questo algoritmo si rimanda alla sezione 2.1.
Per la generazione di dati conformi alle scelte progettuali e stata implementata
una classe, definita Gesture, che partendo dai dati prodotti attraverso l’algoritmo
1.3. ARCHITETTURA DEL SISTEMA 3
di motiongram, restituisce i valori richiesti. Riguardo a questo aspetto e stato scel-
to di usare dei parametri che definiscono le tipologie di gestualita che l’algoritmo
riconosce; nello specifico si e scelto di riconoscere la gestualita riguardo il tempo
2/4 (un battere e un levare) e di interpretare l’ampiezza del gesto (distanza tra un
beat e il precedente) come richiesta di intensita sonora. Per una descrizione piu
dettagliata si rimanda alla sezione 3.1.3
Per la produzione di una performance, che fosse coerente con i dati generati a
partire dalla webcam, la scelta e stata quella di inviare i dati a una patch svilup-
pata nell’ambiente di programmazione dedicato alle multimedialita Puredata, e di
gestire in tempo reale la riproduzione di un file in formato MIDI. La descrizione
di questa patch e trattata nella sezione 3.3.
1.3 Architettura del sistema
Si vuole dare in questa sezione una descrizione del sistema che implementa il soft-
ware sviluppato per l’elaborato finale. L’architettura di questo sistema ha, come
elementi iniziali, un computer a cui e collegata una webcam, elemento fondamen-
tale per poter elaborare informazioni in tempo reale. La parte software e stata
invece divisa in due parti: una legata al video e una legata all’audio; troviamo
quindi che la webcam, e i dati che invia al computer, sono elaborati da Processing,
un ambiente di sviluppo (con un linguaggio di programmazione basato su Java)
per le multimedialita (immagini, animazioni e interazione).
I dati generati ed elaborati dal software sviluppato in Processing, sono quindi
inviati tramite il protocollo OSC (Open Sound Control), creato per permettere la
comunicazione tra computer, sintetizzatori e dispositivi che supportino le moderne
tecnologie di rete. I dati vengono quindi spediti all’ultimo anello dell’architettura
del sistema: la patch creata in Puredata. Questo ambiente di programmazio-
ne visuale, pensato per l’audio, e stato sviluppato da Miller Puckette negli anni
’90, come versione opensource del progetto sviluppato presso l’IRCAM di Parigi
chiamato Max e poi sviluppato come software commerciale con il nome Max/MSP.
In questa patch, descritta dettagliatamente nella sezione 3.3, i dati generati
vengono utilizzati per produrre una performance audio, a partire da un file MIDI
presente nella memoria del computer.
4 CAPITOLO 1. DEFINIZIONE DEL PROGETTO
1.3.1 Protocollo OSC
Open Sound Control (OSC) e un protocollo, inventato nel 1997 da Adrian Freed e
Matt Wright presso il Centre for New Music and Audio Technologies (CNMAT) per
controllare gli algoritmi di sintesi sonora del sistema CAST, attraverso messaggi
sulla rete [WF97]. Ha poi trovato applicazione nel gestire in tempo reale i flussi di
messaggi di controllo audio. Per controllo audio si intende qualsiasi informazione
temporizzata riguardo a un flusso audio, oltre che la componente audio stessa.
Inoltre, questo formato puo avere applicazione anche in applicazioni non legate
unicamente all’audio, e ha infatti trovato impiego in settori come la robotica o
“show control”.
E da specificare che OSC non e uno standard, e non c’e la necessita di test per
certificare la conformita. Il protocollo e “open” nel significato che non ha licenze
di utilizzo, non richiede l’utilizzo di algoritmi registrati o di materiale protetto dal
diritto d’autore e non fa forti assunzioni su come il formato debba essere usato
nelle applicazioni [SFW10].
L’implementazione del protocollo OSC nel progetto avviene in due fase: prima
si crea il messaggio OSC e si invia a un indirizzo (ip:porta), mentre per secondo si
deve impostare la patch puredata per ricevere il messaggio e riuscire a leggerlo.
Nel codice sviluppato in Porcessing questo avviene importando la libreria oscP5 .
Si da un esempio minimale dell’applicazione di tale protocollo:
Listing 1.1: Esempio OSC in Processing
1 import oscP5 .*;
import netP5 .*;
3
OscP5 oscP5;
5 NetAddress myRemoteLocation;
7 void setup() {
size (400 ,400);
9 oscP5 = new OscP5(this ,8000);
myRemoteLocation = new NetAddress("localhost" ,8001);
11 }
13 void draw()
{
15
}
17
1.3. ARCHITETTURA DEL SISTEMA 5
void mousePressed () {
19 OscMessage myMessage = new OscMessage("/test");
myMessage.add("bang");
21 oscP5.send(myMessage , myRemoteLocation );
}
23
void oscEvent(OscMessage theOscMessage)
25 {
String thirdValue = theOscMessage.get (2). stringValue ();
27 }
Si puo osservare come il codice implementato sia molto semplice, costituito di
pochi passi fondamentali, come la creazione del messaggio (riga 19 del listato 1.1),
l’inserimento del valore desiderato (riga 20) e l’invio del messaggio attraverso il
metodo send (riga 21).
Risulta semplice, inviare un beat attraverso la rete, per farlo giungere alla patch
sviluppata in puredata, che attraverso la libreria mrpeach, utilizza oggetti come
[udpreceive numero porta] per mettersi in ascolto dei messaggi, e [unpackOSC] per
leggerli secondo il protocollo OSC. La figura 1.1 mostra un esempio base di come
creare una patch in grado di ricevere messaggi sulla porta 8001, e ne stampi il
valore a video.
Figura 1.1: Esempio di apllicazione protocollo OSC in patch puredata
Capitolo 2
Algoritmi utilizzati
2.1 Motiongram
Jensenius scrive[Jen06] che uno dei modi conosciuti per visualizzare il movimento e
quello di calcolare la differenza tra due frame in un flusso video. Uno degli approcci
alla creazione di un motiongram e quello di calcolare la quantita di moto sommando
i pixel attivi in una motion image e stampando questo valore nel tempo. Questi
grafici restituiscono un’idea del tipo di movimento, ma rimuovono completamente
tutte le informazioni di tipo spaziale riguardanti la posizione, nell’immagine, dove
ha luogo il movimento. Si ricorda che il grafico generato corrisponde solo a una
dimensione/direzione del movimento.
Nel lavoro svolto per l’elaborato finale questo approccio e stato usato e imple-
mentato attraverso il software Processing 1.5.1, attraverso l’uso di una webcam e
la libreria, contenente gli strumenti per utlizzare la webcam, GSVideo. Si e quindi
implementato un algoritmo che confronta i pixel dell’immagine (frame) corrente
con gli stessi pixel dell’immagine precedente, e restituisce un’immagine dove, per
i pixel che sono riscontrati come attivi si imposta un pixel bianco mentre per il
caso opposto si imposta un pixel nero. Dopo aver generato questa immagine a
sogliatura di moto si e proceduti a generare i motiongram (che altro non sono che
grafici del moto), calcolando la media del moto colonna∗ colonna, per ottenere un
grafico del moto orizzontale, e riga ∗ riga, per avere un grafico del moto vertica-
le. Dopo aver implementato questa parte il risultato ottenuto e la visualizzazione
7
8 CAPITOLO 2. ALGORITMI UTILIZZATI
di due motiongram, uno che descrive il moto orizzontale della sequenza di frame
analizzata, mentre il secondo motiongram descirve il moto verticale.
Poiche la scelta progettuale richiede il riconoscimento del movimento di en-
trambe le mani e stato implementato un algoritmo per la separazione delle due
tracce, corrispondenti al movimento delle due mani. Inizialmente e stato scelto di
applicare l’algoritmo di Otsu, che risulta adeguato allo scopo, poiche separa al me-
glio distribuzioni di probabilita bimodali, metodo poi scartato perche, nonostante
gli ottimi risultati, non e possibile assumere che ci siano sempre distribuzioni di
probabilita bimodali, poiche il direttore potrebbe scegliere di muovere una sola
mano.
Il metodo di Otsu, nonostante sia stato scartato, e ugualmente implementato
nel codice, perche in un lavoro futuro potra essere implementato un metodo che
permetta di usare l’algoritmo di Otsu in presenza di due distribuzioni di probabi-
lita, o di utilizzare altre metodologie nel caso di presenza di una sola distribuzione
di probabilita; la classe e OtsuStat e una descrizione dell’algoritmo si puo trovare
in 2.2.
2.2 Algoritmo di Otsu
L’algoritmo di Otsu e un metodo usato per la sogliatura automatica di istogrammi
nelle immagini digitali. Esso considera la presenza di due sole classi (“sfondo” e
“primo piano”) e determina quale valore di soglia sia la migliore per la separazione
delle due classi, minimizzando la varianza intra-classe. La varianza intra-classe
viene quindi definita come somma pesata delle varianze delle due classi:
σ2ω(t) = ω1(t)σ
21(t) + ω2(t)σ
22(t) (2.1)
Otsu dimostra inoltre che minimizzare la varianza intra-classe (2.1) equivale a
massimizzare la varianza inter-classe:
σ2b (t) = σ2 + σ2
ω(t) = ω1(t)ω2(t)[µ1(t)− µ2(t)
]2. (2.2)
la quale (2.2) e espressa in base ai pesi ωi e alle medie µi. Questo aspetto rende
2.2. ALGORITMO DI OTSU 9
migliore la sua applicazione a livello informatico poiche cercare il valore massimo
e un compito facilmente eseguibile da un elaboratore, data la sua natura iterativa
e, piu importante, incrementale.
Il peso della classe ω1(t) e ottenuta dall’istogramma come t:
ω1(t) =t∑0
p(i) (2.3)
mentre la media della classe µi(t) e calcolata:
µi(t) =t∑0
p(i)x(i) (2.4)
dove x(i) e il valore al centro del iesimo istogramma binario. Allo stesso modo, si
puo calcolare il peso della ω2(t) e la media µt della parte destra dell’istogramma
per valori piu grandi di t.
Poiche sia i pesi delle classi che le medie possono essere calcolati in modo
incrementale, si puo ottenere un algoritmo. Questo algoritmo puo essere quindi
eseguito seguendo i passi:
1. calcolare gli istogrammi e i pesi per tutti i livelli di intensita;2. inizializzare ωi(0) e µi(0);3. scorrere tutte le possibili soglie t = 1...valoremassimo;
(a) aggiornare ωi e µi;(b) calcolare σ2
b (t);
4. la soglia desiderata corrisponde al valore massimo di σ2b (t).
Per il lavoro svolto, questo algoritmo si e dimostrato efficace nel separare le
tracce corrispondenti alle due mani, poiche considerate come due distribuzioni di
probabilita; sostituendo i dati in ingresso all’algoritmo, usando quindi le righe del
motiongram orizzontale e non l’istogramma delle intensita, si ottiene il pixel che
separa il semi-quadrato destro dal semi-quadrato sinistro.
Come gia indicato questo metodo e stato scartato poiche e possibile che il di-
rettore muova una sola mano, e quindi il motiongram generato non sia modellabile
come una distribuzione di probabilita bimodale.
10 CAPITOLO 2. ALGORITMI UTILIZZATI
2.3 beatDetection
Dopo aver separato i tracciati delle due mani, e avendo sviluppato un metodo per
la restituzione del valore del pixel corrispondente alla posizione della mano, e stato
implementato un algoritmo che fosse in grado di riconoscere automaticamente i due
momenti, di battere e levare, corrispondenti al beat.
Questo algoritmo e stato sviluppato ex-novo, anche perche alcune degli algo-
ritmi per la ricerca del beat nel movimento usavano parametri diversi, come ad
esempio in [MAJ04], dove l’algoritmo considerava anche il file audio per effettuare
una predizione di dove si trovasse il beat.
L’algoritmo implementato utilizza come parametri solo il valore di y delle due
mani (si ricorda che l’algoritmo funziona in presenza di un gesto da 2/4, quindi solo
verticale), e considera come beat gli istanti in cui la funzione ha un picco, verso
l’alto o verso il basso. E apparso quindi che la condizione da porre all’algoritmo
fosse legata alla derivata prima del movimento.
Questa soluzione presenta delle problematiche, date anche dalla poca linearita
dei dati in ingresso. Infatti i dati in ingresso all’algoritmo, essendo la posizione
del valore medio istante per istante, non risultano come una sequenza lineare di
numeri, e anche se calcolati con media esponenziale rispetto al valore precedente,
secondo la formula 2.5:
pixcurr = (α ∗ pixprev) + pixcurr(1− α) (2.5)
dove α determina il peso del valore precedente, e che varia da 0 (quando non si
vuole tenere in considerazione i valori precedenti) a 1 (dove il peso e talmente
alto che pxcurr = pixprev), l’algoritmo restituisce troppi falsi beat, rendendolo non
utilizzabile.
La scelta e quindi stata quella di creare un algoritmo piu sofisticato che uti-
lizzasse come parametro, oltre alla derivata prima, anche la derivata seconda. Il
modo di calcolare queste due derivate, in questo frangente, e quello di calcolare
la derivata prima come differenza del valore corrente e di quello precedente, e di
calcolare la derivata seconda come la differenza tra la derivata prima del valore
corrente e la derivata prima del valore precedente. L’algoritmo deve quindi memo-
2.3. BEATDETECTION 11
rizzare, a ogni ciclo, i valori correnti, per poter utilizzarli al ciclo successivo come
valori precedenti.
Per cercare di ottenere un risultato il piu possibile consono agli scopi sono stati
aggiunte delle verifiche di controllo. E stato aggiunto un valore che determina se la
direzione del movimento e verso il basso, o viceversa, cosı da impostare l’algoritmo
a cercare un cambiamento di verso in relazione a tale dato; e stato anche aggiunto
un valore temporale che calcola la differenza in millisecondi tra il beat riscontrato
e quello precedente, e in caso questo valore sia inferiore ai 200 millisecondi (vale a
dire a un tempo metronomico di 300bpm, valore che e sensato pensare fuori scala)
considera il beat ottenuto come un falso beat, scartandolo.
L’algoritmo cosı ottenuto e stato implementato nella classe Gesture, descritta
nella sezione 3.1.3.
Capitolo 3
Analisi del software
3.1 Analisi delle Classi
Nella seguente sezione vengono descritte in modo piu approfondito le classi del
codice prodotto durante lo sviluppo del progetto. Sono state scelte le classi
considerate piu pertinenti alle problematiche occorse durante il lavoro di sviluppo.
Si e scelto di descrivere le seguenti classi: FrameDiff, MotiongramX e Gesture,
ritenute parte fondamentale del lavoro svolto, mentre tralasciamo la descrizione
delle classi che non apportano originalita o forte dipendenza dal lavoro svolto.
3.1.1 FrameDiff
La classe denominata FrameDiff consente di svolgere l’operazione preliminare alla
creazione di un motiongram. Come descritto in 2.1, si deve elaborare (partendo
dai frame restituiti dalla webcam) un’immagine a sogliatura di moto, per poter
procedere con l’algoritmo. Di seguito e mostrato il codice prodotto, relativo al
metodo principale della classe:
Listing 3.1: Classe FrameDiff
1 public class FrameDiff {
public PImage process(PImage curr) {
3 PImage result = createImage(prev.width , prev.height , RGB);
for (int x = 0; x < prev.width; x++) {
5 for (int y = 0; y < prev.height; y++) {
int curPix = curr.get(x, y);
7 int prevPix = prev.get(x, y);
13
14 CAPITOLO 3. ANALISI DEL SOFTWARE
float err = abs(red(curPix) - red(prevPix )) +
9 abs(green(curPix) - green(prevPix )) +
abs(blue(curPix) - blue(prevPix ));
11 if (err > thresh) result.set(x, y, color (255));
prev.set(x,y,curPix );
13 }
}
15 return result;
}
17 }
Le variabili prev(di tipo PImage) e tresh(di tipo intero e impostato a 60) ven-
gono definite nella classe; il metodo process confronta quindi il pixel appartenente
al frame corrente col corrispettivo pixel nel frame precedente, e se la somma delle
differenze assolute dei valori dei pixel supera la soglia “(thres)”, viene considerato
come pixel attivo e impostando, nell’immagine result, il relativo pixel come bianco
(color(255), riga 11 del listato 3.1). Il risultato finale e mostrato in figura:
Figura 3.1: Risultato applicazione classe FrameDiff
Come e possibile osservare in figura 3.1, le parti in movimento (mani e volto)
risultano attive e quindi bianche, mentre lo sfondo, che non si muove e non cambia,
non viene visualizzato. Dal risultato di questo primo algoritmo e possibile calcolare
i motiongram.
3.1. ANALISI DELLE CLASSI 15
3.1.2 Classe MotiongramX e MotiongramY
Abbiamo definito, nella sezione 2.1, un motiongram come una rappresentazione
del moto nel tempo, e per questo motivo si devono considerare le due direzioni
indipendenti tra di loro. Il risultato dell’applicazione di un motiongram e quindi
un’immagine che descrive il movimento scelto (orizzontale o verticale) e che ne
disegna la funzione. Vengono mostrati due esempi di motiongram, uno orizzontale
e uno verticale:
Figura 3.2: Visualizzazione motiongram per il movimento orizzontale
Figura 3.3: Visualizzazione motiongram per il movimento verticale
Nelle figure 3.2 e 3.3 il motiongram corrispondente viene visualizzato alla destra
dell’immagine elaborata tramite la classe FrameDiff (vedi sezione 3.1.1). Si deve
specificare che il motiongram per il movimento orizzontale viene disegnato dall’alto
verso il basso, mentre per quello relativo al movimento verticale l’andamento e da
sinistra a destra.
16 CAPITOLO 3. ANALISI DEL SOFTWARE
Viene ora mostrato il codice che applica l’algoritmo per la generazione dei
motiongram (viene illustrato solo il codice relativo al motiongram per il movimento
orizzontale, poiche le modalita sono le stesse anche per il motiongram verticale):
Listing 3.2: Classe MotiongramX
1 public class MotiongramX {
private PImage frame;
3 private int currY;
5 public MotiongramX(int w, int h) {
this.frame = createImage(w, h, RGB);
7 this.currY = 0;
}
9
public float [] process(PImage img) {
11 float[] result = new float[img.width];
currY = (currY + 1) % frame.height;
13 for (int x = 0; x < img.width; x++) {
for (int y = 0; y < img.height; y++) {
15 result[x] += brightness(img.get(x,y));
}
17 result[x] /= cam.width;
frame.set(x, currY , color(result[x]));
19 }
return result;
21 }
23 public void display(int x, int y) {
image(frame ,x,y);
25 }
}
Il metodo principale della classe e process, un metodo che accetta come ingresso
una PImage e restituisce un array di float (numeri in virgola mobile). Il metodo
opera cosı:
• creazione di result, array di lunghezza pari alla lunghezza della PImage img,
• creazione di un valore che sposta l’indicatore colonna dopo colonna,
• viene calcolata la media dei valori di luminosita di tutti i pixel appartenenti
alla colonna,
• viene aggiornato frame secondo i valori ottenuti;
Il procedimento risulta essere simile per il motiongramY, che inverte il ciclo for e
cambia l’indicatore currY in currX per aggiornare colonna dopo colonna.
3.1. ANALISI DELLE CLASSI 17
Come gia indicato e stato necessario avere la possibilita di separare le due
tracce delle mani, per poter avere due tracce distinte anche nel motiongram per il
movimento verticale. Si puo notare, dalle figure 3.2 e 3.3, che se per il movimento
orizzontale e possibile visualizzare due tracce, lo stesso non avviene per il movi-
mento verticale (o meglio, sono presenti due tracce quasi sovrapposte). I metodi
per separare le due tracce che sono stati sviluppati sono due: considerando le due
mani come distribuzioni di probabilita bimodali e possibile applicare l’algoritmo
di Otsu (descritto in sezione 2.2) oppure scegliere di dividere l’immagine in due
semi-quadrati e dividere cosı le tracce. Entrambe le scelte portano dei problemi,
l’algoritmo di Otsu obbliga a considerare sempre due mani, mentre dividere l’im-
magine obbliga il direttore a non spostare troppo le mani in orizzontale, per non
invadere l’altro semi-quadrato. La seconda opzione e stata considerata la migliore,
per la possibilita di muovere una mano sola.
Viene mostrato ora come viene modificato il metodo process, della classe Mo-
tiongramY, per la produzione di due motiongram con le tracce corrispondenti alle
due mani separate:
Listing 3.3: Metodo process nella classe MotiongramY
public float [] process(PImage img , int thresh) {
2 float[] result = new float [2* img.width ];
currX = (currX + 1) % frameL.width;
4 for (int y = 0; y < img.height; y++) {
int j = img.height + y;
6 for (int x = 0; x < thresh; x++) {
result[y] += brightness(img.get(x,y));
8 }
for (int x = thresh; x < img.width; x++) {
10 result[j] += brightness(img.get(x,y));
}
12 result[y] /= img.width;
result[j] /= img.width;
14 frameL.set(currX , y, color(result[y]));
frameR.set(currX , y, color(result[j]));
16 }
return result;
18 }
Si puo osservare come due PImage vengano prodotte da questo metodo, frameL
e frameR(entrambe variabili della classe), e di come il metodo usi due cicli for,
18 CAPITOLO 3. ANALISI DEL SOFTWARE
uno per il valore di x che varia da 0 alla soglia− 1 mentre il secondo dalla soglia
fino alla larghezza dell’immagine.
3.1.3 Classe Gesture
La classe Gesture rappresenta il cuore del progetto, riceve in entrata i valori del
movimento delle due mani e restituisce l’interpretazione di questi valori per gli
obbiettivi definiti in questo elaborato. Il lavoro svolto dalla classe e dai suoi metodi
consiste quindi nel interpretare come gestualita inerente alla direzione musicale il
movimento delle mani, secondo i parametri definiti negli obbiettivi (vedi sezione
1.2). Viene di seguito riportata la classe, nella sua interezza, a cui seguira la
descrizione delle sue parti fondamentali:
Listing 3.4: Classe Gesture
public class Gesture {
2 float[] prevCoords;
float prevRightY , prevDer;
4 long prevMills;
int minBeat , beatDirection;
6
public Gesture(int minBeat) {
8 prevCoords = new float [4];
beatDirection = 1;
10 setMinBeat(minBeat );
}
12
public Gesture () {
14 this (140);
}
16
public void setMinBeat(int minBeat) {
18 this.minBeat = minBeat;
}
20
public float process(float leftX , float leftY , float rightX , float rightY) {
22 float result = 0;
float firstDer = rightY - prevRightY;
24 long mills = millis ();
26 if (beatRule(firstDer , mills )) {
beatDirection = -beatDirection;
28 float[] currCoords = new float [4];
currCoords [0] = leftX;
30 currCoords [1] = leftY;
3.1. ANALISI DELLE CLASSI 19
currCoords [2] = rightX;
32 currCoords [3] = rightY;
float vol = 0;
34 for (int i = 0; i < currCoords.length; i++) {
vol += abs(currCoords[i] - prevCoords[i]);
36 }
result = beatDirection * vol;
38 prevMills = mills;
prevCoords = currCoords;
40 }
prevRightY = rightY;
42 prevDer = firstDer;
return result;
44 }
46 private boolean beatRule(float firstDer , long mills) {
if (beatDirection > 0) {
48 return firstDer >= 0 && prevDer < 0 && mills - prevMills >= minBeat;
}
50 return firstDer <= 0 && prevDer > 0 && mills - prevMills >= minBeat;
}
52 }
Come si osserva nel listato 3.4, la classe Gesture e formata dal metodo princi-
pale process, che esegue le operazioni richieste, e da attributi interni alla classe e
metodi per impostare valori, come la variabile minBeat.
I principi sui quali si basa lo sviluppo di questa classe sono stati descritti nella
sezione 2.3, e descrivono le modalita con cui si e deciso di interpretare la gestualita
riscontrata dalle classi MotiongramX e MotiongramY. L’idea e quindi quella di
calcolare la derivata prima e seconda del movimento e in base alla condizione
che se la derivata prima e maggiore o uguale di 0 e la derivata seconda minore
di 0 (o viceversa derivata prima e minore o uguale di 0 e la derivata seconda
maggiore di 0) verificare la presenza di un beat. Per la rumorosita dei dati e stato
necessario aggiungere un raffinamento, una miglioria nell’algoritmo e quindi nel
codice. Questa miglioria e stato implementata nel metodo privato beatrule (riga
46 del listato 3.4.
Questo metodo ha il compito di decidere come impostare le due condizioni di
ricerca in base alla forma del precedente beat. Attraverso la variabile beatDirection
si tiene memoria della direzione del movimento che ha generato il precedente beat;
cioe, se il beat precedente aveva direzione verso il basso allora per ottenere un beat
valido la sua direzione deve essere verso l’alto. In questo modo si diminuiscono
20 CAPITOLO 3. ANALISI DEL SOFTWARE
sensibilmente i falsi beat dovuti alla rumorosita dei dati in ingresso al metodo.
La modalita con cui viene impiegato questo metodo all’interno della classe, nel
metodo process, e osservabile a riga 26 del listato 3.4.
Inoltre attraverso il metodo process e possibile ricavare anche il valore di in-
tensita interpretata a partire dai dati dell’algoritmo di computer vision. E stata
infatti definita come intensita (richiesta dal direttore d’orchestra) il risultato del
calcolo della distanza del beat corrente a quello precedente (piu grande e la distan-
za piu e richiesta intensita). Ecco che quindi, da riga 28 a 36 (listato 3.4) possiamo
osservare come, attraverso un arrray di numeri in virgola mobile, si operi una som-
ma di differenze assolute tra il valore corrente e il valore precedente, per entrambe
le posizioni delle due mani (posizione orizzontale e verticale) determinando cosı
il valore di intensita. Si puo inoltre osservare come il risultato del metodo sia il
risultato della moltiplicazione tra l’intensita (il float vol) e la direzione del beat
(l’intero beatDirection, compreso tra −1 e +1), che permette di ottenere due infor-
mazioni con un solo valore; si puo constatare infatti che se result = 0 non siamo
in presenza di beat, mentre per result 6= 0 sara presente un beat, e all’intensita
corrispondente a |result|.
3.2 Metodo draw()
Nell’ambiente di sviluppo Processing il metodo draw() rappresenta uno dei metodi
fondamentali nell’esecuzione di un programma. Benche “java-based” Prcessing
utilizza delle strutture che la lo rendono diverso dallo standard Java. Non esiste
infatti nessun metodo main che viene utilizzato. E doveroso osservare che in
realta il metodo main viene utilizzato, solo che non e reso esplicito dall’ambiente;
se infatti si procede a esportare un progetto sviluppato in Processing e si va a
verificare il file “nome progetto.java” e possibile verificare la presenza del metodo
alla fine del codice. Nell’esportare il nostro progetto infatti possiamo notare che
come ultime righe di codice il file eyeDirector.java presenta le seguenti righe:
static public void main(String args []) {
2 PApplet.main(new String [] { "--present", "--bgcolor =#666666", "--hide -stop",
"eyeDirector"});
4 }
3.2. METODO DRAW() 21
dove e osservabile che il metodo main() viene in realta usato (essendo l’applicazione
esportata in Java).
Il metodo draw() in Processing e un metodo che viene chiamato subito dopo il
metodo setup() (usato per le impostazioni iniziali dell’applicazione) e che esegue
ciclicamente le righe di codice al suo interno, fino a che l’applicazione non viene
fermata, o non viene richiamato un metodo noloop(). Questo metodo e chiamato
automaticamente dall’ambiente ed e necessario per l’utilizzo di alcuni metodi (come
mousePressed(), e deve comparire una volta sola nel codice.
Viene quindi esposto il codice all’interno del metodo draw(), per verificare come
l’applicazione chiama i metodi delle classi sopra descritte (vengono tralasciate le
dichiarazioni delle variabili globali dell’applicazione):
public void draw() {
2 if (cam.available () == true) {
cam.read ();
4 PImage diff = frameDiff.process(cam);
float[] movX = motiongramX.process(diff);
6 splitX.process(movX);
int thresh = splitX.getThresh ();
8 float[] movY = motiongramY.process(diff , splitX.getThresh ());
splitY.process(movY);
10 if (splitY.getWeightL () > minMotion) {
leftX = leftX * motionV + splitX.getMeanL () * motionW;
12 leftY = leftY * motionV + splitY.getMeanL () * motionW;
}
14 if (splitY.getWeightR () > minMotion) {
rightX = rightX * motionV + splitX.getMeanR () * motionW;
16 rightY = rightY * motionV + (splitY.getMeanR () - h) * motionW;
}
18 float bang = gesture.process(leftX , leftY , rightX , rightY );
if (bang != 0)
20 {
OscMessage myMessage = new OscMessage("/test");
22 myMessage.add("bang");
oscP5.send(myMessage , myRemoteLocation );
24 }
26 // OUTPUT ON SCREEN
image(diff , 0, h);
28 motiongramX.setMarks(thresh , leftX , rightX );
motiongramX.display(0, 0);
30 motiongramY.setMarks(leftY , rightY );
motiongramY.displayL(w, 0);
32 motiongramY.displayR(w, h);
pushMatrix ();
22 CAPITOLO 3. ANALISI DEL SOFTWARE
34 translate(0, h);
// punto grosso dopo un battere , punto piccolo dopo un levare
36 if (bang > 0) strokeWeight (50);
if (bang < 0) strokeWeight (10);
38 stroke (255, 0, 0);
point(leftX , leftY);
40 stroke(0, 0, 255);
point(rightX , rightY );
42 popMatrix ();
}
44 }
A riga 4 del listato 3.2 si puo osservare come venga richiamato il metodo process
della classe frameDiff (descritta in 3.1.1). In questo modo si avra una PImage
contenente l’immagine a sogliatura di moto. Alle righe 5 e 8 si trova il richiamo del
metodo process della classe motiongramX (a riga 5) e della classe motiongramY (a
riga 8), con le diverse variabili in ingresso (si veda 3.1.2). Si puo anche osservare
che a riga 18 viene richiamata il metodo process della classe gesture (si faccia
riferimento alla descrizione in 3.1.3), che restituria i dati da mandare, tramite
protocollo OSC, alla patch in Puredata.
Con la descrizione del metodo draw() che racchiude tutti i riferimenti alle classi
descritte nel capitolo, viene ora data la descrizione della patch, a cui vengono
inviati i dati.
3.3 Analisi della patch in Puredata
In questa parte dell’elaborato viene descritta la patch progettata in Puredata, quali
sono state le scelte operate per la realizzazione degli obbiettivi posti nella sezio-
ne 1.1. Viene prima data una descrizione dell’ambiente di sviluppo denominato
Puredata.
Puredata Dal sito ufficiale del progetto Puredata1 leggiamo che esso e un am-
biente di sviluppo, grafico ed in tempo reale, per l’elaborazione di audio, video
e grafica. Puredata e open source, ed ha una grande numero di sviluppatori che
lavorano per aggiungere nuove estensioni. E stato sviluppato da Miller Puckette
1http://puredata.info/
3.4. IMPOSTAZIONE DELLA PATCH PUREDATA 23
negli anni ’90, e appare molto simile (sia per gli obbiettivi, che per il design) al pro-
getto sviluppato (sempre da M. Puckette) presso l’IRCAM (Institut de Recherche
et Coordination Acoustique/Musique) di Parigi, conosciuto col nome commerciale
di Max/MSP. Il forte legame col progetto Max/MSP si denota dalla possibilita
di sviluppare estensioni che funzionino anche con Max/MSP, e dall’obbiettivo di
migliorare il paradigma di Max, favorendo un trattamento piu aperto ai dati, e alla
possibilita di estendere le sue applicazioni oltre al mondo dell’audio e del video 2.
Si segnala inoltre che le applicazioni sviluppate in questo ambiente di sviluppo
sono chiamate patch, che non e compito di questo elaborato finale la spiegazio-
ne dettagliata del funzionamento dell’ambiente (per la qual cosa si rimanda alla
numerosa documentazione online), e che per convenzione, poiche si parla di og-
getti, graficamente visualizzatti come rettangoli, si utilizzera la scrittura [nome
dell’oggetto] per la descrizione di questi ultimi.
3.4 Impostazione della patch Puredata
E opportuno fornire una descrizione degli oggetti utilizzati, al fine di avere una
visione piu precisa del funzionamento della patch. Sono stati usati i seguenti
oggetti, di uso non comune in Puredata:
[import] L’oggetto [import] permette di importare librerie esterne, poiche Pu-
redata non fornisce di base tutte le estensioni possibili, ma lascia liberta allo
sviluppatore di importare quelle piu consone per il proprio progetto.
Di base Puredata non fornisce oggetti per il supporto al protocollo OSC (de-
scritto nella sottosezione 1.3.1), e neanche uno strumento per la riproduzione di file
midi che soddisfi i requisiti richiesti. La libreria esterna mrpeach e risultata essere
la piu conforme ai requisiti poiche fornisce oggetti sia per l’utilizzo del protocollo
OSC che per la riproduzione di file midi.
[midifile] L’oggetto [midifile] e l’oggetto che permette la riproduzione ed un
controllo sulla stessa. E presente nella libreria esterna mrpeach e si dovra curare
di importarla prima di procedere. L’oggetto ammette come ingresso una serie
2ibidem.
24 CAPITOLO 3. ANALISI DEL SOFTWARE
di possibilita (riguardo alla riproduzione, poiche attraverso l’oggetto [midifile] e
possibile anche registrare un file midi):
• il percorso specifico ad un file midi,
• un [bang] che aumenta di 1 il tick corrente (quindi inserendo un oggetto
[metro] e possibile riprodurre il file ad una data velocita),
• una message box che sposta il contatore di tick all’indirizzo numerico inserito;
mentre genera un gran numero di uscite che, opportunamente filtrate tramite l’og-
getto [route], restituiscono valori come il numero di tick al quarto, un [bang] alla
fine del file, il numero di traccia, il formato, i microsecondi al quarto, e le singole
note on e note off.
[udpreceive] Questo oggetto ha la funzione di mettersi in ascolto su una porta
scelta, per la ricezione di pacchetti attraverso il protocollo udp, si scrive [udpreceive
numero porta; e un oggetto senza entrate, e come uscita il pacchetto udp ricevuto
in formato raw byte.
[unpackOSC] L’utilizzo di questo oggetto e di fondamentale importanza per la
traduzione dei pacchetti udp in formato raw byte, in protocollo OSC. L’ingresso
accetta quindi un messaggio non tradotto e ne fornisce la traduzione.
3.5 Costruzione della patch Puredata
Dopo questa breve introduzione sull’utilizzo di Puredata, viene ora descritta la
patch; data la grande estensione della stessa, verranno descritti i vari blocchi che
presiedono ognuno allo svoglimento di determinati compiti. Si ricorda che l’oggetto
cardine della patch e [midifile] e che viene importata la libreria mrpeach.
La prima parte della descrizione riguarda come e stata sviluppata una moda-
lita per aprire il file midi che si vorra riprodurre. E stato accennato che [midifile]
accetta come ingresso una message box contenente il percorso del file. Per rendere
piu facile la possibilita di cambiare file midi, sfogliando tra le cartelle del proprio
disco fisso si e scelto di operare nel seguente modo: viene usato l’oggetto [openpa-
nel], che apre una finestra che permette di scegliere un file, nel cui ingresso viene
3.5. COSTRUZIONE DELLA PATCH PUREDATA 25
mandato un [bang] e che in uscita produce la path del file. Viene quindi inserita
una message box al cui interno sta l’istruzione “read $1”, che mandata in input
a [midifile] permette il caricamento del midi da riprodurre. Viene mostrata una
figura sulla realizzazione grafica in Puredata:
Figura 3.4: Premere su Apri File per scegliere il file da aprire.
Per modificare le proprieta di riproduzione del file midi, dobbiamo estrarre da
questo alcune informazioni. Una delle soluzioni adottate consiste nel calcolare la
distanza, in millisecondi, tra due [bang] e dividendo questo valore per il numero di
tick al quarto otteniamo ogni quanti millisecondi deve esserci un tick per andare
alla velocita impostata. Questo approccio non consente il controllo che e presente
nel gesto di un direttore d’orchestra, perche elimina le informazioni che riguardano
il fatto che ad ogni [bang] corrisponda un quarto. Anche per questa parte viene
mostrata la figura della realizzazione in Puredata:
Viene inoltre illustrato il procedimento per la riproduzione del file midi, resa
possibile dagli oggetti [noteout], poiche il procedimento e lungo ma ripetitivo, si
da una descrizione del funzionamento base, e verra poi mostrata la figura che
rappresenta una patch in grado di riprodurre tutte le note a partire da [midifile].
Ecco la figura:
26 CAPITOLO 3. ANALISI DEL SOFTWARE
Figura 3.5: Come ricavare quanti millisecondi per tick ci sono dati due quarti
Figura 3.6: Patch per la riproduzione di file midi.
Capitolo 4
Considerazioni finali
4.1 Testing
Qui descrizioni di come il software funziona e reagisce.
4.2 Future works
Qui le migliorie al lavoro.
4.3 Conclusioni
Qui boh.
27
Bibliografia
[Bor+04] Jan Borchers et al. “Personal Orchestra: A real-time audio/video sy-
stem for interactive conducting”. In: ACM Multimedia Systems Journal
Special Issue on Multimedia Software Engineering 9.5 (2004), pp. 458–
465. url: http://media.informatik.rwth-aachen.de/papers.
html.
[Bru+07] Bernd Bruegge et al. “Pinocchio: conducting a virtual symphony or-
chestra”. In: Proceedings of the international conference on Advances
in computer entertainment technology. Salzburg, Austria: ACM, 2007,
pp. 294–295. isbn: 978-1-59593-640-0. url: http://doi.acm.org/10.
1145/1255047.1255132.
[Jen06] Alexander Refsum Jensenius. “Using Motiongrams in the Study of Mu-
sical Gestures”. In: Proceedings of the 2006 International Computer
Music Conference. New Orleans, LA: Tulane University, 2006, pp. 499–
502. url: http://urn.nb.no/URN:NBN:no-21798.
[KM04] Paul Kolesnik e W. Marcelo. “Recognition, Analysis and Performan-
ce with Expressive Conducting Gestures”. In: In Proceedings of the
International Computer Music Conference. 2004.
[LKB06] Eric Lee, Thorsten Karrer e Jan Borchers. “Toward a Framework for
Interactive Systems to Conduct Digital Audio and Video Streams”. In:
Comput. Music J. 30.1 (mar. 2006), pp. 21–36. issn: 0148-9267. doi:
10.1162/014892606776021317. url: http://dx.doi.org/10.1162/
014892606776021317.
29
30 BIBLIOGRAFIA
[MAJ04] D. Murphy, T. H. Andersen e K. Jensen. “Conducting Audio Files
via Computer Vision”. In: Gesture-Based Communication in Human-
Computer Interaction. Springer Berlin / Heidelberg, 2004, pp. 529–
540.
[MHO91] Hideyuki Morita, Shuji Hashimoto e Sadamu Ohteru. “A Computer
Music System that Follows a Human Conductor”. In: Computer 24.7
(lug. 1991), pp. 44–53. issn: 0018-9162. doi: 10.1109/2.84835. url:
http://dx.doi.org/10.1109/2.84835.
[MN00] Teresa Marrin Nakra. “Inside the conductor’s jacket: analysis, interpre-
tation and musical synthesis of expressive gesture”. AAI0801701. Tesi
di dott. 2000.
[Ots79] N. Otsu. “A threshold selection method from gray-level histograms”.
In: IEEE Transactions on Systems, Man and Cybernetics 9.1 (gen.
1979), pp. 62–66.
[SFW10] Andrew Schmeder, Adrian Freed e David Wessel. “Best Practices for
Open Sound Control”. In: Linux Audio Conference. Utrecht, NL, 2010.
[WF97] Matthew Wright e Adrian Freed. “Open Sound Control: A New Pro-
tocol for Communicating with Sound Synthesizers”. In: International
Computer Music Conference. Thessaloniki, Hellas: International Com-
puter Music Association, 1997, pp. 101–104. url: http://cnmat.
berkeley.edu/publications/open_sound_control_new_protocol_
communicating_sound_synthesizers.