Implementing a WebCam on a WPF App using AForge.Net

荒凉一梦 提交于 2019-11-30 13:17:26

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.)

(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... :)

In my WPF MediaKit, I have a control called VideoCaptureElement that will render a webcam to WPF. You can also get access to the samples by hooking into the new image event and setting the EnableSampleGrabbing on the element.

I know the original post is over 3 years old, but I just have been trying to figure out how to use this code. I found that the answer given by Dimi is nearly a fully functional code. However, I found that I have issues with memory leaking and the frame not being render reliably on some computers. The code worked perfectly on my beefier development computer (i7, 16GB RAM, Quadro Pro Grapthics card), but when I deployed the app on a computer with more limited resources (i5, 4GB RAM, Integrated Intel graphics), the frame disappears once in a while and the program would also crash after the system memory runs out. After searching the internet for a while, I think I finally patched together a working code based on all the feedback people had. I know that the other computer is capable of running frame capture from the webcam because I have a WinForm C# app that I wrote using AForge.NET and it has no issues rendering the frame reliably and with no memory leak. Unfortunately WPF doesn't handle graphics the same way as WinForm and we have to do this hack to get AForge.NET to work with it.

Basically, the code is the same as Dimi's except for the Cam_NewFrame method.

void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        try
        {
            BitmapImage bi;
            using(var bitmap = (Bitmap)eventArgs.Frame.Clone())
            {
                bi = new BitmapImage();
                bi.BeginInit();
                MemoryStream ms = new MemoryStream();
                bitmap.Save(ms, ImageFormat.Bmp);
                bi.StreamSource = ms;
                bi.CacheOption = BitmapCacheOption.OnLoad;
                bi.EndInit();
            }
            bi.Freeze();
            Dispatcher.BeginInvoke(new ThreadStart(delegate { frameHolder.Source = bi; }));


        }
        catch (Exception ex)
        {
            //catch your error here
        }

    } 

The changes that were made are the following:

  1. Enclosing the bitmap handling with Using scope so that any unused memory is cleaned up right away after the end of scope.
  2. Moving the bi.BeginInit() before dealing with the memory stream so that the bitmap is ready for the memomory dump right away.
  3. Changing the CacheOption to OnLoad so that all the image memory gets dump right at the loading. Otherwise, it uses BitmapCacheOption.Default which could allow the image to hold on to the memory even when bi.Freeze() is issued. This caused the frame to not be rendered even with the Dispatcher.BeginInvoke is called to render the image.

So far it's been working well but if anyone else spot other issues please make a comment so we know how to fix it.

Maybe the webcam on the other computer is broken/faulty? Or has one of the webcams that doesnt support the DirectShow api, which i think AForge builds on.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!