Introduzione a Intel Perceptual Computing SDK: Gesture Recognition

In questo articolo ci occuperemo di analizzare cosa ci mette a disposizione Intel Perceptual Computing SDK riguardo le funzionalità di Gesture Recognition.

La classe PXCMGesture

Tutte le funzionalità di gesture recognition della piattaforma sono esposte dalla classe PXCMGesture o da sue classi innestate.

In realtà la classe di occupa di gestire sia le funzionalità tipice del gesture recognition (riconoscimento di posture e gesture dell'utente) che di fornire i dati di finger tracking e hand tracking (di cui ci occuperemo in un successivo articolo).

Come già visto nei precedenti articoi della serie, realizziamo una nostra versione della pipeline fornita dalla piattaforma che esponga le funzionalità di gesture recognition e , al solito, creiamo la nostra classe derivando quella della piattaforma:

Public Class GesturePipeline
    Inherits UtilMPipeline
 
    Public Event ImageCaptured(sender As Object, e As ImageCapturedEventArgs)
    Public Event GestureCaptured(sender As Object, e As GestureCapturedEventArgs)
    Public Event PipelineStarted(sender As Object, e As EventArgs)
    Public Event PipelineStopped(sender As Object, e As EventArgs)
    Public Event PipelineError(sender As Object, e As EventArgs)
 
    Public Sub New()
        MyBase.New()
        EnableImage(PXCMImage.ColorFormat.COLOR_FORMAT_RGB24)
        EnableGesture()
    End Sub
 
    Private LoopFramesThread As Thread
    Public Overrides Function LoopFrames() As Boolean
        If LoopFramesThread Is Nothing Then
            LoopFramesThread = New Thread(New ThreadStart(AddressOf LoopFramesCode))
            LoopFramesThread.Start()
            Return True
        Else
            Return False
        End If
    End Function
 
    Private Sub LoopFramesCode()
        Try
            RaiseEvent PipelineStarted(Me, EventArgs.Empty)
            Dim result = MyBase.LoopFrames()
            If Not result Then RaiseEvent PipelineError(Me, EventArgs.Empty)
        Catch ex As Exception
            RaiseEvent PipelineStopped(Me, EventArgs.Empty)
        End Try
    End Sub
 
    Public Overrides Sub OnImage(image As PXCMImage)
        Dim data As PXCMImage.ImageData
        Dim status = image.AcquireAccess(PXCMImage.Access.ACCESS_READ,
                                         PXCMImage.ColorFormat.COLOR_FORMAT_RGB32, data)
        If status = pxcmStatus.PXCM_STATUS_NO_ERROR Then
            Dim width As UInt32
            Dim height As UInt32
            Dim colorFormat As PXCMImage.ColorFormat
            If image.GetImageInfo(width, height, colorFormat) Then
                Dim bitmap As Bitmap = data.ToBitmap(width, height)
                RaiseEvent ImageCaptured(Me, New ImageCapturedEventArgs() With {.Image = bitmap, .TimeStamp = DateTime.Now})
                image.ReleaseAccess(data)
            End If
        End If
    End Sub
 
 ' funzionalità di gesture capture
 '
 '
 
End Class

Prima cosa da notare è la presenza della chiamata EnableGesture() nel costruttore della pipeline necessaria per abilitare il gesture recognition (se non la eseguiamo, otterremo errore quando cercheremo di accedere alle funzionalità specifiche di gesture recognition).

L'evento GestureCaptured è sollevato dalla pipeline quando una gesture viene riconosciuta dal sistema.

Per interagire con la piattaforma ed ottenere dati sulle eventuali gesture riconosciute, possiamo procedere in due modi.

Il primo è utilizzare il metodo OnGesture della UtilMPipeline. Questo viene richiamato dalla piattaforma ogni volta che si ha una notifica della presenza di una gesture o di una posture.

Il metodo OnGesture fornisce i dati della gesture riconosciuta che possono essere utilizzati per capire quale gesture si è verificata. Nel nostro caso solleviamo l'evento GestureCaptured:

Public Overrides Sub OnGesture(ByRef gesture As PXCMGesture.Gesture)
    RaiseEvent GestureCaptured(Me,New GestureCapturedEventArgs() With {.GestureData = gesture})
End Sub

Il metodo OnGesture viene richiamato dalla piattaforma una volta quando viene riconosciuta una gesture e una volta quando la stessa non è più presente (nel secondo caso il flag di gesture attiva dei dati di gesture è false).

Un altro modo per ricavare l'eventuale gesture riconosciuta, è quello di eseguire esplicitamente la richiesta della stessa nel metodo OnNewFrame (come fatto nei precedenti tutorial per il face detection e face recognition).

In questop caso dobbiamo utilizzare la classe PXCMGesture e, in particolare, il metodo QueryGestureData della stessa:

Public Overrides Function OnNewFrame() As Boolean
    Using gesture = QueryGesture()
        Dim data As PXCMGesture.Gesture
        Dim index As UInt16 = 0
        Do While True
            Dim status = gesture.QueryGestureData(0, PXCMGesture.GeoNode.Label.LABEL_ANY, index, data)
            If status = pxcmStatus.PXCM_STATUS_NO_ERROR Then
                RaiseEvent GestureCaptured(Me, New GestureCapturedEventArgs() With {.GestureData = data})
            Else
                Exit Do
            End If
            index = CUShort(index + 1)
        Loop
    End Using
    Return True
End Function

Come possiamo osservare dal precedente codice, otteniamo l'istanza della classe PXCMGesture grazie al metodo QueryGesture della UtilMPipeline.

Una volta ottenuta l'istanza di PXCMGesture, possiamo utilizzare il metodo QueryGestureData per ottenere le informazioni delal gesture stessa.

Il metodo QueryGestureData funziona in maniera analoga a tutte le funzioni di tipo QueryXXXX già viste nei precedenti tutorial (ad esempio la QueryFace vista nel face detection), cioè è necessario iterare sull'indice delle gesture attive fino a che si ottiene un risultato (pxcmStatus) negativo. Si tratta di una specie di polling.

Da segnalare che la QueryGestureData accetta tra i suoi parametri anche la parte del corpo di cui desideriamo ricercare le gesture. Nel nostro caso specifico stiamo richiedendo qualsiasi parte del corpo.

Questa tecnica, a differenza di quella dell'override di OnGesture genera un treno di eventi GestureCapured (la cui frequenza dipende dal frame rate) che dura fino a quando la gesture rimene nel raggio della camera. La grossa differenza la si per le posture: nel caso di OnGesture avremo due soli eventi, nel caso del polling una serie di eventi.

Posture e Gesture

L'SDK è in grado di riconoscere posture (pose) e gesture.

Una posture altro non è che il posizionamento di una parte del corpo (tipicamente la mano) con una postura che rimane fissa nel tempo. Un esempio è  il pollice verso o la mano aperta.

Una gesture, invece, e' la variazione nel tempo e nello spazio di una parte del corpo.

Intel Perceptual Computing SDK prevede alcune posture e gesture di serie, ma nel pieno spirito della piattaforma consente di creare i propri moduli per le proprie gesture e posture.

Le gesture previste, di serie, dalla piattaforma si possono dividere in tre categorie, due appartenenti alle gesture e una alle posture.

La seguente figura mostra le gesture supportate di default:

Un discorso particolare va fatto per le gesture di swipe. Riconoscere in maniera accurata uno swipe, considerato che si tratta di un movimento di una mano nello spazio tridimensionale e nel tempo, non è banale e, per questo motivo, l'utente dovrebbe eseguire tale gesture immaginando di avere un piano virtuale parallelo alla camera e a circa 30 cm (12 pollici) dalla stessa. Il movimento di swipe dovrebbe per prima cosa entrare attraverso il piano da un lato, viaggiare all'interno di questo e riuscire dal lato successivo, come mostrato nella seguente figura:

La classe PXCMGesture.Gesture

In entrambe le modalità di utilizzo delle funzionalità di gesture recognition viste in precedenza, il risultato del riconoscimento della gesture è un'istanza della classe PXCMGesture.Gesture (mostrata nella seguente figura):

Gli attributi sono:

  • active : l'attributo è valido esclusivamente per le posture ed ha senso solo se stiamo utilizzando l'override del metodo OnGesture ed indica se la posture è attiva o no;  
  • body : indica la parte del corpo che sta eseguendo la gesture (0 se non è disponibile). E' un valore dell'enumerazione PXCMGesture.GeoNode.Label:

  • confidence : indica il valore di confidence del rilevamento che può variare da zero a 100;
  • label : contiene il valore di PXCMGesture.Gesture.Label che indica la gesture rilevata;
  • user : contiene il numero dell'utente che ha eseguito la gesture (o 0 se non è disponibile);
  • timestamp : timestamp (in 100ns) del momento in cui è rilevata la gesture. Può essere utilizzato nelle sincronizzazioni tra differenti utenti.

Le funzionalità di gesture recognition sono disponibili solo se si ha a disposizione la Creative Gesture Cam mentre non possono essere utilizzate con la normale camera del nostro nultrabook.

Nella solution allegata a questo articolo trovate un esempio di applicazione Windows Form per il riconoscimento di gesture.

Para obter informações mais completas sobre otimizações do compilador, consulte nosso aviso de otimização.