【问题标题】:How to display webcam images captured with Emgu?如何显示用 Emgu 拍摄的网络摄像头图像?
【发布时间】:2009-04-19 09:13:19
【问题描述】:

我目前正在开展一个使用面部识别的项目。 因此,我需要一种向用户显示网络摄像头图像的方法,以便他可以调整自己的脸。

我一直在尝试使用尽可能少的 CPU 从网络摄像头获取图像:

但是它们都不是很好...要么太慢要么太消耗 CPU 资源。

然后我尝试了Emgu library,感觉很棒。 起初,我在一个 Windows 窗体项目中进行了尝试,并在 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 但我没有让它们工作......

谢谢!

【问题讨论】:

    标签: c# wpf image webcam


    【解决方案1】:

    Image 类有一个你可能正在寻找的 UriSource 属性

    【讨论】:

      【解决方案2】:

      查看 Emgu wiki -> 教程 -> 示例 -> WPF (Windows Presentation Foundation) 它包含以下代码 sn-p 将您的 IImage 转换为 BitmapSource,您可以直接将其应用于您的控件。

      使用 Emgu.CV; 使用 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】:

        我想你要找的是这个:

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

        【讨论】:

          【解决方案4】:

          如果您使用的是 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>
          

          视图模型:

          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
          
          }
          

          【讨论】:

            【解决方案5】:

            我相信你必须使用互操作(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());
            }
            

            可以这样使用:

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

            如果互操作性能不够好,请查看Image.ToBitmapImage.get_Bitmap 的源代码,了解如何实现自己的WriteableBitmap

            【讨论】:

            • 是的,但是我需要做什么才能让我的“网络摄像头”图像控件显示图像?我试过: webcam.Source = frame.AsImageSource();但它没有显示任何东西......
            • 设置源就足够了。您可以尝试使用图像大小指定 Int32Rect 吗?
            • 我也有同样的问题!和 maging.CreateBitmapSourceFromHBitmap(image.Bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());导致 WPF 内存泄漏!
            【解决方案6】:
            【解决方案7】:

            试试这个。

            http://easywebcam.codeplex.com/

            我用过,非常棒..

            【讨论】:

              猜你喜欢
              • 2020-07-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-04-18
              • 1970-01-01
              • 1970-01-01
              • 2010-11-07
              • 2015-06-13
              相关资源
              最近更新 更多