Как отображать изображения с веб-камеры, сделанные с помощью Emgu? - PullRequest
10 голосов
/ 19 апреля 2009

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

Я много чего пытался получить изображения с веб-камеры, используя как можно меньше ЦП:

Но ни один из них не был в порядке ... Либо слишком медленный, либо слишком ресурсоемкий процессорный ресурс.

Затем я попробовал библиотеку Emgu , и я чувствовал себя прекрасно по этому поводу. Сначала я попробовал это в проекте Windows Form и обновлял изображение в Picture Box . Но затем, когда я попытался интегрировать его в мой проект WPF, я застрял на том, как передать свое изображение в мой элемент управления изображениями.

Прямо сейчас у меня есть следующий исходный код:

<Window x:Class="HA.FacialRecognition.Enroll.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Width="800" Height="600"
        Loaded="Window_Loaded" Closing="Window_Closing">
    <Grid>
        <Image x:Name="webcam" Width="640" Height="480" >
            <Image.Clip>
                <EllipseGeometry  RadiusX="240" RadiusY="240">
                    <EllipseGeometry.Center>
                        <Point X="320" Y="240" />
                    </EllipseGeometry.Center>
                </EllipseGeometry>
            </Image.Clip>
        </Image>
    </Grid>
</Window>

И код позади:

private Capture capture;
private System.Timers.Timer timer;

public Window1()
{
    InitializeComponent();
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    capture = new Capture();
    capture.FlipHorizontal = true;

    timer = new System.Timers.Timer();
    timer.Interval = 15;
    timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
    timer.Start();
}

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    using (Image<Bgr, byte> frame = capture.QueryFrame())
    {
        if (frame != null)
        {
            var bmp = frame.Bitmap;
            // How do I pass this bitmap to my Image control called "webcam"?
        }
    }
}

private void Window_Closing(object sender, CancelEventArgs e)
{
    if (capture != null)
    {
        capture.Dispose();
    }
}

Я предполагал использовать BitmapSource / WriteableBitmap, но я не получил их работу ...

Спасибо!

Ответы [ 7 ]

3 голосов
/ 03 ноября 2009

Я считаю, что все, что вы ищете, это:

Image<Bgr, Byte> frame = capture.QueryFrame();
pictureBox1.Image = image.ToBitmap(pictureBox1.Width, pictureBox1.Height);
3 голосов
/ 29 июля 2015

Если вы используете WPF и MVVM, вот как вы это сделаете, используя EMGU .

Вид:

<Window x:Class="HA.FacialRecognition.Enroll.Views.PhotoCaptureView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Width="800" Height="600">
<Grid>
    <Image Width="640" Height="480" Source="{Binding CurrentFrame}">
        <Image.Clip>
            <EllipseGeometry  RadiusX="240" RadiusY="240">
                <EllipseGeometry.Center>
                    <Point X="320" Y="240" />
                </EllipseGeometry.Center>
            </EllipseGeometry>
        </Image.Clip>
    </Image>
</Grid>

ViewModel:

namespace HA.FacialRecognition.Enroll.ViewModels
{
public class PhotoCaptureViewModel : INotifyPropertyChanged
{
    public PhotoCaptureViewModel()
    {
        StartVideo();
    }

    private DispatcherTimer Timer { get; set; }

    private Capture Capture { get; set; }

    private BitmapSource _currentFrame;
    public BitmapSource CurrentFrame
    {
        get { return _currentFrame; }
        set
        {
            if (_currentFrame != value)
            {
                _currentFrame = value;
                OnPropertyChanged();
            }
        }
    }

    private void StartVideo()
    {
        Capture = new Capture();
        Timer = new DispatcherTimer();
        //framerate of 10fps
        Timer.Interval = TimeSpan.FromMilliseconds(100);
        Timer.Tick += new EventHandler(async (object s, EventArgs a) =>
        {
            //draw the image obtained from camera
            using (Image<Bgr, byte> frame = Capture.QueryFrame())
            {
                if (frame != null)
                {
                    CurrentFrame = ToBitmapSource(frame);
                }
            }
        });
        Timer.Start();
    }

    public static BitmapSource ToBitmapSource(IImage image)
    {
        using (System.Drawing.Bitmap source = image.Bitmap)
        {
            IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap
            BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ptr, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            DeleteObject(ptr); //release the HBitmap
            return bs;
        }
    }

    /// <summary>
    /// Delete a GDI object
    /// </summary>
    [DllImport("gdi32")]
    private static extern int DeleteObject(IntPtr o);

    //implementation of INotifyPropertyChanged, viewmodel disposal etc

}
3 голосов
/ 25 мая 2009

Посмотрите вики Emgu -> Учебные пособия -> Примеры -> WPF (Windows Presentation Foundation) Он содержит следующий фрагмент кода для преобразования вашего IImage в BitmapSource, который вы можете напрямую применить к своему элементу управления.

с использованием Emgu.CV; using System.Runtime.InteropServices; ...

    /// <summary>
    /// Delete a GDI object
    /// </summary>
    /// <param name="o">The poniter to the GDI object to be deleted</param>
    /// <returns></returns>
    [DllImport("gdi32")]
    private static extern int DeleteObject(IntPtr o);

    /// <summary>
    /// Convert an IImage to a WPF BitmapSource. The result can be used in the Set Property of Image.Source
    /// </summary>
    /// <param name="image">The Emgu CV Image</param>
    /// <returns>The equivalent BitmapSource</returns>
    public static BitmapSource ToBitmapSource(IImage image)
    {
        using (System.Drawing.Bitmap source = image.Bitmap)
        {
            IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap

            BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                ptr,
                IntPtr.Zero,
                Int32Rect.Empty,
                System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

            DeleteObject(ptr); //release the HBitmap
            return bs;
        }
    }
3 голосов
/ 19 апреля 2009

Image Class имеет свойство UriSource, которое вы можете искать

0 голосов
/ 25 февраля 2010

Попробуйте это.

http://easywebcam.codeplex.com/

Я использовал это, и это было превосходно ..

0 голосов
/ 22 апреля 2009

Я считаю, что вы должны использовать взаимодействие ( источник ):

using System.Windows.Interop;
using System.Windows.Media.Imaging;

public static ImageSource AsImageSource<TColor, TDepth>(
    this Image<TColor, TDepth> image) where TColor : IColor, new()
{
    return Imaging.CreateBitmapSourceFromHBitmap(image.Bitmap.GetHbitmap(),
                       IntPtr.Zero, Int32Rect.Empty,
                       BitmapSizeOptions.FromEmptyOptions());
}

Что можно использовать следующим образом:

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
        using (Image<Bgr, byte> frame = capture.QueryFrame())
        {
                if (frame != null)
                {
                        var bmp = frame.AsImageSource();
                }
        }
}

Если взаимодействие не работает достаточно хорошо, взгляните на источник Image.ToBitmap и Image.get_Bitmap, чтобы увидеть, как вы можете реализовать свой собственный WriteableBitmap.

...