2009-04-19 9 views
10

Attualmente sto lavorando a un progetto che utilizza Riconoscimento facciale. Ho quindi bisogno di un modo per visualizzare le immagini della webcam all'utente in modo che possa regolare il suo viso.Come visualizzare le immagini della webcam catturate con Emgu?

Ho provato un sacco di cose per ottenere immagini dalla webcam utilizzando il meno possibile CPU:

Ma nessuno di loro stavano bene ... In ogni caso, troppo lento o troppo carico di risorse della CPU.

Quindi ho provato il Emgu library e mi sono sentito benissimo. Inizialmente, l'ho provato in un progetto Windows Form e aggiornavo l'immagine in una Picture Box . Ma poi, quando ho cercato di integrarlo nel mio progetto WPF sono rimasto bloccato su come passare la mia immagine al mio controllo Image ..

In questo momento, ho il seguente codice sorgente:

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

E il codice dietro:

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

la mia ipotesi era quella di utilizzare BitmapSource/WriteableBitmap ma non ho avuto loro lavoro ...

Grazie!

risposta

3

Image Class ha una proprietà UriSource che si può essere alla ricerca di

0

credo che si deve usare interoperabilità (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()); 
} 

che potrebbe essere utilizzato in questo modo:

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

Se l'intervallo non funziona abbastanza bene, dai un'occhiata alla fonte di Image.ToBitmap e Image.get_Bitmap per vedere come potresti implementare il tuo WriteableBitmap.

+1

Sì, ma che cosa devo fare per fare visualizzare il mio "webcam" Image Control l'immagine? Ho provato: webcam.Source = frame.AsImageSource(); Ma non visualizza nulla ... – ZogStriP

+1

L'impostazione della sorgente dovrebbe essere sufficiente. Potresti provare a specificare un Int32Rect con le dimensioni dell'immagine? – dahlbyk

+0

Ho lo stesso problema! E maging.CreateBitmapSourceFromHBitmap (image.Bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); causa perdite di memoria in WPF! – Evgeny

3

Guarda il wiki di Emgu -> Esercitazioni -> Esempi -> WPF (Windows Presentation Foundation) Contiene il seguente frammento di codice per convertire il tuo IImage in un BitmapSource, che puoi applicare direttamente al tuo controllo.

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

Mi sa che tutto quello che stai cercando è questo:

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

Se si utilizza WPF e MVVM ecco come si potrebbe fare usando 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> 

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 

} 
Problemi correlati