2009-04-19 11 views
10

Actualmente estoy trabajando en un proyecto que utiliza Reconocimiento facial. Por lo tanto, necesito una forma de mostrar las imágenes de la cámara web al usuario para que pueda ajustar su rostro.¿Cómo mostrar las imágenes de webcam capturadas con Emgu?

He estado tratando un montón de cosas para obtener imágenes de la cámara web utilizando como menos CPU como sea posible:

Pero ninguno de estaban bien ... De cualquier manera, demasiado lento o consumiendo demasiados recursos de la CPU.

Luego probé el Emgu library y me sentí muy bien al respecto. Al principio, lo probé en un proyecto de Windows Form y estaba actualizando la imagen en un Picture Box. Pero entonces, cuando traté de integrarlo en mi proyecto WPF me quedé atrapado en la forma de pasar mi imagen a mi control de imagen ..

En este momento, no tengo el siguiente código:

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

Y el código subyacente:

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

Mi suposición era utilizar BitmapSource/WriteableBitmap pero no he tenido que trabajar ...

Gracias!

Respuesta

3

Image Class ha conseguido una propiedad UriSource que puede estar buscando

0

Creo que usted tiene que utilizar interoperabilidad (source):

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

que podría ser utilizado como esto:

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

Si la interoperabilidad no funciona lo suficientemente bien, eche un vistazo a la fuente de Image.ToBitmap y Image.get_Bitmap para ver cómo podría implementar su propia WriteableBitmap.

+1

Sí, pero ¿qué tengo que hacer para que me muestra el "webcam" Control de imagen de la imagen? Lo he intentado: webcam.Source = frame.AsImageSource(); Pero no muestra nada ... – ZogStriP

+1

Configurar el origen debe ser suficiente. ¿Podría intentar especificar un Int32Rect con el tamaño de la imagen? – dahlbyk

+0

¡Tengo el mismo problema! Y maging.CreateBitmapSourceFromHBitmap (image.Bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); causa pérdidas de memoria en WPF! – Evgeny

3

Mira en la wiki de Emgu -> Tutoriales -> Ejemplos -> WPF (Windows Presentation Foundation) Contiene el siguiente fragmento de código para convertir tu IImage en un BitmapSource, que puedes aplicar directamente a tu control.

usando Emgu.CV; usando 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

Creo que todo lo que está buscando es la siguiente:

Image<Bgr, Byte> frame = capture.QueryFrame(); 
pictureBox1.Image = image.ToBitmap(pictureBox1.Width, pictureBox1.Height); 
2

Si está utilizando WPF MVVM y así es como usted lo haría utilizando EMGU.

Vista:

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

modelo de vista:

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 

} 
Cuestiones relacionadas