Passa ai contenuti principali

Alla scoperta del Kinect : utilizzo del Kinect in modalità polling

Nei precedenti post abbiamo visto che il Kinect ci mette a disposizione una serie di eventi che ci permettono di recuperare i frame video, di profondità o gli skeleton data.

Possiamo utilizzare le potenzialità del Kinect anche senza fare ricorso alla gestione di tali eventi ma utilizzando una tecnica di polling sugli streams.

Partiamo dall’inizio: la classe Runtime (già vista in precedenza) ci mette a disposizione 3 proprietà utilissime in questo contesto e che contengono proprio gli stream di cui sopra.

image

  • VideoStream : è un’istanza di ImageStream che incapsula lo stream video;
  • DepthStream : è un’istanza di ImageStream che incapsula lo stream dei dati di profondità;
  • SkeletonEngine : è il motore di skeletal Tracking che permette l’accesso ai frem di skeleton data.

In particolare osserviamo la presenza, in tutte le classi in gioco, del metodo GetNextFrame il cui risultato è un oggetto di tipo ImageFrame per il VideoStream e per il DepthStream e SkeletonFrame per lo SkeletonEngine.

ImageFrame e SkeletonFrame sono esattamente le istanze che ci vengono restituite all’interno degli eventi della classe Runtime utilizzati in precedenza.

Per questo motivo possiamo utilizzare questo metodo per accedere allo stream e recuperare il frame che ci interessa.

L’applicazione allegata a questo post altro non fa che visualizzare lo stream video e depth utilizzando un polling.

In particolare vengono utilizzati due Task che si occupano di eseguire il “polling” accedendo ai differenti stream.

  1. Private Nui As Runtime
  2.  
  3. Private VideoWorkTask As Task
  4. Private DepthWorkTask As Task
  5. Private WorkTaskTokenSource As CancellationTokenSource
  6.  
  7. Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
  8.     Try
  9.         Nui = New Runtime
  10.         Nui.Initialize(RuntimeOptions.UseColor Or RuntimeOptions.UseDepthAndPlayerIndex)
  11.         Nui.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color)
  12.         Nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex)
  13.  
  14.         WorkTaskTokenSource = New CancellationTokenSource()
  15.  
  16.         Dim cancellationToken = WorkTaskTokenSource.Token
  17.         VideoWorkTask = New Task(New Action(Of Object)(AddressOf VideoWorkTaskCode), Nui, cancellationToken)
  18.         VideoWorkTask.Start()
  19.  
  20.         cancellationToken = WorkTaskTokenSource.Token
  21.         DepthWorkTask = New Task(New Action(Of Object)(AddressOf DepthWorkTaskCode), Nui, cancellationToken)
  22.         DepthWorkTask.Start()
  23.     Catch ex As Exception
  24.  
  25.     End Try
  26. End Sub

Viene inizializzata l’istanza di Runtime e gli stream Video e Depth, non vengono agganciati i gestori di evento ma vengono avviati due task che si occupano di recuperare i frame:

  1. Private Sub VideoWorkTaskCode(obj As Object)
  2.     Dim nui = CType(obj, Runtime)
  3.     While Not WorkTaskTokenSource.IsCancellationRequested
  4.         If nui IsNot Nothing AndAlso nui.VideoStream IsNot Nothing Then
  5.             Dim frame = nui.VideoStream.GetNextFrame(0)
  6.             If frame IsNot Nothing Then
  7.                 Dispatcher.BeginInvoke(Sub()
  8.                                            Me.VideoImage.Source = frame.ToBitmapSource()
  9.                                        End Sub)
  10.             End If
  11.         End If
  12.         System.Threading.Thread.Sleep(100)
  13.     End While
  14. End Sub
  1. Private Sub DepthWorkTaskCode(obj As Object)
  2.     Dim nui = CType(obj, Runtime)
  3.     While Not WorkTaskTokenSource.IsCancellationRequested
  4.         If nui IsNot Nothing AndAlso nui.DepthStream IsNot Nothing Then
  5.             Dim frame = nui.DepthStream.GetNextFrame(0)
  6.             If frame IsNot Nothing Then
  7.                 Dispatcher.BeginInvoke(Sub()
  8.                                            Me.DepthImage.Source = frame.ToBitmapSource()
  9.                                        End Sub)
  10.             End If
  11.         End If
  12.         System.Threading.Thread.Sleep(100)
  13.     End While
  14. End Sub

A differenza della gestione degli eventi vista nei precedenti post, in questo caso i task vengono eseguiti in threads differenti dal principale ed è, quindi, necessario l’utilizzo del Dispatcher per aggiornare l’interfaccia.

Il metodo GetNextFrame prevede un parametro che indica quanti millisecondi attendere prima di restituire il frame.

Il valore di ritorno di GetFrame può anche essere nothing (nel caso che il frame non sia ancora pronto).

Questa tecnica è un “pelino” più complicata di quella Event-Driven e deve essere utilizzata quando l’applicazione lo richiede (ad esempio abbiamo la necessità di recuperare un frame ogni x secondi).


Commenti

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...