Implementing a WebCam on a WPF App using AForge.Net

João Cardoso picture João Cardoso · Jan 5, 2010 · Viewed 21.1k times · Source

I'm writing an WPF application where I need to show a Webcam feed. I was able to do this easly with the AForge framework.But when I've changed from a computer to a another computer the same code doesn't work the same way.

In the first one the webcam feed works perfectly, but in the other one this does't occur, the feed has a lot of delay, and the application doesn't work properly.

Here is the code:

    private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        Bitmap img = (Bitmap)eventArgs.Frame.Clone();

        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate
            {
                IntPtr hBitmap = img.GetHbitmap();
                System.Windows.Media.Imaging.BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    hBitmap,
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

                DeleteObject(hBitmap);

                img.Dispose();
                GC.Collect();
                image1.Source = bitmapSource;

            }, null);

    }

What this code is really simple, it gets a new_frame from the webcam in a form of a Bitmap, and what I need to do is to convert it to a BitmapSource, so I can show in the image frame of the WPF. I think this conversion is the responsible of the mess that is happening, but I don't understand why it works in a computer and in the other doesn't.

The computer specs are almost the same, the processor is the same, as well the system memory.

My problem here is about performance, this code in one computer runs smoothly, and the webcam feed is presented as it should, when I port it to another PC this doesn't happen.

Answer

DmitryBoyko picture DmitryBoyko · Feb 8, 2013

Here is working code based on this article.

(1) Download and install last AForge framework. (I have used version 2.2.4)

(2) Create WPF Application project.

(3) Add references to those AForge DLLs. (You can find them under C:\Program Files (x86)\AForge.NET\Framework\Release folder i.e.)

enter image description here

(4) Build your project. (I have used VS 2012)

(5) Add WPF Image control and name it "frameHolder".

So you have something like

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Image HorizontalAlignment="Stretch" Name="frameHolder"  VerticalAlignment="Stretch"  Stretch="Fill"/>
    </Grid>
</Window>

(6) Add C# code:

using AForge.Video;
    using AForge.Video.DirectShow;
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;

/////

namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            VideoCaptureDevice LocalWebCam;
            public FilterInfoCollection LoaclWebCamsCollection; 

        void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            try
            {
                System.Drawing.Image img = (Bitmap)eventArgs.Frame.Clone();

                MemoryStream ms = new MemoryStream();
                img.Save(ms, ImageFormat.Bmp);
                ms.Seek(0, SeekOrigin.Begin);
                BitmapImage bi = new BitmapImage();
                bi.BeginInit();
                bi.StreamSource = ms;
                bi.EndInit();

                bi.Freeze();
                Dispatcher.BeginInvoke(new ThreadStart(delegate
                {
                    frameHolder.Source = bi;
                }));
            }
            catch (Exception ex)
            {
            }
        } 

        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            LoaclWebCamsCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            LocalWebCam = new VideoCaptureDevice(LoaclWebCamsCollection[0].MonikerString);
            LocalWebCam.NewFrame += new NewFrameEventHandler(Cam_NewFrame);

            LocalWebCam.Start();
        }
    }
}

(7) Re-Build project and it works!

Note: We use first detected WebCam by default. Make sure you have WebCam driver insalled and WebCam is working in general... :)