Passa ai contenuti principali

Kinect: gli scheletri e l’uomo vitruviano

Continuando la carrellata di ciò che è cambiato nel nuovo SDK del Kinect rispetto alla beta2, eccoci all’uomo vitruviano (vedi post).

E’ oramai noto che uno degli aspetti più interessanti del Kinect è il fatto che il suo SDK è in grado di fornirci la posizione di alcuni punti ben determinati dei player inquadrati e riconosciuti dal sensore.

L’insieme di questi punti (20 per la precisione) per ogni player è detto Skeleton e i punti sono mostrati in figura:

skeleton joints

L’SDK è in grado di ritornare una collection di oggetti di tipo Joint, ognuno dei quali rappresenta i dati spaziali del singolo punto.

Cominciamo dal vedere come accedere al sensore Kinect e attivare il riconoscimento dello scheletro (Skeletal Tracking).

Come già visto nei precedenti due post della serie, il meccanismo per accedere al Kinect è quello di passare dalla collezione KinectSensors della classe KinectSensor, registrare l’opportuno gestore di evento e abilitare lo stream che ci interessa:

  1. If KinectSensor.KinectSensors.Any() Then
  2.     Sensor = KinectSensor.KinectSensors(0)
  3.     If Sensor.Status = KinectStatus.Connected Then
  4.         AddHandler Sensor.SkeletonFrameReady, AddressOf SkeletonFrameHandler
  5.         Sensor.SkeletonStream.Enable()
  6.         Try
  7.             Sensor.Start()
  8.         Catch ex As Exception
  9.  
  10.         End Try
  11.     End If
  12. End If

L’evento SkeletonFrameReady viene sollevato dall’SDK del Kinect ogni volta che un nuovo frame contenente gli Skeleton è pronto.

La figura seguente mostra la struttura delle classi coinvolte nell’argomento dell’evento SkeletonFrameReady:

image

Come già visto per il video e la profondità, anche in questo caso, l’effettivo frame viene ottenuto utilizzando il metodo OpenSkeletonFrame.

Osserviamo che, a differenza della Beta2, la classe SkeletonFrame non ha più le proprietà NormalToGravity e Quality (poco significative) e la proprietà FloorClipPlane è di tipo Tuple(Of Single, Single, Single, Single) anziché Vector.

La proprietà FloorClipPlane fornisce i coefficienti dell’equazione del piano di terra (pavimento) stimata dall’SDK. L’equazione ha la forma:

Ax+By+Cz+D=0

dove:
    A = FloorClipPlane.Item1
    B = FloorClipPlane.Item2
    C = FloorClipPlane.Item3
    D = FloorClipPlane.Item4

L’equazione del piano è normalizzata, quindi D rappresenta, di fatto, l’altezza della camera rispetto al pavimento. Anche in questa versione dell’SDK, come nella versione Beta, il vettore è sempre nullo.

Una volta ottenuta l’istanza dello SkeletonFrame, possiamo utilizzare il metodo CopySkeletonDataTo  per recuperare gli effettivi dati degli scheletri:

  1. Private Skeletons() As Skeleton = New Skeleton(6) {}
  2.  
  3. Private Sub SkeletonFrameHandler(sender As Object, e As SkeletonFrameReadyEventArgs)
  4.     Dim skeletonFrame = e.OpenSkeletonFrame()
  5.     If skeletonFrame IsNot Nothing Then
  6.         skeletonFrame.CopySkeletonDataTo(Skeletons)
  7.         '
  8.         ' gestione degli skeleton recuperati
  9.         '
  10.     End If
  11. End Sub

La classe Skeleton (nella Beta2 si chiamava SkeletonData) contiene i dati essenziali degli scheletri e il diagramma delle classi coinvolte è il seguente:

ClassDiagram-SkeletonData

Ogni Skeleton ha un suo TrackingId che lo identifica univocamente, un TrackingState che ci dice se è tracciato o meno (ricordiamo che su 6 scheletri disponibili, solo fino a 2 sono tracciati contemporaneamente), una posizione (proprietà Position) che dovrebbe rappresentare il baricentro e una collezione di Joint (proprietà Joints).

Possiamo recuperare i singoli Joint a partire dal loro tipo (enumerazione JointType).

Questa enumerazione era già presente nella Beta2 ma il suo nome era JointId (ora è decisamente più chiara) così come la proprietà del Joint che la contiene si chiama JointType (si chiamava JointID nella Beta2).

Altri cambiamenti sono stati introdotti nelle Position (sia dello Skeleton che del Joint): nella Beta2 queste erano di tipo Vector, mentre ora sono di tipo SkeletonPoint. La SkeletonPoint non ha più la proprietà W (presente nel Vector) e non significativa nella Beta2.

Come abbiamo già visto quando abbiamo parlato del sensore di profondità, il Kinect for Windows (e, quindi, l’SDK) ha la modalità “Near Mode”.

Questa influenza non solo la minima distanza di riconoscimento di un player (come già visto nel precedente post) ma anche il numero di joint rilevati, come mostrato nella seguente tabella:

Near Mode vs Default Mode Funzionalità

La tabella va necessariamente spiegata perchè fuorviante: nel caso di Near Mode, la classe Skeleton valorizza la sola proprietà Position (e solo se l’intero scheletro è tracciato), quindi il punto denominato “Center Hip Joint” non è il Joint “HipCenter” (uno dei 20 a disposizione) anche se, in prima approssimazione, possiamo pensarli coincidenti.

Per poter passare nella modalità “Near Mode” si deve intervenire sulla proprietà Range del DepthStream esposto dal KinectSensor impostandola a KinectRange.NearMode.

Se si imposta la proprietà Range del DepthStream quando questo non è stato abilitato tramite il metodo Enable, non si ottiene alcun errore, ma il sensore non va il modalità near mode.

L’applicazione proposta in allegato mostra, istante per istante, le posizioni dei 20 punti sensibili dello skeletal tracking, come mostrato in figura:

15-03-2012 20-34-50

 

 

Commenti

Unknown ha detto…
How to use the SDK version ?
Massimo Bonanni ha detto…
This post is based on Kinect V1 and its SDK. You can use the code that you can find in this post with Kinect SDK 1.8.

Post popolari in questo blog

VB.NET for Dummies: Gli Eventi

Vorrei iniziare con questo post una serie dedicata ad aspetti di VB.NET di base che possono essere utile a coloro che si avvicinano al mondo .NET e che, in genere, non vengono trattati a livello base. La serie di post non ha la pretesa di essere assolutamente esaustivi sugli argomenti che tratterò In questo primo post parleremo degli eventi. Cosa sono e a cosa servono Un evento è la “notifica” dell’accadimento di qualcosa. Quando, ad esempio, premiamo un bottone della finestra di un’applicazione, dietro le quinte, il bottone stesso “notifica” al mondo circostante che qualcuno, in quell’istante, lo ha premuto. Sta, poi, al mondo circostante preoccuparsi di “intercettare” l’evento stesso per gestirlo (tramite un gestore di evento). Attenzione a non confondere la pressione del tasto con la “notifica” della pressione del tasto: l’evento è la “notifica” dell’accadimento, non l’accadimento stesso. Ma a cosa serve tutto ciò? Utilizzare gli eventi è un modo per disaccoppiare ...

VB.NET: SplashScreen con effetto fade-in

In questo post vorrei proporvi un modo per realizzare una splash screen per le nostre applicazioni Windows Form che appare progressivamente con un effetto fade. Supponiamo di avere il nostro progetto VB.NET in una soluzione Visual Studio 2008 in cui abbiamo il sorgente della nostra applicazione Windows Form. Inseriamo una splash screen utilizzando il menù Progetto->Aggiungi Nuovo Elemento e selezionando il tipo di elemento “Schermata Iniziale” A questo punto Visual Studio creerà, automaticamente, la schermata iniziale che possiamo personalizzare graficamente come vogliamo. Per poter fare in modo che questa finestra appaia nel momento in cui avviamo l’applicazione, è necessario aprire le proprietà del progetto e impostare la maschera di avvio: In questo modo, all’avvio dell’applicazione, la schermata appare immediatamente e scompare un attimo prima della visualizzazione della finestra dell’applicazione. Possiamo far apparire la schermata iniziale con un ef...

Alla scoperta del Kinect: presentazioni e convenevoli

Oggi è arrivato un Kinect nuovo nuovo su cui cominciare a fare sperimentazione ed ho, quindi, deciso di condividere tutto ciò che scopro, le cavolate che faccio e i segreti che scopro con chi mi segue. I post che cercherò di scrivere con frequenza sono post di un neofita che si avvicina all’”Aggeggio” e che quindi sono diretti a chi nulla dell’argomento. Gli esperti troveranno noiosi e banali questi post, ma non si può aver tutto dalla vita. Per cominciare, scartato l’”Aggeggio” ho cominciato a preparare l’ambiente di sviluppo: 1) Visual Studio 2010 Ultimate (che uso normalmente ma che non è necessario in quanto si può sviluppare tranquillamente con la express edition); 2) Kinect SDK, scaricabile all’indirizzo http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/download.aspx 3) DirectX Software Development Kit scaricabile all’indirizzo http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=6812 A questo punto vi basta connettere il Kinect al...