Monday, February 1, 2010

Using a Webcam with WIA and F#

In this post I'm going to show a small example of taking a picture using a Webcam with Windows Image Adquisition 1.0 . This API seems to have changed in Vista and above, the following code only applies to XP.

First step, create the interop assemblies:


C:\test\> TlbImp c:\WINDOWS\system32\wiascr.dll
Microsoft (R) .NET Framework Type Library to Assembly Converter 3.5.30729.1
Copyright (C) Microsoft Corporation. All rights reserved.

Type library imported to WIALib.dll

C:\test>TlbImp c:\WINDOWS\system32\wiavideo.dll
Microsoft (R) .NET Framework Type Library to Assembly Converter 3.5.30729.1
Copyright (C) Microsoft Corporation. All rights reserved.

Type library imported to WIAVIDEOLib.dll


Now we launch FSI and load the assemblies:


C:\test> fsi.exe

Microsoft F# Interactive, (c) Microsoft Corporation, All Rights Reserved
F# Version 1.9.7.8, compiling for .NET Framework Version v2.0.50727

For help type #help;;

> #r "WIALib.dll";;

--> Referenced 'C:\development\blog\wiafs\WIALib.dll'

> #r "WIAVIDEOLIB.dll";;

--> Referenced 'C:\development\blog\wiafs\WIAVIDEOLIB.dll'



Now we can list the capture devices:


> wia.Devices |> Seq.cast |> Seq.map (fun (x:WIALib.IWiaDeviceInfo) -> x.Name);;

val it : seq<string> = seq ["My iPod"; "Logitech QuickCam Chat"]



Now I'm going to use the QuickCam to take the picture so we get the information for this device (of type 'StreamingVideo'):


> let devInfo = wia.Devices |> Seq.cast |> Seq.filter (fun (x:WIALib.IWiaDeviceInfo) -> x.Type.Contains("StreamingVideo")) |> Seq.head;;

val devInfo : WIALib.IWiaDeviceInfo

> devInfo.Name;;
val it : string = "Logitech QuickCam Chat"


Now we create an instance of the 'WIAVIDEOLib.WiaVideoClass' which will let us use the Webcam.


> let vid = new WIAVIDEOLib.WiaVideoClass();;
Binding session to 'C:\development\blog\wiafs\WIAVIDEOLib.dll'...

val vid : WIAVIDEOLib.WiaVideoClass

> vid.ImagesDirectory <- "c:\\temp";;
val it : unit = ()
> let h = ref (new WIAVIDEOLib._RemotableHandle());;

val h : WIAVIDEOLib._RemotableHandle ref =
{contents = WIAVIDEOLib._RemotableHandle;}

> vid.CreateVideoByWiaDevID(devInfo.Id,h,0,1);;
val it : unit = ()



The 'ImagesDirectory' property specifies the location for the captured images.

Now we can take a picture:


> let outFileName = ref "";;

val outFileName : string ref = {contents = "";}

> vid.TakePicture( outFileName );;
val it : unit = ()
> outFileName;;
val it : string ref = {contents = "c:\temp\Imagen 009.jpg";}


The 'outFileName' parameter gets the name of the saved image in the images directory.