WPF Webcam Control part 2

Some time ago, I wrote an article about how to capture images from a webcam. The article contained some customized code that was originally posted by Tamir Khason.

On January 7th, 2009, Edgar commented that he wanted to control the device or selected camera via WPF bindings. I agreed that if the blog entry promised to give a WPF Webcam Control, it should support WPF bindings as well.

So, I have rewritten some parts of the webcam control so that fully supports WPF. If have also written a simple sample application that allows users that download the control to easily decide whether this control is useful or not.

I have implemented code that you can easily change the MonikerString of a CapDevice. This means that you can set one device to a CapPlayer object and simply set the device via WPF bindings. The example application shows how to bind a combobox to the available devices on the system and how to set the values via dependency properties.

You can see a screenshot of the example application below:

webcamplayer_example

WebcamPlayer_1.1.zip (118.49 kb) [Downloads: 2817]

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Comments

January 21. 2009 14:03

Aaditya

Hello Geert,

'm developing an application which captures and saves images from a web cam. i am using WPF. 'm pretty new to both WPF and C#. so 'm finding it difficult to understand the code. Can u suggest a way to save the image as a file on local hard disk.

Aaditya

January 21. 2009 14:06

Geert van Horrik

Well, the example application has a dependency property SelectedImages. This is a collection of BitmapSource.

Searching for "Save BitmapSource" gave me the following result:

social.msdn.microsoft.com/.../

Geert van Horrik

February 15. 2009 14:49

oded

Hi,
Thanks for the great sample project, is there a way to control the Framerate? I want a lower framerate for a client/server application...
Thanks,
oded

oded

February 15. 2009 16:12

Geert van Horrik

You can control the framerate (or any webcam properties) with this sample project.

However, you can easily control the number of images that are passed to your client application (downgrade the framerate) by storing the time that you captured the last image and check if that value is larger than (1 second / required framerate).

Best regards,

Geert van Horrik

February 27. 2009 17:00

Ricky


Hi Geert,

This is probably one of the best samples i could find for capturing images from a web cam. I have a problem though. I am using this sample as a part of a bigger project wherein i send the captured image via web services. I have a number of windows. so once i have captured the image, i want to call a 'destructor' of the screen housing your webcam capturing code. This is because
a) I want to free up the resources
b) I somehow can't capture the images once i navigate off from the webcam window. The 'SelectedWebcam' property returns false.

Please suggest some way to do this.

Regard,

Ricky

Ricky

March 4. 2009 04:44

elwolv

excellent!!  i just run the code demonstration with the ability to capture still image from the video stream.
now i will read your article/code

my complement

elwolv


elwolv

March 4. 2009 16:19

Geert van Horrik

Hi Ricky,

Did you check whether your destructor is actually called before you try to use the device again? Maybe the device is still in use. For one of my clients, I have created a picture import wizard that is able to import multiple images from webcam, digital camera, disk, scanner, etc. We are not having any problems with the webcam being in use or not allowing to capture again.

Geert van Horrik

March 4. 2009 18:22

elwolv

hello Geert

the camplayer references has 2 references that are not in the original code   J832.common, and J832.wpf.bagotrickslib

what are those and i did not see such file/code with such names
however, references is accessing them?

elwolv

March 4. 2009 18:30

Geert van Horrik

See http://j832.com/. It is a library written by Kevin Moore.

I use only one part, and that is to insert the images in a nice transition. The control is used in the MainWindow class for the selected images control.

Geert van Horrik

April 15. 2009 22:36

Regis Hanol

Hi Geert,

I've tried your application and it is definitively not taking any CPU power! Awesome!
But it is also really really slow!... Not awesome ;)

I mean the frame rate of the webcam is like 1 frame per 5 seconds or so...

Any thoughts ?

I'm running Windows 7 Beta 1 on a Macbook if this is important.

Thanks a lot !

Regis Hanol

April 16. 2009 08:49

Geert

Hi Regis,

Are you sure your webcam supports that much frames? At the moment, the software tries to read as much frames as possible from the webcam. A nice additional feature would be to extend the software with a framerate control.

Did you try to view the webcam results in Windows Explorer (you can view the video there)? What framerate does it support there?

Best regards,

Geert

Geert

April 16. 2009 09:43

Regis Hanol

Hi Geert,

Yes the webcam works. I've been using the code you can find there www.brains-n-brawn.com/default.aspx and I get a decent 30 FPS.

Anyway, I tried to use your software with another webcam (a USB one) and it worked fine, but used 40% of the CPU...

Regis

Regis Hanol

April 22. 2009 11:48

Geert van Horrik

You have to understand that this software is not very optimized. I think if you only use the webcam part (and not the demo application), the CPU will go down a bit.

Geert van Horrik

May 20. 2009 20:15

Kyle Egbert

Nice work!  I was trying to use your control and was wondering if there is support to change the resolution of the captured image... I have a nice webcam which supports 960*720 output but the captured image always seems to be much lower quality.

Thanks,
Kyle

Kyle Egbert

May 25. 2009 16:43

Gatt

Hi !!
It's a really nice work !
But I'm wondering how can I change the resolution, I have a Webcam which can show 960x720 and I've only 640x480.
I tried to change
header.BmiHeader.Width = 960;
header.BmiHeader.Height = 720;
but this doesn't make a good picture

Thanks

Gatt

May 26. 2009 18:37

Geert

Hi,

Sorry for my "late" reply, I have been out-of-office for the weekend.

Anyway, this control doesn't directly support changing the resolution. Changing the size of the BmiHeader is useless since the image is already captured (and you are simply resizing a bitmap in that case).

I suggest you take a took at the Device class.

Best regards,

Geert

Geert

May 27. 2009 11:20

Gatt

Hi,
Thanks. This is what I was thinking.
In order to change the resolution, tell me if I'm wrong, I have to work on the _sourceObject in the RunWorker Method when the graph is created (but I don't know what to do for the moment).

Thanks.

Gatt

May 27. 2009 11:50

Geert

What you might try to do is set the requested size in the mediaType variable.

Please take a look at the documentation:

code.snapstream.com/.../...AMMediaTypeMembers.html

As you can see in the Structures file, the FixedSizeSamples is set to true by default.

Geert

May 27. 2009 12:07

Gatt

I've already tried this, and this change nothing. But there is something strange, when I set imagesize/samplesize or something else in mediatype, the BufferLen in BufferCB method doesn't change, and it's always the imagesize in 640x480 (the bad resolution).

Gatt

May 27. 2009 12:25

Geert

Keep in mind that this sample is not a DirectShow example. Please see the documentation:

msdn.microsoft.com/.../dd319784(VS.85).aspx

A good C# version of DirectShow (that contains all the interfaces definitions, etc) is http://directshownet.sourceforge.net/.

Geert

May 27. 2009 12:41

Gatt

Your first link is exactly what I'm trying to do, to set the output format thanks to IAMStreamConfig Interface.
I know that your sample isn't a directshow example, but to my mind, it's a very good sample, and changinig is the only thing which is missing, is the webcam resolution.
I have directshow examples and it's easy to change the webcam resolution.
So I would like to add the resolution support to your code, to have a complete wpf webcam control.

Gatt

May 27. 2009 16:52

Gatt

It's works !!

you just have to add (And implement IAMStreamConfig, and make the code prettier)

IEnumPins _enumPin;
_sourceObject.EnumPins(out _enumPin);
IPin[] _IPP = new IPin[3];
int pt = -1;
_enumPin.Next(3, _IPP, out pt);
                
IAMStreamConfig st;
st = (IAMStreamConfig)_IPP[0];
                
AMMediaType med = new AMMediaType();
st.GetFormat(out med);
VideoInfoHeader head = (VideoInfoHeader)Marshal.PtrToStructure(med.FormatPtr, typeof(VideoInfoHeader));

head.BmiHeader.Width = 960;
head.BmiHeader.Height = 720;

Marshal.StructureToPtr(head, med.FormatPtr, false);
st.SetFormat(med);

Gatt

May 27. 2009 17:08

Geert

Great to hear! Thank you for posting this fix!

I have received more fixes during the weeks, so I will try to post and update with all fixes as soon as I have some time left...

Geert

June 2. 2009 14:51

Gatt

Hi,

Is somebody succeed in recording webcam in a file (toto.avi for example) thanks to this control?
With a ICaptureGraphBuilder it's easy to record and preview the webcam stream, but we have a "simple" GraphBuilder ...

Thanks

Gatt

June 4. 2009 13:10

syeed

Hi,

iam saving the image from list,

FileStream stream1 = new FileStream("1.jpg", FileMode.Create);
            JpegBitmapEncoder encoder1 = new JpegBitmapEncoder();
            TextBlock myTextBlock = new TextBlock();
            myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
            encoder1.FlipHorizontal = true;
            encoder1.FlipVertical = false;
            encoder1.QualityLevel = 30;
            encoder1.Rotation = Rotation.Rotate90;
            encoder1.Frames.Add(BitmapFrame.Create(webcamPlayer.CurrentBitmap.Clone()));
            encoder1.Save(stream1);

but the image  is storing in TransformedBitmap mode and the view is no priview image....
please i need solution for this

syeed

June 4. 2009 14:51

syeed


Thanks (advancely)

my aim is to store these images in hard disk,

i used another code also

Image image1 = new  Image();
            image1.Source = SelectedImages[0] ;
            int width = 100;
            int height = 100;
            int stride = width / 8;

            RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
            rtb.Render(image1);
            FileStream stream = new FileStream("1.gif" , FileMode.Create);
            BitmapEncoder encoder = new GifBitmapEncoder();
            //JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(rtb));
            encoder.Save(stream);



but the result is same, image able to stor but in "no image prive" mode

please help me

syeed

June 5. 2009 09:43

Gatt


In Capture_Executed, you just have to add
FileStream stream1 = new FileStream("1.jpg", FileMode.Create);
            JpegBitmapEncoder encoder1 = new JpegBitmapEncoder();
            
            encoder1.FlipHorizontal = true;
            encoder1.FlipVertical = false;
            encoder1.QualityLevel = 30;
            
            encoder1.Frames.Add(BitmapFrame.Create(Bitmap));
            encoder1.Save(stream1);

then close the encoder if you want to open your image when your application is running

Gatt

Comments are closed