2009-04-19 42 views
10

Tôi hiện đang làm việc trên một dự án sử dụng Nhận dạng khuôn mặt. Do đó, tôi cần một cách để hiển thị hình ảnh webcam cho người dùng để có thể điều chỉnh khuôn mặt của mình.Làm thế nào để hiển thị hình ảnh webcam được chụp với Emgu?

Tôi đã cố gắng rất nhiều thứ để có được hình ảnh từ webcam sử dụng như ít CPU càng tốt:

Nhưng không ai trong số chúng được sử dụng tốt ... Dù bằng cách nào quá chậm hoặc quá tiêu tốn tài nguyên CPU.

Sau đó, tôi đã thử các Emgu library và tôi cảm thấy tuyệt vời về nó. Lúc đầu, tôi đã thử nó trong một dự án Biểu mẫu Windows và đang cập nhật hình ảnh trong một Hộp Hình ảnh . Nhưng sau đó, khi tôi đã cố gắng để tích hợp nó trong dự án WPF của tôi, tôi đã bị mắc kẹt trên làm thế nào để vượt qua hình ảnh của tôi để kiểm soát hình ảnh của tôi ..

Ngay bây giờ, tôi đã mã nguồn sau đây:

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

Và mã sau:

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

tôi đoán là sử dụng BitmapSource/WriteableBitmap nhưng tôi đã không nhận được họ làm việc ...

Cảm ơn!

Trả lời

3

Hình ảnh lớp đã có một tài sản UriSource mà bạn có thể tìm kiếm

0

Tôi tin rằng bạn phải sử dụng interop (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()); 
} 

Mà có thể được sử dụng như thế này:

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

Nếu interop không hoạt động đủ tốt, hãy xem nguồn của Image.ToBitmapImage.get_Bitmap để xem cách bạn có thể triển khaicủa riêng mình.

+1

Yeah, nhưng những gì tôi cần phải làm gì để làm cho tôi "webcam" Điều khiển hình ảnh hiển thị hình ảnh? Tôi đã thử: webcam.Source = frame.AsImageSource(); Nhưng nó không hiển thị bất cứ điều gì ... – ZogStriP

+1

Đặt nguồn là đủ. Bạn có thể thử chỉ định một Int32Rect với kích thước của hình ảnh? – dahlbyk

+0

Tôi có cùng một vấn đề! Và maging.CreateBitmapSourceFromHBitmap (image.Bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); gây rò rỉ bộ nhớ trong WPF! – Evgeny

3

Nhìn vào wiki Emgu -> Hướng dẫn -> Ví dụ -> WPF (Windows Presentation Foundation) Nó chứa đoạn mã sau để chuyển đổi IImage của bạn thành một BitmapSource, bạn có thể áp dụng trực tiếp điều khiển của mình.

sử dụng Emgu.CV; bằng 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

Tôi nghĩ tất cả các bạn đang tìm kiếm là thế này:

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

Nếu bạn đang sử dụng WPF và MVVM đây là cách bạn sẽ làm điều đó bằng EMGU.

Xem:

<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 

} 
Các vấn đề liên quan