In questo articolo vedremo come sia possibile elencare le web cam disponibili nel nostro pc e come sia possibile selezionarne una da utilizzare con Intel Perceptual SDK.
I moduli della piattaformaLe web cam vengono viste dalla piattaforma Intel come dei moduli (alla stregua del riconoscimento facciale, delle gesture o del riconoscimento vocale).
Un modulo altro non è che l'implementazione di funzionalità della piattaforma stessa.
Per questo motivo, recuperare le web cam disponibili si traduce nel recuperare l'elenco dei moduli di un certo tipo presenti nella piattaforma.
Vediamo prima di entrare nello specifico delle web cam cosa significa recuperare i moduli della piattaforma.
I moduli sono strutturati gerarchicamente e suddivisi per funzionalità esposte come mostrato nella seguente figura:
Possiamo vedere, ad esempio, che la piattaforma supporta il modulo di Video Capture e che, nel caso di specie, questo è supportato da due device presenti nel PC (Integrated WebCam e Creative GestureCam).
Recuperare i moduliIl primo step, quindi, è recuperare làeòenco dei moduli disponibili.
In sostanza, un modulo, altro non è che l'implementazione di una o più interfacce dell'SDK e, quindi, per conoscere quali implementazioni sono disponibili, è sufficiente "chiederlo" all'SDK stesso.
Per questo ci viene in aiuto il metodo QueryImpl della classe PXCMSession che consente di riempire una struttura (la PXCMSession.ImplDesc) contenente tutti i dati relativi ad un singolo modulo.
Per recuperare l'elenco completo dei moduli a nostra disposizione, dobbiamo procedere in questo modo:
- creare un'istanza di PXCMSession (metodo statico CreateInstance);
- richiamare il metodo QueryImpl per recuperare la struttura ImplDesc.
Il codice per il recupero dei moduli è il seguente:
Public Function EnumerateAllModules() As List(Of String)
Dim session As PXCMSession = Nothing
Dim status As pxcmStatus = PXCMSession.CreateInstance(Session)
If status <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Return Nothing
Dim modules = New List(Of String)
Dim modIndex As UInteger = 0
Do
Dim modDesc As PXCMSession.ImplDesc
If session.QueryImpl(modIndex, modDesc) <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Exit Do
modules.Add(modDesc.friendlyName.get())
modIndex = modIndex + CUInt(1)
Loop While True
session.Dispose()
Return modules
End Function
Osserviamo che dobbiamo iterare su di un indice (modIndex) fino a che non otteniamo un risultato diverso da pxcmStatus.PXCM_STATUS_NO_ERROR. Questa modalità è, come abbiamo già visto per il face detection, standard nel mondo Perceptual.
La struttura PXCMSession.ImplDesc è mostrata nella seguente figura:
Tra gli attributi esposti da PXCMSession.ImplDesc troviamo:
- friendlyName : contiene il nome del modulo (da recuperare tramite il metodo get());
- group : è un'enumerazione (PXCMSession.ImplGroup) a maschera di bit che identifica il gruppo fnzionale del modulo. Ad esempio il modulo Video Capture appartiene al modulo IMPL_GROUP_SENSOR, mentre il Face Analysis appartiene al gruppo IMPL_GROUP_OBJECT_RECOGNITION). L'elenco completo dei valori è riportato nella seguente figura:
- subgroup : è un'enumerazione (PXCMSession.ImplSubgroup, anch'essa a maschera di bit) che definisce un sottogruppo specifico di funzionalità che caratterizza un modulo. Ad esempio il modulo denominato "Hand/Finger Tracking and Gesture Recognition" appartiene al gruppo IMPL_GROUP_OBJECT_RECOGNITION e al sottogruppo IMPL_SUBGROUP_GESTURE_RECOGNITION. L'elenco completo dei valori è riportato dalla seguente figura
- vendor : è un intero che identifica il produttore del modulo (Intel ha il valore 0x8086);
- version : identifica la versione del modulo.
Nel codice mostrato in precedenza abbiamo recuperato l'intero elenco dei moduli, ma l'SDK ci mette a disposizione anche un overload del metodo QueryImpl che consente di "filtrare" la ricerca dei moduli in base al group e al subgroup desiderati.
Ad esempio se volessimo recuperare tutti i moduli che supportano il video capture, potremo utilizzare il seguente codice:
Public Function EnumerateWebCamModules() As List(Of String)
Dim session As PXCMSession = Nothing
Dim status As pxcmStatus = PXCMSession.CreateInstance(session)
If status <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Return Nothing
Dim desc = New PXCMSession.ImplDesc()
desc.group = PXCMSession.ImplGroup.IMPL_GROUP_SENSOR
desc.subgroup = PXCMSession.ImplSubgroup.IMPL_SUBGROUP_VIDEO_CAPTURE
Dim modules = New List(Of String)
Dim modIndex As UInteger = 0
Do
Dim modDesc As PXCMSession.ImplDesc
If session.QueryImpl(desc, modIndex, modDesc) <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Exit Do
modules.Add(modDesc.friendlyName.get())
modIndex = modIndex + CUInt(1)
Loop While True
session.Dispose()
Return modules
End Function
La differenza rispetto al precedente è nella creazione della struittura desc di tipo PXCMSession.ImplDesc che ci serve da filtro di ricerca e che utilizziamo nella chiamata al metodo QueryImpl.
Recuperare le device che implementano i moduliUna volta recuperato un modulo tramite la QueryImpl, possiamo cercare di recuperare le device presenti nel sistema in grado di gestirlo.
Per fare questo possiamo procedere in questo modo:
- richiedere all'SDK di create l'implementazione definita del modulo in oggetto (istanza della classe PXCMCapture)
- se l'implementazione può essere creata (significa che esiste qualche device in grado di gestirlo), possiamo recuperare l'elenco delle device utilizzando il metodo QueryDevice della classe PXCMCapture.
Public Function EnumerateAllDevices() As List(Of String)
Dim session As PXCMSession = Nothing
Dim status As pxcmStatus = PXCMSession.CreateInstance(session)
If status <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Return Nothing
Dim devices = New List(Of String)
Dim modIndex As UInteger = 0
Do
' recupero le informazioni sul modulo
Dim desc1 As PXCMSession.ImplDesc
If session.QueryImpl(modIndex, desc1) <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Exit Do
' provo a ricchiedere l'implementazione del modulo
Dim capture As PXCMCapture = Nothing
If session.CreateImpl(Of PXCMCapture)(desc1, PXCMCapture.CUID, capture) = pxcmStatus.PXCM_STATUS_NO_ERROR Then
Dim devIndex As UInteger = 0
Do
' Recupero le informazioni sul device
Dim dinfo As PXCMCapture.DeviceInfo
If capture.QueryDevice(devIndex, dinfo) <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Exit Do
devices.Add(String.Format("{0} - [{1}]", dinfo.name.get(), desc1.friendlyName.get))
devIndex = devIndex + CUInt(1)
Loop While True
capture.Dispose()
End If
modIndex = modIndex + CUInt(1)
Loop While True
session.Dispose()
Return devices
End Function
Quello che possiamo notare è che, una volta ottenuto il modulo (le cui informazioni sono contenute nella variabile desc1), proviamo a recuperare l'implementazione dello stesso (grazie al metodo CreateImpl della classe PXCMSession) e, infine, se questo è disponibile, richiediamo le device utilizzando il metodo QueryDevice della classe PXCMCapture che, in caso positivo, riempie la struttura PXCMCapture.DeviceInfo.
L'attributo name della struttura PXCMCapture.DeviceInfo fornisce il nome del device che può essere utilizzato per selezionare il device stesso per làutilizzo.
Se proviamo ad eseguire il precedente codice su un ultrabook con la Creative Gesture Cam collegata potremmo ottenere:
Abbiamo visto, in precedenza, come recuperare l'elenco delle device disponibili all'interno del sistema.
In particolare per recuperare solo ed esclusivamente le webcam, possimao utilizzare il seguente pezzo di codice:
Public Function FillDeviceList() As List(Of String)
Dim session As PXCMSession = Nothing
Dim status As pxcmStatus = PXCMSession.CreateInstance(session)
If status <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Return Nothing
Dim desc = New PXCMSession.ImplDesc()
desc.group = PXCMSession.ImplGroup.IMPL_GROUP_SENSOR
desc.subgroup = PXCMSession.ImplSubgroup.IMPL_SUBGROUP_VIDEO_CAPTURE
Dim devices = New List(Of String)
Dim devIndex As UInteger = 0
Do
Dim desc1 As PXCMSession.ImplDesc
If session.QueryImpl(desc, devIndex, desc1) <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Exit Do
If desc1.subgroup = PXCMSession.ImplSubgroup.IMPL_SUBGROUP_VIDEO_CAPTURE Then
Dim capture As PXCMCapture
If session.CreateImpl(Of PXCMCapture)(desc1, PXCMCapture.CUID, capture) = pxcmStatus.PXCM_STATUS_NO_ERROR Then
Dim subDevIndex As UInteger = 0
Do
Dim dinfo As PXCMCapture.DeviceInfo
If capture.QueryDevice(subDevIndex, dinfo) <> pxcmStatus.PXCM_STATUS_NO_ERROR Then Exit Do
devices.Add(dinfo.name.get())
subDevIndex = subDevIndex + CUInt(1)
Loop While True
capture.Dispose()
End If
End If
devIndex = devIndex + CUInt(1)
Loop While True
session.Dispose()
Return Devices
End Function
Nel codice recuperiamo i moduli di gruppo IMPL_GROUP_SENSOR e sottogruppo IMPL_SUBGROUP_VIDEO_CAPTURE e selezioniamo quelli che hanno il solo sottogruppo IMPL_SUBGROUP_VIDEO_CAPTURE (tralasciamo, tanto per fare un esempio la parte infrarossi della Creative Gesture Cam che ha come sottogruppo sia il IMPL_SUBGROUP_VIDEO_CAPTURE che il IMPL_SUBGROUP_VOICE_RECOGNITION).
Se utilizziamo la UtilMPipeline per gestire il flusso di dati provenienti dall'SDK, ci basta impostare il device utilizzando il metodo SetFilter della classe UtilMCapture ottenuta, a partire dalla UtilMPipeline, tramite il metoro QueryCapture:
Dim capture = QueryCapture()
If capture IsNot Nothing Then
capture.SetFilter(DeviceName)
End If