Riconoscimento automatico della gestualità del direttore d'orchestra

36
Riconoscimento Automatico della Gestualit` a del Direttore d’Orchestra Relatore: Prof. Goffredo Haus Correlatore: Dott. Davide Andrea Mauro Correlatore: Dott. Stefano Baldan Tesi di Laurea di Tommaso Matticchio Matricola n. 715751 Anno Accademico 2011/2012

description

Testi di laurea triennale di Tommaso Matticchio

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

2

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

ii INDICE

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

6 CAPITOLO 1. DEFINIZIONE DEL PROGETTO

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.

12 CAPITOLO 2. ALGORITMI UTILIZZATI

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

28 CAPITOLO 4. CONSIDERAZIONI FINALI

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.