Реализация веб-камеры в приложении WPF с использованием AForge.Net - PullRequest
9 голосов
/ 05 января 2010

Я пишу приложение WPF, в котором мне нужно показать канал веб-камеры. Я смог сделать это легко с помощью фреймворка AForge. Но когда я перешел с одного компьютера на другой, тот же код не работает так же.

В первом из них канал веб-камеры работает идеально, но во втором случае этого не происходит, канал имеет большую задержку, и приложение не работает должным образом.

Вот код:

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

    }

Что этот код действительно прост, он получает новый_фрейм от веб-камеры в виде Bitmap, и мне нужно преобразовать его в BitmapSource, чтобы я мог показать его в рамке изображения из WPF. Я думаю, что это преобразование является причиной беспорядка, который происходит, но я не понимаю, почему он работает на компьютере, а на другом - нет.

Характеристики компьютера практически одинаковы, процессор такой же, как и системная память.

Моя проблема здесь связана с производительностью , этот код на одном компьютере работает без сбоев, а веб-камера отображается так, как и должно быть, при переносе на другой компьютер этого не происходит.

Ответы [ 4 ]

19 голосов
/ 08 февраля 2013

Вот рабочий код, основанный на этой статье.

(1) Загрузите и установите последнюю платформу AForge . (Я использовал версию 2.2.4)

(2) Создать проект приложения WPF.

(3) Добавить ссылки на эти библиотеки AForge. (Их можно найти в папке C: \ Program Files (x86) \ AForge.NET \ Framework \ Release, т. Е.)

enter image description here

(4) Создайте свой проект. (Я использовал VS 2012)

(5) Добавьте элемент управления WPF Image и назовите его «frameHolder».

Итак, у вас есть что-то вроде

<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) Добавить код C #:

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) Перестройте проект, и он работает!

Примечание: Мы используем первую обнаруженную веб-камеру по умолчанию. Убедитесь, что у вас установлен драйвер WebCam, а WebCam работает в общем ...:)

2 голосов
/ 27 января 2017

Я знаю, что оригинальному сообщению уже более 3 лет, но я просто пытался выяснить, как использовать этот код. Я обнаружил, что ответ, данный Дими, является почти полностью функциональным кодом. Однако я обнаружил, что у меня есть проблемы с утечкой памяти и ненадежным отображением кадра на некоторых компьютерах. Код отлично работал на моем более совершенном компьютере для разработки (i7, 16 ГБ ОЗУ, карта Quadro Pro Grapthics), но когда я развернул приложение на компьютере с более ограниченными ресурсами (i5, 4 ГБ ОЗУ, интегрированная графика Intel), рамка исчезает один раз в некоторое время, и программа также будет аварийно завершать работу после исчерпания системной памяти. Пройдя некоторое время в интернете, я думаю, что наконец-то собрал воедино рабочий код, основанный на всех отзывах людей. Я знаю, что другой компьютер способен выполнять захват кадров с веб-камеры, потому что у меня есть приложение WinForm C #, которое я написал с помощью AForge.NET, и у него нет проблем с надежным рендерингом кадров без утечки памяти. К сожалению, WPF не обрабатывает графику так же, как WinForm, и мы должны сделать это, чтобы заставить AForge.NET работать с ним.

По сути, код такой же, как у Дими, за исключением метода Cam_NewFrame.

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
        }

    } 

Были внесены следующие изменения:

  1. Включение обработки растрового изображения с использованием области видимости, так что любая неиспользуемая память очищается сразу после окончания области действия.
  2. Перемещение bi.BeginInit () перед обработкой потока памяти, чтобы растровое изображение было сразу готово для дампа памяти.
  3. Изменение CacheOption на OnLoad, чтобы вся память изображений была выгружена прямо при загрузке. В противном случае он использует BitmapCacheOption.Default, который может позволить изображению удерживаться в памяти, даже когда выдается bi.Freeze (). Это привело к тому, что кадр не отображался даже при вызове Dispatcher.BeginInvoke для визуализации изображения.

Пока что все работает хорошо, но если кто-то еще заметит другие проблемы, пожалуйста, оставьте комментарий, чтобы мы знали, как это исправить.

2 голосов
/ 05 января 2010

В моем WPF MediaKit есть элемент управления VideoCaptureElement, который будет отображать веб-камеру в WPF. Вы также можете получить доступ к образцам, подключившись к событию нового изображения и установив EnableSampleGrabbing для элемента.

0 голосов
/ 09 января 2010

Может веб-камера на другом компьютере сломана / неисправна? Или имеет одну из веб-камер, которые не поддерживают API DirectShow, на котором, я думаю, AForge опирается

...