Home Page Home Page Articoli Catturare immagini da una Webcam con .NET

Catturare immagini da una Webcam con .NET

In questo articolo mostreremo come è possibile costruire una applicazione per catturare immagini da una Webcam, utilizzando componenti già presenti in Windows, in questo caso l' Avicap32.dll
Autore: Giovanni Ferron Livello:
Tra le tante applicazioni che possiamo creare con .NET ci sono anche quelle per il divertimento personale, una di queste è l'acquisizioni di immagini tramite una Webcam. Per l'interfaccia con la nostra camera, o qualsiasi altro device di acquisizione, possiamo utilizzare diversi strumenti, ma il più indicato in questo caso è l'utilizzo della DLL di Windows avicap32.dll.
AVIcap window class (avicap32.dll) è una libreria di acquisizione che permette di interfacciarsi con dispositivi audio-visivi, senza dover preoccuparci del device. Infatti la libreria ci offre la completa l'interoperabilità con tutti i dispositivi, l'importante è che sia installata correttamente sul nostro sistema.
Il codice presente nell'articolo è VB.NET, per gli appassionati di C# troverete nei file anche la versione in C#.

Nota: L'icona del programma non è originale, ma è ricavata dal set di icone Gorilla_1.3 per KDE, distribuito in licenza GPL. Per informazioni:

http://www.kde-look.org/ ">KDE-Look

http://www.fsf.org/licenses/gpl.html ">Licenza GPL

System.Runtime.InteropServices
Il System.Runtime.InteropServices è l'assembly che fornisce un'ampia varietà di metodi che ci permettono di lavorare con COM e servizi di chiamata al sistema operativo, infatti per poter catturare il flusso della nostra webcam dobbiamo fare una chiamata al sistema per permettere al nostro applicativo di accedere alla memoria, questa richiesta deve essere inviata in una determinata posizione, la superfice che deve utilizzare e l'applicativo. In seguito bisogna connettersi al flusso e visualizzare i dati.
Per eseguire questi passi dovremo lavorare con due DLL di sistema, l'Avicap32.dll e la User32.dll, e per richiamarle è necessario creare delle funzioni che faranno da puntatori alle funzioni interne delle nostre dll.

Elenco dei devices
Prima di catturare immagini e salvare come file immagine, dobbiamo assicurarci di avere una webcam e che sia correttamente installata, per evitare sgradevoli inconvenienti, il nostro applicativo prima di fare qualsiasi operazione controllerà l'esistenza di un device.
Creiamo quindi una funzione capGetDriverDescriptionA che fa riferimento a una funzione esistente nella nostra avicap32.dll, i parametri sono gli stessi che la vera funzione richiede.


Public Declare Function capGetDriverDescriptionA Lib "avicap32.dll" (ByVal wDriver As Short, ByVal lpszName As String, ByVal cbName As Integer, ByVal lpszVer As String, ByVal cbVer As Integer) As Boolean


Dopo di che facciamo un piccolo ciclo che elencherà tutti i device disponibili, e aggiungiamo il device a un listBox


Dim strName As String = Space(100)
Dim strVer As String = Space(100)
Dim bReturn As Boolean
Dim x As Integer = 0
'carica la lista completa nell'elenco
Do
'ricava il nome del driver e la versione
bReturn = capGetDriverDescriptionA(x, strName, 100, strVer, 100)
'se un device lo aggiunge alla lista
If bReturn Then lstDevices.Items.Add(strName.Trim)
x += 1
Loop Until bReturn = False


Ecco uno screenshot del nostro elenco, in questo caso è solamente uno, ma se avete più device di acquisizione audio-video vi verrà una lista più lunga.




Acquisizione preview
Ora che abbiamo selezionato il nostro device di acquisizione vogliamo creare una piccola finestra di preview, che ci farà vedere in tempo reale quello che la webcam invia al nostro sistema.
Il primo passo è creare nella nostra form un pictureBox che utilizzeremo come finestra di preview.



Dopo di che dovremo eseguire i seguenti passi:

? Indicare al sistema che deve dirigere il flusso verso il nostro pictureBox
? Collegarsi al device
? Impostare le dimensioni del flusso in base alle dimensioni del nostro controllo di preview
? Impostare il frame di cattura
? Far partire il processo di preview

Per far ciò dobbiamo utilizzare delle funzioni che faranno da puntatori a routines delle DLL avicap32 e user32, di seguito le funzioni:


Public Declare Function capCreateCaptureWindowA Lib "avicap32.dll" _
(ByVal lpszWindowName As String, ByVal dwStyle As Integer, _
ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, _
ByVal nHeight As Short, ByVal hWndParent As Integer, _
ByVal nID As Integer) As Integer



La funzione capCreateCaptureWindowA indicherà al sistema in che finestra dovrà inviare il flusso di dati:


Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, _
ByVal lParam As Object) As Integer


La funzione SendMessage la utilizzeremo per inviare messaggi alla avicap32, dopo aver impostato il flusso di dati:


Public Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Integer, _
ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, _
ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer


La funzione SetWindowPos verrà utilizzata per ridimensionare la finestra del flusso di dati.

Dopo aver creato le funzioni puntatore alle nostre dll di sistema, eseguiamo gli step elencati precedentemente, quindi per prima cosa indicheremo al sistema dove inviare il flusso di dati.


'Handle della finestra di preview
Dim hHwnd As Integer
'Dico alla dll di dirigere il flusso alla mia finestra di preview
hHwnd = capCreateCaptureWindowA(iDevice, WS_VISIBLE Or WS_CHILD, 0, 0, 640, _
480, objPreview.Handle.ToInt32, 0)


La variabile hHwnd rappresenta l'Handle della nostra finestra, che non è altro che il numero che identifica in modo univoco il nostro pictureBox, infatti tra i parametri c'è anche il valore objPreview.Handle.ToInt32 che ritorna proprio quel numero. Oltre a questo parametro passiamo anche il parametro iDevice che è il numero del device che vogliamo utilizzare, la dimensione del frame di cattura (640, 480), e le costanti WS_VISIBLE e WS_CHILD (nel progetto c'è un elenco completo delle costanti e dei loro valori)

Ora è necessario collegarsi al device e lo facciamo richiamando la funzione SendMessage, in questo modo

SendMessage(hHwnd, WM_CAP_DRIVER_CONNECT, iDevice, 0)

La funzione ci ritornerà un valore compreso tra 1 e 9 nel caso l'operazione sia andata a buon fine, e 0 se la connessione è avvenuta in modo corretto.
Ora che siamo connessi facciamo le operazioni di resize e di impostazione dei frame di acquisizione


'Imposto la preview
SendMessage(hHwnd, WM_CAP_SET_SCALE, True, 0)

'imposto il rate in millisecondi
SendMessage(hHwnd, WM_CAP_SET_PREVIEWRATE, 66, 0)

'Faccio partire la preview
SendMessage(hHwnd, WM_CAP_SET_PREVIEW, True, 0)

'Scalo la preview all'interno della dimensione del mio box immagine
SetWindowPos(hHwnd, HWND_BOTTOM, 0, 0, iWidth, iHeight, SWP_NOMOVE Or SWP_NOZORDER)


Come risultato di queste operazioni, vedremo comparire all'interno del nostro pictureBox in tempo reale le acquisizioni della nostra Webcam.



Cattura dell'immagine
Ora che siamo riusciti a ricavare il flusso di dati dalla nostra Webcam, salviamo un singolo frame in un file immagine bmp. Questa operazione è la più semplice di tutte perché non dovremo far altro che eseguire una chiamata alla funzione sendMessage indicando la costante per il salvataggio e il percorso del file.


'salvo il file
SendMessage(hHwnd, WM_CAP_FILE_SAVEDIB, 0&, txtFileName.Text)


Nota: L'avicap32.dll salva esclusivamente in formato bmp, per chi volesse produrre gif o jpeg dovrà crearsi una funzione di conversione personalizzata. Un esempio potrebbe essere:


'Imposto un oggetto bitmap, indicando il percorso del file da convertire
Dim objBmp As New Bitmap(BMPFullPath)
'salvo l'immagine, indicando il nuovo percorso, e il tipo di formato
objBmp.Save(strFileName, ImageFormat)
'libero le risorse
objBmp.Dispose()


Ed ecco il risultato del nostro duro lavoro.




Chiusura acquisizione
Per chiudere la nostra preview, e quindi anche l'accesso esclusivo alla nostra periferica di acquisizione, dobbiamo utilizzare una funzione presente nella user32dll, che non farà altro che chiudere la finestra di preview, in questo caso bloccherà l?accesso al nostro pictureBox, ecco la funzione:


Public Declare Function DestroyWindow Lib "user32" (ByVal hndw As Integer) As Boolean


E di seguito la chiamata, che come unico parametro vuole l'Handle della nosta finestra:


'chiudo il flusso di dati
DestroyWindow(hHwnd)


Possibili applicazioni
Le possibili applicazioni sono svariate, si parte dalla semplice webcam rudimentale per il proprio sito, a un applicativo per il controllo degli accessi, oppure anche registrazione filmati, fino a un applicativo di video conferenza, oppure spiare la nuova segretaria :).

Voto medio articolo: 4.7 Numero Voti: 20

File allegati


115_hellcam.zip (100 Kbyte)
Giovanni Ferron

Giovanni Ferron

Sviluppatore dal 2000. Collabora a grandi progetti nella creazione di portali e intranet aziendali. Attualmente ha lasciato la terra natia per una nuova avventura in Australia, dove lavora come programmatore web per una emittente radio Australiana. Profilo completo

Articoli collegati

Importare dati di Excel con .NET tramite ODBC o OLEDB e Drag & Drop
Spesso in ambito aziendale è necessario adattare le proprie applicazioni e consentire che possano leggere e operare su file e dati provenienti dai tools della suite di Office fra cui uno dei più usati è Excel. Vediamo quindi come importare dati da file XLS tramite ODBC/OLEDB e Drag & Drop.
Autore: Marco Farina | Difficoltà:
Gestire le Access Control List (ACL) NTFS di file e directory con .NET
Scopriamo come nel .NET Framework 2.0 sia diventato facile recuperare e modificare la lista controllo accessi dei file e directory e in generale come gestire le ACL.
Autore: Marco Caruso | Difficoltà: | Commenti: 1 | Voto:
Costruire un client FTP usando il .NET Framework 2.0
In questo articolo tratteremo una delle novità più attese del .NET Framework 2.0, le classi per l'utilizzo del protocollo FTP. Realizzeremo un mini client FTP con alcune fra le funzionalità più comuni.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 28
Alla scoperta di WMI, questo sconosciuto
WMI o Windows Management Instrumentation è un componente fondamentale del sistema operativo Windows. La sua utilità è permettere l'accesso a informazioni fondamentali del sistema, come informazioni sull'hardware, software, servizi, ecc. Vediamo come sfruttarlo con .NET.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 2
Gestire e sfruttare i campi BLOB usando .NET
I database server sono software con una potenza elevata e offrono una vasta gamma di features che spesso non vengono utilizzate. Una di queste sono i campi BLOB (campi per contenere dati in formato binario). Vediamo in questo articolo come utilizzarli con .NET.
Autore: David De Giacomi | Difficoltà: | Commenti: 13
Usare il protocollo POP3 per creare un Client di posta
Volete costruirvi un client di posta? Volete costruire una Web Mail ? Ecco un articolo che vi introduce al protocollo POP3 e vi insegna come costruire un mini client di posta elettronica.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 2 | Voto:
La stampa di una Win Form
Vedremo in questo articolo i passi necessari per creare una stampa sia di testo che di grafica di una WinForm attraverso .NET.
Autore: Marco Caruso | Difficoltà: | Commenti: 9 | Voto:
Creare un Setup di un progetto con Visual Studio .NET
Ecco delle semplici ma dettagliate istruzioni passo-passo per costruire un pacchetto di Setup (Setup Package) per le nostre Applicazioni WinForms.
Autore: Marco Caruso | Difficoltà: | Commenti: 18
Creare un?icona nella Taskbar di Windows con .NET
Scoprirete come potenziare la vostra applicazione aggiungendo un'icona nella barra di Windows nella famosa Tray Area a fianco dell'orologio del sistema. Disponibile sia codice VB.NET che C#.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 1 | Voto:
Costruire un Servizio di Windows usando .NET
Un avanzato tutorial che vi spiegherà passo passo e in modo dettagliato le istruzioni per costruire un Servizio Windows, utilizzando ciò che il .NET Framework ci mette a disposizione. Disponibile sia codice C# che VB.NET.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 13 | Voto:
Windows XP Visual Styles con .NET e Win Forms
Come usare lo stile XP nelle vostre applicazioni .NET ? Questo articolo vi spiega come applicare a Buttons, Textbox, ListViews (ai controlli di Windows in genere) lo stile/tema grafico della GUI introdotto dal sistema operativo Windows XP.
Autore: David De Giacomi | Difficoltà: | Commenti: 7
Come sfruttare le funzioni di una DLL unmanaged esterna creata in C/C++
Come usare la classe DllImportAttribute messa a disposizione dal namespace System.Runtime.InteropServices per sfruttare le funzioni di una DLL unmanaged Win32 old-style scritta con Visual C++ 6.0
Autore: David De Giacomi | Difficoltà: | Commenti: 4 | Voto:
Creare una DLL in Visual C++ 6.0
Vedremo in questo articolo come creare una Dynamic Link Link Library, comunemente chiamata DLL con Visual C++ 6.0. Questo passo è necessario per poi dimostrare l'utilizzo di librerie C/C++ in .NET tramite il package System.Runtime.InteropServices
Autore: David De Giacomi | Difficoltà: | Commenti: 11 | Voto:
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5