Passa ai contenuti principali

Kinect: cosa cambia nella nuova SDK

Con questo post vorrei iniziare una serie dedicata alle novità e ai cambiamenti presenti nell’SDK rilasciato il 1 febbraio 2012.

Cominciamo con riportare il link del portale Kinect in cui trovare il pacchetto di installazione dell’SDK e le risorse necessarie per cominciare a lavorare con lo stesso.

In questi post prenderò spunto dagli esempi che avevo a suo tempo riportato in un’analoga serie di post (ai tempi della beta2) e proverò di farli funzionare nuovamente con il nuovo SDK analizzando ciò che è cambiato.

Installato l’SDK, abbiamo a disposizione un browser che ci permette di accedere facilmente alla documentazione e agli esempi.

SNAGHTML1cbd41a8

Prima cosa che balza all’occhio quando tentiamo di utilizzare l’assembly contenente le classi di gestione del Kinect è che l’assembly da referenziare non è più Microsoft.Research.Kinect.dll ma Microsoft.Kinect.dll.

In maniera analoga, il namespace principale delle classi dell’SDK non è più Microsoft.Research.Kinect ma Microsoft.Kinect.

La classe principale utilizzata nella Beta2 per accedere alle funzionalità del Kinect era la classe Runtime, nella versione 1.0 questa è completamente sparita ed è sparito anche il modo con cui si accede alla classe di gestione del Kinect.

La classe Runtime è stata sostituita dalla classe KInectSensor contenuta nel namespace Microsoft.Kinect.

Il seguente disegno mostra la struttura della classe KinectSensor:

KinectSensor class

La classe KinectSensor non ha costruttori ma espone una proprietà Shared chiamata KinectSensors che ci consente di avere a disposizione l’elenco dei sensori Kinect attaccati al nostro PC (fino a 4) e rilevati dal sistema. Altra cosa importante (di cui ci occuperemo in un prossimo post) è l’esistenza dell’evento AllFrameReady il cui scopo è quello di fornire dei frame sincronizzati per le sorgenti abilitate.

Possiamo, quindi, accedere al nostro Kinect nel seguente modo:

  1. If KinectSensor.KinectSensors.Any() Then
  2.     Sensor = KinectSensor.KinectSensors(0)
  3. End If

dove Sensor è la variabile che utilizzeremo per accedere al dispositivo.

Una volta recuperata l’istanza della classe per la gestione del Kinect, dobbiamo sottoscrivere gli eventi da gestire per i frame che arrivano dal dispositivo e aprire gli opportuni stream.

Anche per questo, ci sono stati dei cambiamenti. In particolare, l’evento VideoFrameReady della vecchia Runtime, è stato rinominato in ColorFrameReady e l’attivazione degli stream non avviene più con il metodo Initialize (che apriva gli stream e avviava la gestione degli stessi) ma richiamando il metodo Enable (o Disable per disabilitare) delle proprietà ColorStream, DepthStream o SkeletonStream (in base a quale stream gestire) seguito dal metodo Start.

Il metodo Enable prevede, nel caso del ColorStream, la possibilità di passare come argomento la risoluzione delle immagini da recuperare. La presenza dell’Enable e del Disable fa si che si possano attivare e disattivare i flussi provenienti dal Kinect “a caldo” senza dover fermare l’istanza del KinectSensor e riavviarla.

Ad esempio per gestire una risoluzione video di 640x480 a 30 fps, possiamo scrivere:

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

La proprietà Status della KinectSensor ci consente di sapere lo stato del sensore (nel nostro caso se è connesso) in modo da eseguire le operazioni di apertura degli stream e di aggancio degli eventi solo se effettivamente il sensore è connesso.

Anche la firma del gestore dell’evento ColorFrameReady è cambiata rispetto alla firma del precedente evento presente nella classe Runtime.

  1. Private Sub ColorFrameReadyHandler(sender As Object, e As ColorImageFrameReadyEventArgs)
  2.  
  3. End Sub

L’argomento ColorImageFrameReadyArgs permette di accedere alle informazioni relative al frame recuperato dal Kinect

image


Da notare la presenza del metodo OpenColorImageFrame per recuperare l’istanza della classe ColorImageFrame che è il vero contenitore dei dati provenienti dalla video camera del Kinect.



Per ottenere l’array di byte costituenti l’immagine effettiva è necessario definire un array di byte della lunghezza pari a PixelDataLenght e copiarvi dentro i dati con il metodo CopyPixelDataTo().







  1. Using colorImageFrame = e.OpenColorImageFrame()

  2.     If colorImageFrame IsNot Nothing Then

  3.         Dim imageArray() = New Byte(colorImageFrame.PixelDataLength - 1) {}

  4.         colorImageFrame.CopyPixelDataTo(imageArray)

  5.         '

  6.         ' Gestione dell'array dati proveniente dal Kinect

  7.         '

  8.     End If

  9. End Using






Dato l’array di byte possiamo creare una BitmapSource e possiamo visualizzare la stessa all’interno, ad esempio, di un controllo image WPF:







  1. Private Sub ColorFrameReadyHandler(sender As Object, e As ColorImageFrameReadyEventArgs)

  2.     Dim colorImageFrame = e.OpenColorImageFrame()

  3.     Dim imageArray(colorImageFrame.PixelDataLength) As Byte

  4.     colorImageFrame.CopyPixelDataTo(imageArray)

  5.     Dim stride = colorImageFrame.Width * colorImageFrame.BytesPerPixel

  6.     Me.VideoImage.Source = BitmapSource.Create(colorImageFrame.Width, colorImageFrame.Height,

  7.                                                96, 96,

  8.                                                PixelFormats.Bgr32, Nothing,

  9.                                                imageArray, stride)

  10. End Sub






Ogni volta che l’SDK avrà ricevuto un frame dalla video camera del dispositivo, richiamerà il nostro gestore di evento e visualizzeremo l’immagine corrispondente.



Infine, nel momento in cui dobbiamo chiudere la nostra applicazione e rilasciare la classe di gestione del Kinect, possiamo utilizzare il metodo Stop (per fermare il flusso degli stream e il Dispose per rilasciare effettivamente l’istanza:







  1. If Sensor IsNot Nothing Then

  2.     If Sensor.IsRunning Then

  3.         Sensor.Stop()

  4.         Sensor.Dispose()

  5.     End If

  6. End If






Prima di concludere questo primo post, un accenno allo stride di una immagine per capire meglio il codice precedente.



Quando memorizziamo una immagine in memoria, in realtà, questa è memorizzata in un buffer che potrebbe contenere dei byte in più rispetto a quelli necessari a memorizzare l’immagine stessa (vedi figura). Questi byte in più non influenzano la visualizzazione ma solo lo spazio occupato.



IC156482



Lo stride di un’immagine altro non è che la lunghezza di una riga della precedente matrice buffer. Nella fattispecie è data dalla larghezza del frame per il numero di byte per pixel.



In allegato trovate una solution di esempio:




 



Commenti

Post popolari in questo blog

VB.NET : Aggregare stringhe con LINQ

Tip facile facile, ma a qualcuno potrebbe servire. Supponiamo di avere una lista di stringhe (magari come risultato di una query LINQ) e di voler ottenere una stringa con la concatenazione delle stesse: Dim list = CreateList() Dim concatStr = (From s In list _ Select s).Aggregate( Function (currentString, nextString) currentString + nextString) MessageBox.Show(concatStr) Il metodo CreateList non ci interessa, in questo momento, ma crea una lista di oggetti String. Protected Function CreateList() As IEnumerable( Of String ) Dim list As String () = {" stringa1 ", " stringa2 ", " stringa3 ", " stringa4 ", " stringa5 "} Return list.AsEnumerable() End Function Questo metodo potrebbe restituire una qualsiasi lista di oggetti di cui, nella select successiva recuperiamo solo stringhe. La stessa tecnica è utilizzabile per concatenare stringhe inserendovi un carattere separatore Dim list = CreateList() Dim

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

VB.NET: Convertire un file DOC in RTF e PDF con office interop

In questo post vorrei proporvi del codice per poter convertire un file .doc in un file .rtf oppure .pdf utilizzando le API di interoperabilità di Office. Creeremo una classe, DocConverter, che esporrà le due funzionalità sopra citate. Cominciamo con il prevedere un attributo privato della classe che rappresenterà l’applicazione Word che utilizzeremo per la conversione. Creeremo l’istanza dell’attributo privato all’interno del costruttore della classe: Public Sub New () If Not CreateWordApp() Then Throw New ApplicationException(" Assembly di interoperabilità con Office non trovato! ") End If End Sub Private _wordApp As Word.ApplicationClass Protected Function CreateWordApp() As Boolean Dim retval = True Try _wordApp = New Word.ApplicationClass() _wordApp.Visible = False Catch ex As System.Exception _wordApp = Nothing retval = False End Try Return retval End Function La conve